chore: add credential settings for agent in enrolling agent (#116)

* chore: add collection mode to cluster editing

* chore: add credential settings for agent when enroll agent

* chore: update release notes

---------

Co-authored-by: yaojiping <yaojiping@infini.ltd>
This commit is contained in:
yaojp123 2025-02-11 22:44:06 +08:00 committed by GitHub
parent 8762255322
commit d2a3ec0e7a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 669 additions and 41 deletions

View File

@ -19,6 +19,9 @@ Information about release notes of INFINI Console is provided here.
## 1.28.1 (2025-01-24)
- add credential settings for agent in enrolling agent
- add collection mode to cluster editing
### Features
- Support function-format parameters in Insight Data API

View File

@ -17,6 +17,9 @@ title: "版本历史"
### Improvements
- 在注册 Agent 中新增 Agent 凭据设置
- 在集群编辑中新增采集模式
## 1.28.1 (2025-01-24)
### Features

View File

@ -151,8 +151,11 @@ const Monitor = (props) => {
const breadcrumbList = getBreadcrumbList(state);
const isAgent = useMemo(() => {
const { monitor_configs = {} } = selectedCluster || {}
return monitor_configs?.node_stats?.enabled === false && monitor_configs?.index_stats?.enabled === false
const { metric_collection_mode, monitor_configs = {} } = selectedCluster || {}
if (typeof metric_collection_mode === 'undefined') {
return monitor_configs?.node_stats?.enabled === false && monitor_configs?.index_stats?.enabled === false
}
return metric_collection_mode === 'agent'
}, [JSON.stringify(selectedCluster?.monitor_configs)])
return (

View File

@ -6,7 +6,12 @@ export default {
"agent.instance.associate.labels.select_cluster": "Select Cluster",
"agent.instance.associate.tips.associate":
"Please select cluster(s) to enroll !",
"agent.instance.associate.set_credential": "Set credential for agent",
"agent.instance.associate.set_credential.tips":
"This permission will be used for metrics and log collection. It is recommended to use a user with a reasonable permission range.",
"agent.instance.associate.tips.connected": "Connection succeeded!",
"agent.instance.associate.tips.connected.check": "please set a credential for agent",
"agent.instance.associate.auth.error": "The following clusters need to set credentials for the agent:",
"agent.instance.associate.tips.metric":
"After enroll, the agent will collect metrics for the enrolled cluster",
"agent.instance.associate.tips.unregister":
@ -35,4 +40,7 @@ export default {
"agent.install.setup.copy.success": "Copied to clipboard successfully!",
"agent.instance.auto_associate.title": "Auto Enroll",
"agent.instance.install.title": "Install Agent",
"agent.label.agent_credential": "Agent Credential",
"agent.credential.tip": "No credential required",
};

View File

@ -207,6 +207,8 @@ export default {
"alert.rule.table.columnns.schedule": "Schedule",
"alert.rule.table.columnns.expression": "Expression",
"alert.rule.table.columnns.status": "Status",
"alert.rule.table.columnns.status.failed": "Connect failed",
"alert.rule.table.columnns.status.succeeded": "Connect succeeded",
"alert.rule.table.columnns.enabled": "Enabled",
"alert.rule.table.columnns.updated": "Updated time",
"alert.rule.table.columnns.category": "Category",

View File

@ -35,6 +35,7 @@ export default {
"cluster.manage.table.column.location": "Location",
"cluster.manage.monitored.on": "ON",
"cluster.manage.monitored.off": "OFF",
"cluster.manage.metric_collection_mode": "Collect Mode",
"cluster.manage.monitor_configs.cluster_health": "Cluster health",
"cluster.manage.monitor_configs.cluster_stats": "Cluster stats",
"cluster.manage.monitor_configs.node_stats": "Node stats",

View File

@ -5,7 +5,11 @@ export default {
"agent.instance.associate.labels.cluster_version": "版本",
"agent.instance.associate.labels.select_cluster": "关联到集群",
"agent.instance.associate.tips.associate": "请选择要关联的集群!",
"agent.instance.associate.set_credential": "为代理设置凭据",
"agent.instance.associate.set_credential.tips": "此权限将用于度量和日志收集。建议使用具有合理权限范围的用户。",
"agent.instance.associate.tips.connected": "连接成功!",
"agent.instance.associate.tips.connected.check": "请设置凭据",
"agent.instance.associate.auth.error": "以下集群需要为 Agent 设置凭据:",
"agent.instance.associate.tips.metric":
"关联后 Agent 会对关联的集群进行指标采集操作",
"agent.instance.associate.tips.unregister":
@ -33,4 +37,7 @@ export default {
"agent.install.setup.copy.success": "已成功复制到剪贴板!",
"agent.instance.auto_associate.title": "自动关联集群",
"agent.instance.install.title": "安装 Agent",
"agent.label.agent_credential": "代理凭据",
"agent.credential.tip": "不需要凭据",
};

View File

@ -195,6 +195,8 @@ export default {
"alert.rule.table.columnns.schedule": "计划周期",
"alert.rule.table.columnns.expression": "告警规则",
"alert.rule.table.columnns.status": "运行状态",
"alert.rule.table.columnns.status.failed": "连接失败",
"alert.rule.table.columnns.status.succeeded": "连接成功",
"alert.rule.table.columnns.enabled": "告警启停",
"alert.rule.table.columnns.updated": "更新时间",
"alert.rule.table.columnns.category": "分类",

View File

@ -35,6 +35,7 @@ export default {
"cluster.manage.table.column.location": "位置",
"cluster.manage.monitored.on": "启用",
"cluster.manage.monitored.off": "关闭",
"cluster.manage.metric_collection_mode": "采集模式",
"cluster.manage.monitor_configs.cluster_health": "集群健康状态指标",
"cluster.manage.monitor_configs.cluster_stats": "集群指标",
"cluster.manage.monitor_configs.node_stats": "节点指标",

View File

@ -0,0 +1,117 @@
import { Alert, Button, Form, message } from "antd";
import { useState } from "react";
import { formatMessage } from "umi/locale";
import request from "@/utils/request";
import AgentCredentialForm, { MANUAL_VALUE } from "./AgentCredentialForm";
import { ESPrefix } from "@/services/common";
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 18 },
},
};
export default Form.create()((props) => {
const { form, record, loading, tryConnect, onAgentCredentialSave } = props;
const [isManual, setIsManual] = useState(false);
const [saveLoading, setSaveLoading] = useState(false);
const needAuth = !!(record.credential_id || record.basic_auth?.username);
const onConfirm = async () => {
form.validateFields(async (errors, values) => {
if (errors) return;
setSaveLoading(true);
const { credential_id, basic_auth, metric_collection_mode } = record;
const res = await request(`${ESPrefix}/${record.id}`, {
method: "PUT",
body: {
credential_id,
basic_auth,
metric_collection_mode,
agent_credential_id:
values.agent_credential_id !== MANUAL_VALUE
? values.agent_credential_id
: undefined,
agent_basic_auth: {
username: values.agent_username,
password: values.agent_password,
},
},
});
if (res?.result === "updated") {
message.success(
formatMessage({
id: "app.message.update.success",
})
);
const res = await request(`/elasticsearch/${record.id}`);
if (res?.found) {
onAgentCredentialSave(res._source);
if (res._source?.agent_credential_id) {
setIsManual(false);
}
form.setFieldsValue({
agent_credential_id: res._source?.agent_credential_id
? res._source?.agent_credential_id
: res._source?.agent_basic_auth?.username
? MANUAL_VALUE
: undefined,
agent_username: res._source.agent_basic_auth?.username,
agent_password: res._source.agent_basic_auth?.password,
});
}
} else {
message.error(
formatMessage({
id: "app.message.update.failed",
})
);
}
setSaveLoading(false);
});
};
if (!needAuth) {
return (
<Alert
message={formatMessage({ id: "agent.credential.tip" })}
type="success"
/>
);
}
return (
<Form {...formItemLayout} colon={false}>
<AgentCredentialForm
btnLoading={loading}
needAuth={needAuth}
form={form}
initialValue={{
...record,
username: record.agent_basic_auth?.username,
password: record.agent_basic_auth?.password,
}}
isManual={isManual}
setIsManual={setIsManual}
isEdit={true}
tryConnect={tryConnect}
credentialRequired={false}
/>
<Form.Item label=" " colon={false}>
<div style={{ textAlign: "right" }}>
<Button loading={loading} type="primary" onClick={() => onConfirm()}>
{formatMessage({ id: "cluster.regist.step.confirm.title" })}
</Button>
</div>
</Form.Item>
</Form>
);
});

View File

@ -0,0 +1,143 @@
import React, { useEffect, useMemo, useState } from "react";
import { Button, Divider, Form, Input, Select, Row, Col } from "antd";
import { formatMessage } from "umi/locale";
import useFetch from "@/lib/hooks/use_fetch";
import { formatESSearchResult } from "@/lib/elasticsearch/util";
export const MANUAL_VALUE = "manual";
export default (props) => {
const {
btnLoading = false,
needAuth,
form: { getFieldDecorator },
initialValue,
isEdit,
tryConnect,
credentialRequired = false,
isManual,
setIsManual,
} = props;
const { loading, error, value, run } = useFetch(
"/credential/_search",
{
queryParams: {
from: 0,
size: 1000,
},
},
[]
);
const onCredentialChange = (value) => {
if (value === "manual") {
setIsManual(true);
} else {
setIsManual(false);
}
};
const { data, total } = useMemo(() => {
return formatESSearchResult(value);
}, [value]);
if (!needAuth) {
return null;
}
return (
<>
<Form.Item
label={formatMessage({
id: "cluster.regist.step.connect.label.agent_credential",
})}
>
{getFieldDecorator("agent_credential_id", {
initialValue: initialValue?.agent_credential_id
? initialValue?.agent_credential_id
: initialValue?.username
? MANUAL_VALUE
: undefined,
rules: [
{
required: credentialRequired,
message: formatMessage({
id: "cluster.regist.form.verify.required.agent_credential",
}),
},
],
})(
<Select loading={loading} onChange={onCredentialChange} allowClear>
<Select.Option value={MANUAL_VALUE}>
{formatMessage({
id: "cluster.regist.step.connect.credential.manual",
})}
</Select.Option>
{data.map((item) => (
<Select.Option value={item.id}>{item.name}</Select.Option>
))}
</Select>
)}
</Form.Item>
{isManual && (
<>
<Form.Item
label={formatMessage({
id: "cluster.regist.step.connect.label.username",
})}
>
{getFieldDecorator("agent_username", {
initialValue: initialValue?.username || "",
rules: [
{
required: credentialRequired,
message: formatMessage({
id: "cluster.regist.form.verify.required.auth_username",
}),
},
],
})(<Input autoComplete="off" placeholder={formatMessage({id: "agent.form.placeholder.auth.username"})} />)}
</Form.Item>
<Form.Item
label={formatMessage({
id: "cluster.regist.step.connect.label.password",
})}
hasFeedback
>
{getFieldDecorator("agent_password", {
initialValue: initialValue?.password || "",
rules: [
{
required: credentialRequired,
message: formatMessage({
id: "cluster.regist.form.verify.required.auth_password",
}),
},
],
})(
<Input.Password
autoComplete="off"
placeholder={formatMessage({
id: "cluster.regist.form.verify.required.auth_password",
})}
/>
)}
</Form.Item>
{isEdit && (
<>
<Form.Item label={" "}>
<div style={{ lineHeight: "20px" }}>
{formatMessage({
id: "cluster.regist.form.credential.manual.desc",
})}
</div>
</Form.Item>
</>
)}
</>
)}
</>
);
};

View File

@ -1,22 +1,36 @@
import { useGlobal } from "@/layouts/GlobalContext";
import request from "@/utils/request";
import { Form, Input, Switch, Icon, Button, Select } from "antd";
import { useMemo, useRef, useState } from "react";
import { Form, Input, Switch, Icon, Button, Select, Alert } from "antd";
import { useEffect, useMemo, useRef, useState } from "react";
import { Link, router } from "umi";
import { formatMessage } from "umi/locale";
import ClusterSelect from "@/components/ClusterSelect";
import SetAgentCredential from "./SetAgentCredential";
export default ({ onEnroll, loading }) => {
const { clusterList = [], clusterStatus } = useGlobal();
const [selectedCluster, setSelectedCluster] = useState([]);
const [auths, setAuths] = useState([]);
const onEnrollClick = () => {
if (typeof onEnroll === "function") {
if (selectedCluster.length === 0) return;
const newAuths = [...auths]
selectedCluster.forEach((item) => {
if (item.credential_id && !item.agent_credential_id) {
newAuths.push(item)
}
})
setAuths(newAuths)
if (newAuths.length === 0 && typeof onEnroll === "function") {
onEnroll(selectedCluster.map((item) => item.id));
}
};
useEffect(() => {
setAuths([])
}, [JSON.stringify(selectedCluster)])
return (
<div>
<div
@ -37,6 +51,27 @@ export default ({ onEnroll, loading }) => {
}}
/>
</div>
<SetAgentCredential selectedCluster={selectedCluster} setSelectedCluster={setSelectedCluster}/>
{
auths.length > 0 && (
<Alert style={{ marginTop: 10 }} type="error" message={(
<div>
<div>
{formatMessage({
id: "agent.instance.associate.auth.error",
})}
</div>
<div>
{ auths.map((item) => (
<div key={item.id}>
- {item.name}
</div>
)) }
</div>
</div>
)}/>
)
}
<div style={{ marginTop: 10, textAlign: "right" }}>
<div style={{ marginBottom: 15, color: "rgba(130,129,136,1)" }}>
<span>

View File

@ -228,7 +228,7 @@ export const AgentRowDetail = ({ agentID, t }) => {
})
}
>
<Button type="link" loading={btnLoading}>
<Button style={{padding: 0}} type="link" loading={btnLoading}>
Revoke
</Button>
</Popconfirm>

View File

@ -0,0 +1,174 @@
import request from "@/utils/request";
import { message, Table, Tooltip, Spin } from "antd";
import { useState } from "react";
import { formatMessage } from "umi/locale";
import { MANUAL_VALUE } from "./AgentCredentialForm";
import styles from "./SetAgentCredential.less";
import AgentCredential from "./AgentCredential";
import { ESPrefix } from "@/services/common";
import { cloneDeep } from "lodash";
import { connect } from "dva";
export default connect()((props) => {
const { selectedCluster, setSelectedCluster, dispatch } = props
const [status, setStatus] = useState({});
const [testLoading, setTestLoading] = useState(false);
const onAgentCredentialSave = async (values) => {
const newSelectedCluster = cloneDeep(selectedCluster);
const index = newSelectedCluster.findIndex((item) => item.id === values.id);
if (index !== -1) {
newSelectedCluster[index] = values;
setSelectedCluster(newSelectedCluster);
}
dispatch({
type: "global/fetchClusterList",
payload: {
size: 200,
name: "",
},
});
dispatch({
type: "global/fetchClusterStatus",
})
};
const expandedRowRender = (record) => {
return (
<AgentCredential
record={record}
onAgentCredentialSave={(values) => onAgentCredentialSave(values)}
/>
);
};
const tryConnect = async (values) => {
setTestLoading(true);
const body = {
basic_auth: {
username: values.agent_basic_auth?.username,
password: values.agent_basic_auth?.password,
},
host: values.host,
credential_id:
values.agent_credential_id !== MANUAL_VALUE
? values.agent_credential_id
: undefined,
schema: values.schema || "http",
};
if (
values.credential_id &&
!body.credential_id &&
(!body.basic_auth.username || !body.basic_auth.password)
) {
message.warning(formatMessage({ id: "agent.instance.associate.tips.connected.check" }));
setTestLoading(false);
return;
}
const res = await request(`${ESPrefix}/try_connect`, {
method: "POST",
body,
showErrorInner: true,
}, false, false);
setStatus({
...status,
[values.id]: {
status: res?.status,
error: res?.error,
},
});
setTestLoading(false);
};
return (
<>
<div style={{ marginTop: 32 }}>
<div
style={{
fontSize: 16,
color: "rgba(16, 16, 16, 1)",
fontWeight: 600,
marginBottom: 8,
}}
>
{formatMessage({ id: "agent.instance.associate.set_credential" })}
</div>
<div>{formatMessage({ id: "agent.instance.associate.set_credential.tips" })}</div>
</div>
<div style={{ marginTop: 15 }}>
<Table
size="small"
rowKey={"id"}
dataSource={selectedCluster || []}
className={styles.table}
columns={[
{
title: formatMessage({
id: "agent.instance.associate.labels.cluster_name",
}),
dataIndex: "name",
key: "name",
},
{
title: formatMessage({ id: "guide.cluster.auth" }),
dataIndex: "credential_id",
key: "credential_id",
render: (text, record) => {
return record.credential_id || record.basic_auth?.username
? formatMessage({
id: "cluster.regist.step.complete.tls.yes",
})
: formatMessage({
id: "cluster.regist.step.complete.tls.no",
});
},
},
{
title: formatMessage({ id: "agent.label.agent_credential" }),
dataIndex: "agent_credential_id",
key: "agent_credential_id",
render: (text, record) => {
return record.agent_credential_id ? "Set" : "No set";
},
},
{
title: formatMessage({ id: "alert.rule.table.columnns.status" }),
dataIndex: "status",
key: "Status",
render: (text, record) => {
if (!status[record.id]) return "-";
if (status[record.id].error) {
return (
<Tooltip title={status[record.id].error}>
<span style={{ color: "red" }}>{formatMessage({ id: "alert.rule.table.columnns.status.failed"})}</span>
</Tooltip>
);
}
return (
<span style={{ color: "green" }}>{formatMessage({ id: "alert.rule.table.columnns.status.succeeded"})}</span>
);
},
},
{
title: formatMessage({ id: "table.field.actions" }),
dataIndex: "",
key: "",
render: (record) =>
testLoading ? (
<Spin />
) : (
<a onClick={() => tryConnect(record)}>
{formatMessage({ id: "guide.cluster.test.connection" })}
</a>
),
},
]}
expandedRowRender={expandedRowRender}
/>
</div>
</>
);
});

View File

@ -0,0 +1,7 @@
.table {
:global {
tr.ant-table-expanded-row, tr.ant-table-expanded-row:hover {
background: #fff;
}
}
}

View File

@ -1,22 +1,35 @@
import { useGlobal } from "@/layouts/GlobalContext";
import request from "@/utils/request";
import { Form, Input, Switch, Icon, Button, Select } from "antd";
import { useMemo, useRef, useState } from "react";
import { Form, Input, Switch, Icon, Button, Alert } from "antd";
import { useEffect, useMemo, useRef, useState } from "react";
import { Link, router } from "umi";
import { formatMessage } from "umi/locale";
import ClusterSelect from "@/components/ClusterSelect";
import SetAgentCredential from "./SetAgentCredential";
export default ({ onBatchEnroll, loading }) => {
const { clusterList = [], clusterStatus } = useGlobal();
const [selectedCluster, setSelectedCluster] = useState([]);
const [auths, setAuths] = useState([]);
const onBatchEnrollClick = () => {
if (typeof onBatchEnroll === "function") {
if (selectedCluster.length === 0) return;
const newAuths = [...auths]
selectedCluster.forEach((item) => {
if (item.credential_id && !item.agent_credential_id) {
newAuths.push(item)
}
})
setAuths(newAuths)
if (newAuths.length === 0 && typeof onBatchEnroll === "function") {
onBatchEnroll(selectedCluster.map((item) => item.id));
}
};
useEffect(() => {
setAuths([])
}, [JSON.stringify(selectedCluster)])
return (
<div>
<div
@ -38,6 +51,27 @@ export default ({ onBatchEnroll, loading }) => {
}}
/>
</div>
<SetAgentCredential selectedCluster={selectedCluster} setSelectedCluster={setSelectedCluster}/>
{
auths.length > 0 && (
<Alert style={{ marginTop: 10 }} type="error" message={(
<div>
<div>
{formatMessage({
id: "agent.instance.associate.auth.error",
})}
</div>
<div>
{ auths.map((item) => (
<div key={item.id}>
- {item.name}
</div>
)) }
</div>
</div>
)}/>
)
}
<div style={{ marginTop: 10, textAlign: "right" }}>
<div style={{ marginBottom: 15, color: "rgba(130,129,136,1)" }}>
<span>

View File

@ -0,0 +1,7 @@
.table {
:global {
tr.ant-table-expanded-row, tr.ant-table-expanded-row:hover {
background: #fff;
}
}
}

View File

@ -0,0 +1,48 @@
import { Form, Radio } from "antd";
import { useEffect, useState } from "react";
import { formatMessage } from "umi/locale";
import styles from "./CollectMode.less";
export default (props) => {
const { editValue, form, onChange } = props;
const { getFieldDecorator } = form;
const [mode, setMode] = useState(
editValue?.metric_collection_mode || "agentless"
);
useEffect(() => {
const monitor_configs = form.getFieldValue("monitor_configs");
if (mode === "agent") {
monitor_configs["node_stats"] = { enabled: false };
monitor_configs["index_stats"] = { enabled: false };
} else {
monitor_configs["node_stats"] = { enabled: true };
monitor_configs["index_stats"] = { enabled: true };
}
form.setFieldsValue({ monitor_configs });
}, [mode]);
return (
<>
<Form.Item
label={formatMessage({ id: "cluster.manage.metric_collection_mode" })}
>
{getFieldDecorator(`metric_collection_mode`, {
initialValue: mode,
})(
<Radio.Group
className={styles.mode}
onChange={(e) => {
setMode(e.target.value)
onChange(e.target.value)
}}
>
<Radio.Button value="agentless">Agentless</Radio.Button>
<Radio.Button value="agent">Agent</Radio.Button>
</Radio.Group>
)}
</Form.Item>
</>
);
};

View File

@ -0,0 +1,8 @@
.mode {
:global {
.ant-radio-button-wrapper {
margin-right: 12px;
border-radius: 4px;
}
}
}

View File

@ -27,6 +27,7 @@ import { MANUAL_VALUE } from "./steps";
import SearchEngines from "./components/SearchEngines";
import Providers from "./components/Providers";
import TrimSpaceInput from "@/components/TrimSpaceInput";
import CollectMode from "./CollectMode";
const InputGroup = Input.Group;
@Form.create()
@ -51,7 +52,7 @@ class ClusterForm extends React.Component {
validateFieldNames = [
"name",
"host",
"hosts",
"isTLS",
"credential_id",
"username",
@ -59,7 +60,7 @@ class ClusterForm extends React.Component {
];
agentValidateFieldNames = [
"name",
"host",
"hosts",
"isTLS",
"agent_credential_id",
"agent_username",
@ -70,6 +71,7 @@ class ClusterForm extends React.Component {
//console.log(this.props.clusterConfig.editMode)
const { match, dispatch, clusterConfig } = this.props;
if (clusterConfig?.editValue) {
this.setState({
monitored: clusterConfig?.editValue.hasOwnProperty("monitored")
? clusterConfig?.editValue?.monitored
@ -98,9 +100,14 @@ class ClusterForm extends React.Component {
isManual = true;
}
}
let collectMode = editValue?.metric_collection_mode || 'agentless'
if (typeof editValue?.metric_collection_mode === 'undefined' && editValue?.monitor_configs?.node_stats?.enabled === false && editValue?.monitor_configs?.index_stats?.enabled === false) {
collectMode = 'agent'
}
this.setState({
needAuth,
isManual,
collectMode
});
}
});
@ -154,6 +161,7 @@ class ClusterForm extends React.Component {
}
const monitor_configs_new = formatConfigsValues(values.monitor_configs);
const metadata_configs_new = formatConfigsValues(values.metadata_configs);
const isAgentMode = values.metric_collection_mode === "agent";
let newVals = {
name: values.name,
@ -169,13 +177,14 @@ class ClusterForm extends React.Component {
},
agent_credential_id:
values.agent_credential_id !== MANUAL_VALUE
values.agent_credential_id !== MANUAL_VALUE && isAgentMode
? values.agent_credential_id
: undefined,
agent_basic_auth: {
: agent_credential_id,
agent_basic_auth: isAgentMode ? {
username: values.agent_username,
password: values.agent_password,
},
} : agent_basic_auth,
metric_collection_mode: values.metric_collection_mode || 'agentless',
description: values.description,
enabled: values.enabled,
@ -267,9 +276,10 @@ class ClusterForm extends React.Component {
if (!values) {
return;
}
debugger
let newVals = {
name: values.name,
host: values.host,
hosts: values.hosts,
schema: values.isTLS === true ? "https" : "http",
};
@ -417,6 +427,15 @@ class ClusterForm extends React.Component {
],
})(<Input autoComplete="off" placeholder="Cluster name" />)}
</Form.Item>
<Form.Item
label={formatMessage({
id: "cluster.manage.table.column.description",
})}
>
{getFieldDecorator("description", {
initialValue: editValue.description,
})(<Input.TextArea placeholder="Cluster Descirption" />)}
</Form.Item>
<Form.Item
label={formatMessage({
id: "cluster.manage.label.distribution",
@ -508,35 +527,12 @@ class ClusterForm extends React.Component {
tryConnect={this.tryConnect}
credentialRequired={this.state.credentialRequired}
/>
<AgentCredentialForm
btnLoading={this.state.btnLoadingAgent}
needAuth={this.state.needAuth}
form={this.props.form}
initialValue={{
...editValue,
username: editValue.agent_basic_auth?.username,
password: editValue.agent_basic_auth?.password,
}}
isManual={this.state.isManual}
isEdit={true}
tryConnect={this.tryConnect}
credentialRequired={this.state.agentCredentialRequired}
/>
{/* <Form.Item label="">
{getFieldDecorator('order', {
initialValue: editValue.order || 0,
})(<InputNumber />)}
</Form.Item> */}
<Form.Item
label={formatMessage({
id: "cluster.manage.table.column.description",
})}
>
{getFieldDecorator("description", {
initialValue: editValue.description,
})(<Input.TextArea placeholder="Cluster Descirption" />)}
</Form.Item>
{/* <Form.Item label="">
{getFieldDecorator('enabled', {
valuePropName: 'checked',
@ -581,10 +577,36 @@ class ClusterForm extends React.Component {
/>
)}
</Form.Item>
<CollectMode
form={this.props.form}
editValue={editValue}
onChange={(mode) => {
this.setState({ collectMode: mode })
}}
/>
{
this.state.collectMode === 'agent' && (
<AgentCredentialForm
btnLoading={this.state.btnLoadingAgent}
needAuth={this.state.needAuth}
form={this.props.form}
initialValue={{
...editValue,
username: editValue.agent_basic_auth?.username,
password: editValue.agent_basic_auth?.password,
}}
isManual={this.state.isManual}
isEdit={true}
tryConnect={this.tryConnect}
credentialRequired={this.state.agentCredentialRequired}
/>
)
}
<MonitorConfigsForm
form={this.props.form}
editValue={editValue}
visible={this.state.monitored}
collectMode={this.state.collectMode}
/>
<MetadataConfigsForm
form={this.props.form}

View File

@ -24,7 +24,10 @@ const MonitorConfigsForm = (props) => {
display: props.visible ? "block" : "none",
}}
>
{configs.map((item) => {
{configs.filter((item) => {
if (props.collectMode !== "agent") return true;
return !["node_stats", "index_stats"].includes(item.key);
}).map((item) => {
return (
<Form.Item
key={item.key}