From a3ef55300aa968210b560e430ce8d89e9f9cb04d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cdorac-ext=E2=80=9D?= <103416234+doracretu3pillar@users.noreply.github.com> Date: Wed, 24 Jul 2024 12:06:13 +0300 Subject: [PATCH 01/30] Nodes for MySQLConnection --- .../AddRemoteInstance.service.tsx | 58 ++++++++++++++ .../AddRemoteInstance/AddRemoteInstance.tsx | 3 + .../AddRemoteInstance.types.ts | 2 + .../FormParts/FormParts.styles.tsx | 6 ++ .../MySQLConnectionDetails.tsx | 75 ++++++++++++++++++- .../app/percona/add-instance/panel.types.ts | 2 + .../app/percona/inventory/Inventory.types.ts | 13 +++- .../shared/core/reducers/nodes/nodes.ts | 13 +++- .../shared/core/reducers/nodes/nodes.utils.ts | 24 +++++- 9 files changed, 191 insertions(+), 5 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx index 01b755575a7fb..0d43c0a09a597 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx @@ -30,6 +30,64 @@ import { const BASE_URL = '/services'; class AddRemoteInstanceService { + /* +* { + "node_id": "string", + "node_name": "string", + "add_node": { + "node_type": "NODE_TYPE_INVALID", + "node_name": "string", + "machine_id": "string", + "distro": "string", + "container_id": "string", + "container_name": "string", + "node_model": "string", + "region": "string", + "az": "string", + "custom_labels": { + "additionalProp1": "string", + "additionalProp2": "string", + "additionalProp3": "string" + } + }, + "service_name": "string", + "address": "string", + "port": 0, + "socket": "string", + "pmm_agent_id": "string", + "environment": "string", + "cluster": "string", + "replication_set": "string", + "username": "string", + "password": "string", + "qan_mysql_perfschema": true, + "qan_mysql_slowlog": true, + "custom_labels": { + "additionalProp1": "string", + "additionalProp2": "string", + "additionalProp3": "string" + }, + "skip_connection_check": true, + "disable_comments_parsing": true, + "max_query_length": 0, + "disable_query_examples": true, + "max_slowlog_file_size": "string", + "tls": true, + "tls_skip_verify": true, + "tls_ca": "string", + "tls_cert": "string", + "tls_key": "string", + "tablestats_group_table_limit": 0, + "metrics_mode": "AUTO", + "disable_collectors": [ + "string" + ], + "agent_password": "string", + "log_level": "auto", + "expose_exporter": true +} +* +* */ static async addMysql(body: MySQLPayload, token?: CancelToken) { return apiManagement.post( BASE_URL, diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tsx index b6c3877a734e3..6c33990833383 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tsx @@ -53,6 +53,8 @@ const AddRemoteInstance: FC = ({ if (type === Databases.mysql) { initialValues.qan_mysql_perfschema = true; initialValues.disable_comments_parsing = true; + initialValues.node = ""; + initialValues.agent = ""; } if (type === Databases.postgresql) { @@ -65,6 +67,7 @@ const AddRemoteInstance: FC = ({ const onSubmit = useCallback( async (values: FormValues) => { + console.log('----Submit---', values); try { setLoading(true); if (values.isRDS) { diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.types.ts b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.types.ts index 61785c8f1105b..c26394e34d728 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.types.ts +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.types.ts @@ -127,6 +127,8 @@ export interface MySQLPayload extends RemoteCommonPayload, TLSCommon { tls_key: string; tls_ca: string; max_query_length: number; + node?: string; + agent?: string; } export interface MongoDBPayload extends RemoteCommonPayload, TLSCommon { diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.styles.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.styles.tsx index d62ed18323f3e..556d80657e9d4 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.styles.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.styles.tsx @@ -32,6 +32,12 @@ export const getStyles = ({ breakpoints, spacing, colors }: GrafanaTheme2) => ({ width: 100%; margin-right: 5px; `, + selectFieldWrapper: css` + width: 100%; + `, + selectField: css` + height: 38px; + `, group: css` display: flex; flex-direction: row; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx index 1c6ea246b0374..25794a6ace003 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx @@ -1,10 +1,18 @@ -import React, { FC, useMemo } from 'react'; +import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { useStyles2 } from '@grafana/ui'; +import { GET_NODES_CANCEL_TOKEN } from "app/percona/inventory/Inventory.constants"; +import { AgentsOptions, NodesOptions } from "app/percona/inventory/Inventory.types"; import { PasswordInputField } from 'app/percona/shared/components/Form/PasswordInput'; +import { SelectField } from "app/percona/shared/components/Form/SelectFieldCore"; import { TextInputField } from 'app/percona/shared/components/Form/TextInput'; +import { useCancelToken } from "app/percona/shared/components/hooks/cancelToken.hook"; +import { fetchNodesOptionsAction } from "app/percona/shared/core/reducers/nodes/nodes"; +import { isApiCancelError } from "app/percona/shared/helpers/api"; +import { logger } from "app/percona/shared/helpers/logger"; import Validators from 'app/percona/shared/helpers/validators'; import { validators } from 'app/percona/shared/helpers/validatorsForm'; +import { useAppDispatch } from "app/store/store"; import { Messages } from '../FormParts.messages'; import { getStyles } from '../FormParts.styles'; @@ -14,11 +22,48 @@ export const MySQLConnectionDetails: FC = ({ form, rem const styles = useStyles2(getStyles); const formValues = form && form.getState().values; const tlsFlag = formValues && formValues['tls']; + const dispatch = useAppDispatch(); + const [generateToken] = useCancelToken(); + const [selectedNode, setSelectedNode] = useState(undefined); + const [selectedAgent, setSelectedAgent] = useState(undefined); + const [nodes, setNodes] = useState([]); + + const loadData = useCallback(async () => { + try { + setNodes(await dispatch(fetchNodesOptionsAction({ token: generateToken(GET_NODES_CANCEL_TOKEN) })).unwrap()); + } catch (e) { + if (isApiCancelError(e)) { + return; + } + logger.error(e); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + if(nodes.length === 0) { + loadData(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [nodes]); const portValidators = useMemo(() => [validators.required, Validators.validatePort], []); const userPassValidators = useMemo(() => (tlsFlag ? [] : [validators.required]), [tlsFlag]); const maxQueryLengthValidators = useMemo(() => [Validators.min(-1)], []); + const setNodeAndAgent = (value: NodesOptions) => { + setSelectedNode(value); + if (value.agents && value.agents.length > 1) { + form?.change('agent', value.agents[1]); + } else if (value.agents && value.agents.length === 1) { + form?.change('agent', value.agents[0]); + } + + if(selectedAgent && selectedAgent.value !== "pmm-server") { + form?.change('address', 'localhost'); + } + } + return (

{Messages.form.titles.mainDetails}

@@ -32,6 +77,34 @@ export const MySQLConnectionDetails: FC = ({ form, rem />
+
+
+ { setNodeAndAgent(event as NodesOptions) }} + className={styles.selectField} + value={selectedNode} + /> +
+
+ { setSelectedAgent(event as AgentsOptions); }} + className={styles.selectField} + /> +
+
+
( + 'percona/fetchNodesOptions', + async (params = {}) => { + const { nodes } = await InventoryService.getNodes(params.token); + + return nodesOptionsMapper(nodes); + } +); + export const removeNodesAction = createAsyncThunk( 'percona/removeNodes', async (params: RemoveNodesParams): Promise => { diff --git a/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts b/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts index 3b7193cd27adf..cfe19f4df96ec 100644 --- a/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts +++ b/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions */ -import { Node, NodeDB } from 'app/percona/inventory/Inventory.types'; +import { AgentsOptions, AgentType, Node, NodeDB, NodesOptions } from 'app/percona/inventory/Inventory.types'; import { getAgentsMonitoringStatus } from 'app/percona/inventory/Tabs/Services.utils'; import { DbAgent } from 'app/percona/shared/services/services/Services.types'; @@ -54,3 +54,25 @@ export const nodeFromDbMapper = (nodeFromDb: NodeDB[]) => { } as Node; }); }; + +export const nodesOptionsMapper = (nodeFromDb: NodeDB[]) => { + return nodeFromDb.map((node) => { + + const agents = node.agents?.map( + (agent) => { + if (agent.agent_type === AgentType.pmmAgent) { + return { + value: agent.agent_id, + label: agent.agent_type + } as AgentsOptions; + } else { return null; } + } + ).filter(agent => agent !== null) as AgentsOptions[]; + + return { + value: node.node_id, + label: node.node_name, + agents: agents, + } as NodesOptions; + }); +} From a0353acc76cb6db8c03598c6a50138a2d10d2b55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cdorac-ext=E2=80=9D?= <103416234+doracretu3pillar@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:13:53 +0300 Subject: [PATCH 02/30] Added Nodes Agents component --- .../MySQLConnectionDetails.tsx | 79 +--------------- .../FormParts/NodesAgents/NodesAgents.tsx | 89 +++++++++++++++++++ .../PostgreSQLConnectionDetails.tsx | 2 + 3 files changed, 95 insertions(+), 75 deletions(-) create mode 100644 public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx index 25794a6ace003..20605e9ca9c5e 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx @@ -1,69 +1,25 @@ -import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; +import React, { FC, useMemo } from 'react'; import { useStyles2 } from '@grafana/ui'; -import { GET_NODES_CANCEL_TOKEN } from "app/percona/inventory/Inventory.constants"; -import { AgentsOptions, NodesOptions } from "app/percona/inventory/Inventory.types"; -import { PasswordInputField } from 'app/percona/shared/components/Form/PasswordInput'; -import { SelectField } from "app/percona/shared/components/Form/SelectFieldCore"; +import { PasswordInputField } from 'app/percona/shared/components/Form/PasswordInput' import { TextInputField } from 'app/percona/shared/components/Form/TextInput'; -import { useCancelToken } from "app/percona/shared/components/hooks/cancelToken.hook"; -import { fetchNodesOptionsAction } from "app/percona/shared/core/reducers/nodes/nodes"; -import { isApiCancelError } from "app/percona/shared/helpers/api"; -import { logger } from "app/percona/shared/helpers/logger"; import Validators from 'app/percona/shared/helpers/validators'; import { validators } from 'app/percona/shared/helpers/validatorsForm'; -import { useAppDispatch } from "app/store/store"; import { Messages } from '../FormParts.messages'; import { getStyles } from '../FormParts.styles'; import { MainDetailsFormPartProps } from '../FormParts.types'; +import { NodesAgents } from "../NodesAgents/NodesAgents"; export const MySQLConnectionDetails: FC = ({ form, remoteInstanceCredentials }) => { const styles = useStyles2(getStyles); const formValues = form && form.getState().values; const tlsFlag = formValues && formValues['tls']; - const dispatch = useAppDispatch(); - const [generateToken] = useCancelToken(); - const [selectedNode, setSelectedNode] = useState(undefined); - const [selectedAgent, setSelectedAgent] = useState(undefined); - const [nodes, setNodes] = useState([]); - - const loadData = useCallback(async () => { - try { - setNodes(await dispatch(fetchNodesOptionsAction({ token: generateToken(GET_NODES_CANCEL_TOKEN) })).unwrap()); - } catch (e) { - if (isApiCancelError(e)) { - return; - } - logger.error(e); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - useEffect(() => { - if(nodes.length === 0) { - loadData(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [nodes]); const portValidators = useMemo(() => [validators.required, Validators.validatePort], []); const userPassValidators = useMemo(() => (tlsFlag ? [] : [validators.required]), [tlsFlag]); const maxQueryLengthValidators = useMemo(() => [Validators.min(-1)], []); - const setNodeAndAgent = (value: NodesOptions) => { - setSelectedNode(value); - if (value.agents && value.agents.length > 1) { - form?.change('agent', value.agents[1]); - } else if (value.agents && value.agents.length === 1) { - form?.change('agent', value.agents[0]); - } - - if(selectedAgent && selectedAgent.value !== "pmm-server") { - form?.change('address', 'localhost'); - } - } - return (

{Messages.form.titles.mainDetails}

@@ -77,34 +33,7 @@ export const MySQLConnectionDetails: FC = ({ form, rem />
-
-
- { setNodeAndAgent(event as NodesOptions) }} - className={styles.selectField} - value={selectedNode} - /> -
-
- { setSelectedAgent(event as AgentsOptions); }} - className={styles.selectField} - /> -
-
- +
= ({ form }) => { + const styles = useStyles2(getStyles); + const dispatch = useAppDispatch(); + const [generateToken] = useCancelToken(); + const [selectedNode, setSelectedNode] = useState(undefined); + const [selectedAgent, setSelectedAgent] = useState(undefined); + const [nodes, setNodes] = useState([]); + + const loadData = useCallback(async () => { + try { + setNodes(await dispatch(fetchNodesOptionsAction({ token: generateToken(GET_NODES_CANCEL_TOKEN) })).unwrap()); + } catch (e) { + if (isApiCancelError(e)) { + return; + } + logger.error(e); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const setNodeAndAgent = (value: NodesOptions) => { + setSelectedNode(value); + if (value.agents && value.agents.length > 1) { + form?.change('agent', value.agents[1]); + } else if (value.agents && value.agents.length === 1) { + form?.change('agent', value.agents[0]); + } + + if(selectedAgent && selectedAgent.value !== "pmm-server") { + form?.change('address', 'localhost'); + } + } + + useEffect(() => { + if(nodes.length === 0) { + loadData(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [nodes]); + + return ( +
+
+ { setNodeAndAgent(event as NodesOptions) }} + className={styles.selectField} + value={selectedNode} + /> +
+
+ { setSelectedAgent(event as AgentsOptions); }} + className={styles.selectField} + /> +
+
+ ); + +} diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.tsx index 1ae6fbc86512d..6eb1dd7e82e0b 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.tsx @@ -9,6 +9,7 @@ import { validators } from 'app/percona/shared/helpers/validatorsForm'; import { Messages } from '../FormParts.messages'; import { getStyles } from '../FormParts.styles'; import { MainDetailsFormPartProps } from '../FormParts.types'; +import { NodesAgents } from "../NodesAgents/NodesAgents"; export const PostgreSQLConnectionDetails: FC = ({ form, remoteInstanceCredentials }) => { const styles = useStyles2(getStyles); @@ -31,6 +32,7 @@ export const PostgreSQLConnectionDetails: FC = ({ form />
+
Date: Mon, 29 Jul 2024 11:44:54 +0300 Subject: [PATCH 03/30] Added pmm_agent_id parameter instead of agent/node --- .../AddRemoteInstance.service.tsx | 61 +------------------ .../AddRemoteInstance/AddRemoteInstance.tsx | 4 +- .../AddRemoteInstance.types.ts | 2 - .../FormParts/NodesAgents/NodesAgents.tsx | 8 +-- .../app/percona/add-instance/panel.types.ts | 3 +- .../shared/core/reducers/nodes/nodes.utils.ts | 4 +- 6 files changed, 11 insertions(+), 71 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx index 0d43c0a09a597..10c90406522ec 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx @@ -30,64 +30,6 @@ import { const BASE_URL = '/services'; class AddRemoteInstanceService { - /* -* { - "node_id": "string", - "node_name": "string", - "add_node": { - "node_type": "NODE_TYPE_INVALID", - "node_name": "string", - "machine_id": "string", - "distro": "string", - "container_id": "string", - "container_name": "string", - "node_model": "string", - "region": "string", - "az": "string", - "custom_labels": { - "additionalProp1": "string", - "additionalProp2": "string", - "additionalProp3": "string" - } - }, - "service_name": "string", - "address": "string", - "port": 0, - "socket": "string", - "pmm_agent_id": "string", - "environment": "string", - "cluster": "string", - "replication_set": "string", - "username": "string", - "password": "string", - "qan_mysql_perfschema": true, - "qan_mysql_slowlog": true, - "custom_labels": { - "additionalProp1": "string", - "additionalProp2": "string", - "additionalProp3": "string" - }, - "skip_connection_check": true, - "disable_comments_parsing": true, - "max_query_length": 0, - "disable_query_examples": true, - "max_slowlog_file_size": "string", - "tls": true, - "tls_skip_verify": true, - "tls_ca": "string", - "tls_cert": "string", - "tls_key": "string", - "tablestats_group_table_limit": 0, - "metrics_mode": "AUTO", - "disable_collectors": [ - "string" - ], - "agent_password": "string", - "log_level": "auto", - "expose_exporter": true -} -* -* */ static async addMysql(body: MySQLPayload, token?: CancelToken) { return apiManagement.post( BASE_URL, @@ -237,8 +179,11 @@ export const toPayload = (values: any, discoverName?: string, type?: InstanceAva } } + data.pmm_agent_id = values.pmm_agent_id.label; + data.metrics_mode = 1; delete data.tracking; + delete data.node; return data; }; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tsx index 6c33990833383..7e9377a618294 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tsx @@ -49,12 +49,11 @@ const AddRemoteInstance: FC = ({ const [loading, setLoading] = useState(false); const [generateToken] = useCancelToken(); const initialValues: FormValues = { ...remoteInstanceCredentials }; + initialValues.pmm_agent_id = ""; if (type === Databases.mysql) { initialValues.qan_mysql_perfschema = true; initialValues.disable_comments_parsing = true; - initialValues.node = ""; - initialValues.agent = ""; } if (type === Databases.postgresql) { @@ -67,7 +66,6 @@ const AddRemoteInstance: FC = ({ const onSubmit = useCallback( async (values: FormValues) => { - console.log('----Submit---', values); try { setLoading(true); if (values.isRDS) { diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.types.ts b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.types.ts index c26394e34d728..61785c8f1105b 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.types.ts +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.types.ts @@ -127,8 +127,6 @@ export interface MySQLPayload extends RemoteCommonPayload, TLSCommon { tls_key: string; tls_ca: string; max_query_length: number; - node?: string; - agent?: string; } export interface MongoDBPayload extends RemoteCommonPayload, TLSCommon { diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx index 04e28cf197474..673361dab2fca 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx @@ -39,12 +39,12 @@ export const NodesAgents: FC = ({ form }) => { const setNodeAndAgent = (value: NodesOptions) => { setSelectedNode(value); if (value.agents && value.agents.length > 1) { - form?.change('agent', value.agents[1]); + form?.change('pmm_agent_id', value.agents[1]); } else if (value.agents && value.agents.length === 1) { - form?.change('agent', value.agents[0]); + form?.change('pmm_agent_id', value.agents[0]); } - if(selectedAgent && selectedAgent.value !== "pmm-server") { + if(selectedAgent && selectedAgent.label !== "pmm-server") { form?.change('address', 'localhost'); } } @@ -77,7 +77,7 @@ export const NodesAgents: FC = ({ form }) => { isSearchable={false} disabled={!selectedNode || !selectedNode.agents || selectedNode.agents.length === 1} options={selectedNode?.agents || []} - name="agent" + name="pmm_agent_id" data-testid="nodes-label" onChange={ (event) => { setSelectedAgent(event as AgentsOptions); }} className={styles.selectField} diff --git a/public/app/percona/add-instance/panel.types.ts b/public/app/percona/add-instance/panel.types.ts index d443c0976c055..7a8e6c9177431 100644 --- a/public/app/percona/add-instance/panel.types.ts +++ b/public/app/percona/add-instance/panel.types.ts @@ -33,8 +33,7 @@ export interface RemoteInstanceCredentials { skip_connection_check?: boolean; tls?: boolean; tls_skip_verify?: boolean; - node?: string; - agent?: string; + pmm_agent_id?: string; } export enum InstanceTypesExtra { diff --git a/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts b/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts index cfe19f4df96ec..88c60ff64ec6d 100644 --- a/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts +++ b/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts @@ -62,8 +62,8 @@ export const nodesOptionsMapper = (nodeFromDb: NodeDB[]) => { (agent) => { if (agent.agent_type === AgentType.pmmAgent) { return { - value: agent.agent_id, - label: agent.agent_type + value: agent.agent_type, + label: agent.agent_id } as AgentsOptions; } else { return null; } } From 98f238a1daf8f4ff45e3f54f1b3a80b21581745e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cdorac-ext=E2=80=9D?= <103416234+doracretu3pillar@users.noreply.github.com> Date: Mon, 5 Aug 2024 19:10:39 +0300 Subject: [PATCH 04/30] Added NodesAgents to all the services --- .../ExternalServiceConnectionDetails.tsx | 2 ++ .../HAProxyConnectionDetails/HAProxyConnectionDetails.tsx | 4 +++- .../AddRemoteInstance/FormParts/MainDetails/MainDetails.tsx | 2 ++ .../MongoDBConnectionDetails/MongoDBConnectionDetails.tsx | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/ExternalServiceConnectionDetails/ExternalServiceConnectionDetails.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/ExternalServiceConnectionDetails/ExternalServiceConnectionDetails.tsx index b80ce5548b2d2..3c3f7f5cc9f39 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/ExternalServiceConnectionDetails/ExternalServiceConnectionDetails.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/ExternalServiceConnectionDetails/ExternalServiceConnectionDetails.tsx @@ -1,6 +1,7 @@ import React, { FC, useCallback, useEffect, useMemo } from 'react'; import { useStyles2 } from '@grafana/ui'; +import { NodesAgents } from "app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents"; import { PasswordInputField } from 'app/percona/shared/components/Form/PasswordInput'; import { RadioButtonGroupField } from 'app/percona/shared/components/Form/RadioButtonGroup'; import { TextInputField } from 'app/percona/shared/components/Form/TextInput'; @@ -96,6 +97,7 @@ export const ExternalServiceConnectionDetails: FC = ({ form }) => />
+
= ({ remoteInstanceCredentials }) => { +export const HAProxyConnectionDetails: FC = ({ form, remoteInstanceCredentials }) => { const styles = useStyles2(getStyles); const portValidators = useMemo(() => [validators.required, Validators.validatePort], []); @@ -29,6 +30,7 @@ export const HAProxyConnectionDetails: FC = ({ remoteI />
+
= ({ form, remote />
+
= ({ form, r />
+
Date: Fri, 16 Aug 2024 16:51:11 +0300 Subject: [PATCH 05/30] Fixes after reviews --- .../AddRemoteInstance.tools.tsx | 1 + .../AddRemoteInstance/AddRemoteInstance.tsx | 1 - .../MySQLConnectionDetails.tsx | 2 +- .../NodesAgents/NodesAgents.test.tsx | 34 ++++++++++ .../FormParts/NodesAgents/NodesAgents.tsx | 64 +++++++++++-------- .../NodesAgents/NodesAgents.types.ts | 5 ++ .../app/percona/inventory/Inventory.types.ts | 6 +- public/app/percona/inventory/Tabs/Agents.tsx | 17 ++++- public/app/percona/inventory/Tabs/Nodes.tsx | 16 ++++- .../shared/core/reducers/nodes/nodes.ts | 19 ++---- .../shared/core/reducers/nodes/nodes.types.ts | 4 +- .../shared/core/reducers/nodes/nodes.utils.ts | 24 +++---- 12 files changed, 122 insertions(+), 71 deletions(-) create mode 100644 public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx create mode 100644 public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.types.ts diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.tsx index 9d00a10c1a547..08cf6b9886876 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.tsx @@ -117,6 +117,7 @@ export const getInstanceData = (instanceType: InstanceAvailableType, credentials remoteInstanceCredentials: { metricsParameters: MetricsParameters.manually, schema: Schema.HTTPS, + pmm_agent_id: "", }, }; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tsx index 7e9377a618294..b6c3877a734e3 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tsx @@ -49,7 +49,6 @@ const AddRemoteInstance: FC = ({ const [loading, setLoading] = useState(false); const [generateToken] = useCancelToken(); const initialValues: FormValues = { ...remoteInstanceCredentials }; - initialValues.pmm_agent_id = ""; if (type === Databases.mysql) { initialValues.qan_mysql_perfschema = true; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx index 20605e9ca9c5e..33fe24de63379 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx @@ -9,7 +9,7 @@ import { validators } from 'app/percona/shared/helpers/validatorsForm'; import { Messages } from '../FormParts.messages'; import { getStyles } from '../FormParts.styles'; import { MainDetailsFormPartProps } from '../FormParts.types'; -import { NodesAgents } from "../NodesAgents/NodesAgents"; +import { NodesAgents } from '../NodesAgents/NodesAgents'; export const MySQLConnectionDetails: FC = ({ form, remoteInstanceCredentials }) => { const styles = useStyles2(getStyles); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx new file mode 100644 index 0000000000000..9e2ec22dcc5d8 --- /dev/null +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -0,0 +1,34 @@ +import { fireEvent, render, screen } from '@testing-library/react'; +import React from 'react'; +import { Form } from 'react-final-form'; +import { Provider } from 'react-redux'; + +import { configureStore } from 'app/store/configureStore'; +import { StoreState } from 'app/types'; + +import { NodesAgents } from './NodesAgents'; + +describe('Nodes Agents:: ', () => { + render( + +
+ + +
+ ); + + it('should change the list of agents when changing the nodes', () => { + const nodesValue = screen.getByTestId('nodes-selectbox'); + fireEvent.change(nodesValue, { target: { value: 'pmm-agent' } }); + + expect(screen.getByTestId('agents-selectbox')).toHaveValue('pmm-agent'); + }); + +}); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx index 673361dab2fca..0fcf0f18e50c4 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx @@ -1,32 +1,41 @@ -import { FormApi } from "final-form"; -import React, { FC, useCallback, useEffect, useState } from "react"; +import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { useStyles2 } from '@grafana/ui'; -import { getStyles } from "app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.styles"; -import { GET_NODES_CANCEL_TOKEN } from "app/percona/inventory/Inventory.constants"; -import { AgentsOptions, NodesOptions } from "app/percona/inventory/Inventory.types"; -import { SelectField } from "app/percona/shared/components/Form/SelectFieldCore"; -import { useCancelToken } from "app/percona/shared/components/hooks/cancelToken.hook"; -import { fetchNodesOptionsAction } from "app/percona/shared/core/reducers/nodes/nodes"; -import { isApiCancelError } from "app/percona/shared/helpers/api"; -import { logger } from "app/percona/shared/helpers/logger"; -import { useAppDispatch } from "app/store/store"; - -export interface NodesAgentsProps { - form?: FormApi; -} +import { getStyles } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.styles'; +import { NodesAgentsProps } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.types'; +import { GET_NODES_CANCEL_TOKEN } from 'app/percona/inventory/Inventory.constants'; +import { AgentsOption, NodesOption } from 'app/percona/inventory/Inventory.types'; +import { SelectField } from 'app/percona/shared/components/Form/SelectFieldCore'; +import { useCancelToken } from 'app/percona/shared/components/hooks/cancelToken.hook'; +import { nodesOptionsMapper } from 'app/percona/shared/core/reducers/nodes'; +import { fetchNodesAction } from 'app/percona/shared/core/reducers/nodes/nodes'; +import { getNodes } from 'app/percona/shared/core/selectors'; +import { isApiCancelError } from 'app/percona/shared/helpers/api'; +import { logger } from 'app/percona/shared/helpers/logger'; +import { useAppDispatch } from 'app/store/store'; +import { useSelector } from 'app/types'; export const NodesAgents: FC = ({ form }) => { const styles = useStyles2(getStyles); const dispatch = useAppDispatch(); const [generateToken] = useCancelToken(); - const [selectedNode, setSelectedNode] = useState(undefined); - const [selectedAgent, setSelectedAgent] = useState(undefined); - const [nodes, setNodes] = useState([]); + const [selectedNode, setSelectedNode] = useState(); + const [selectedAgent, setSelectedAgent] = useState(); + const [nodesOptions, setNodesOptions] = useState([]); + const { nodes } = useSelector(getNodes); + + useMemo(() => { + if(nodes.length > 0) { + setNodesOptions(nodesOptionsMapper(nodes)); + } + }, + [nodes] + ); + const loadData = useCallback(async () => { try { - setNodes(await dispatch(fetchNodesOptionsAction({ token: generateToken(GET_NODES_CANCEL_TOKEN) })).unwrap()); + await dispatch(fetchNodesAction({ token: generateToken(GET_NODES_CANCEL_TOKEN) })).unwrap(); } catch (e) { if (isApiCancelError(e)) { return; @@ -36,7 +45,7 @@ export const NodesAgents: FC = ({ form }) => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const setNodeAndAgent = (value: NodesOptions) => { + const setNodeAndAgent = (value: NodesOption) => { setSelectedNode(value); if (value.agents && value.agents.length > 1) { form?.change('pmm_agent_id', value.agents[1]); @@ -50,11 +59,11 @@ export const NodesAgents: FC = ({ form }) => { } useEffect(() => { - if(nodes.length === 0) { + if(nodesOptions.length === 0) { loadData(); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [nodes]); + }, [nodesOptions]); return (
@@ -62,11 +71,10 @@ export const NodesAgents: FC = ({ form }) => { { setNodeAndAgent(event as NodesOptions) }} + data-testid="nodes-selectbox" + onChange={ (event) => setNodeAndAgent(event as NodesOption)} className={styles.selectField} value={selectedNode} /> @@ -78,8 +86,8 @@ export const NodesAgents: FC = ({ form }) => { disabled={!selectedNode || !selectedNode.agents || selectedNode.agents.length === 1} options={selectedNode?.agents || []} name="pmm_agent_id" - data-testid="nodes-label" - onChange={ (event) => { setSelectedAgent(event as AgentsOptions); }} + data-testid="agents-selectbox" + onChange={ (event) => setSelectedAgent(event as AgentsOption)} className={styles.selectField} />
diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.types.ts b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.types.ts new file mode 100644 index 0000000000000..865e97935d888 --- /dev/null +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.types.ts @@ -0,0 +1,5 @@ +import { FormApi } from 'final-form'; + +export interface NodesAgentsProps { + form?: FormApi; +} diff --git a/public/app/percona/inventory/Inventory.types.ts b/public/app/percona/inventory/Inventory.types.ts index 3b65036b02720..82a2c70102a95 100644 --- a/public/app/percona/inventory/Inventory.types.ts +++ b/public/app/percona/inventory/Inventory.types.ts @@ -177,13 +177,13 @@ export type FlattenNode = DbNode & { type: NodeType; }; -export interface NodesOptions { +export interface NodesOption { value: string; label: string; - agents?: AgentsOptions[]; + agents?: AgentsOption[]; } -export interface AgentsOptions { +export interface AgentsOption { value: string; label: string; } diff --git a/public/app/percona/inventory/Tabs/Agents.tsx b/public/app/percona/inventory/Tabs/Agents.tsx index ae4a20a15b907..708ed7155260c 100644 --- a/public/app/percona/inventory/Tabs/Agents.tsx +++ b/public/app/percona/inventory/Tabs/Agents.tsx @@ -7,7 +7,7 @@ import { AppEvents } from '@grafana/data'; import { Badge, Button, HorizontalGroup, Icon, Link, Modal, TagList, useStyles2 } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; -import { Agent, FlattenAgent, ServiceAgentStatus } from 'app/percona/inventory/Inventory.types'; +import { Agent, FlattenAgent, Node, ServiceAgentStatus } from 'app/percona/inventory/Inventory.types'; import { SelectedTableRows } from 'app/percona/shared/components/Elements/AnotherTableInstance/Table.types'; import { CheckboxField } from 'app/percona/shared/components/Elements/Checkbox'; import { DetailsRow } from 'app/percona/shared/components/Elements/DetailsRow/DetailsRow'; @@ -16,6 +16,7 @@ import { ExtendedColumn, FilterFieldTypes, Table } from 'app/percona/shared/comp import { FormElement } from 'app/percona/shared/components/Form'; import { useCancelToken } from 'app/percona/shared/components/hooks/cancelToken.hook'; import { usePerconaNavModel } from 'app/percona/shared/components/hooks/perconaNavModel'; +import { nodeFromDbMapper } from 'app/percona/shared/core/reducers/nodes'; import { fetchNodesAction } from 'app/percona/shared/core/reducers/nodes/nodes'; import { fetchServicesAction } from 'app/percona/shared/core/reducers/services'; import { getNodes, getServices } from 'app/percona/shared/core/selectors'; @@ -51,10 +52,22 @@ export const Agents: FC { + if(nodes.length > 0) { + return nodeFromDbMapper(nodes).sort((a, b) => a.nodeName.localeCompare(b.nodeName)); + } + return []; + }, + [nodes] + ); + const service = services.find((s) => s.params.serviceId === match.params.serviceId); - const node = nodes.find((s) => s.nodeId === nodeId); + const node = mappedNodes.find((s) => s.nodeId === nodeId); const flattenAgents = useMemo(() => data.map((value) => ({ type: value.type, ...value.params })), [data]); + + const columns = useMemo( (): Array> => [ { diff --git a/public/app/percona/inventory/Tabs/Nodes.tsx b/public/app/percona/inventory/Tabs/Nodes.tsx index b35e5f476c362..4584bbd346ea3 100644 --- a/public/app/percona/inventory/Tabs/Nodes.tsx +++ b/public/app/percona/inventory/Tabs/Nodes.tsx @@ -14,7 +14,7 @@ import { ExtendedColumn, FilterFieldTypes, Table } from 'app/percona/shared/comp import { FormElement } from 'app/percona/shared/components/Form'; import { useCancelToken } from 'app/percona/shared/components/hooks/cancelToken.hook'; import { usePerconaNavModel } from 'app/percona/shared/components/hooks/perconaNavModel'; -import { RemoveNodeParams } from 'app/percona/shared/core/reducers/nodes'; +import { nodeFromDbMapper, RemoveNodeParams } from 'app/percona/shared/core/reducers/nodes'; import { fetchNodesAction, removeNodesAction } from 'app/percona/shared/core/reducers/nodes/nodes'; import { getNodes } from 'app/percona/shared/core/selectors'; import { isApiCancelError } from 'app/percona/shared/helpers/api'; @@ -51,6 +51,16 @@ export const NodesTab = () => { const styles = useStyles2(getStyles); const dispatch = useAppDispatch(); + const mappedNodes: Node[] = useMemo( + (): Node[] => { + if(nodes.length > 0) { + return nodeFromDbMapper(nodes).sort((a, b) => a.nodeName.localeCompare(b.nodeName)); + } + return []; + }, + [nodes] + ); + const getActions = useCallback( (row: Row): Action[] => [ { @@ -350,8 +360,8 @@ export const NodesTab = () => { ( +export const fetchNodesAction = createAsyncThunk( 'percona/fetchNodes', async (params = {}) => { - const { nodes } = await InventoryService.getNodes(params.token); - const mappedNodes = nodeFromDbMapper(nodes); - return mappedNodes.sort((a, b) => a.nodeName.localeCompare(b.nodeName)); - } -); - -export const fetchNodesOptionsAction = createAsyncThunk( - 'percona/fetchNodesOptions', - async (params = {}) => { - const { nodes } = await InventoryService.getNodes(params.token); - - return nodesOptionsMapper(nodes); + const { nodes } = await InventoryService.getNodes(params.token); + return nodes; } ); diff --git a/public/app/percona/shared/core/reducers/nodes/nodes.types.ts b/public/app/percona/shared/core/reducers/nodes/nodes.types.ts index 76610b40756f9..aeece8752072e 100644 --- a/public/app/percona/shared/core/reducers/nodes/nodes.types.ts +++ b/public/app/percona/shared/core/reducers/nodes/nodes.types.ts @@ -1,9 +1,9 @@ import { CancelToken } from 'axios'; -import { Node } from 'app/percona/inventory/Inventory.types'; +import { NodeDB } from 'app/percona/inventory/Inventory.types'; export interface NodesState { - nodes: Node[]; + nodes: NodeDB[]; isLoading: boolean; } diff --git a/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts b/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts index 88c60ff64ec6d..0d9ce4da072a9 100644 --- a/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts +++ b/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts @@ -1,11 +1,11 @@ /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions */ -import { AgentsOptions, AgentType, Node, NodeDB, NodesOptions } from 'app/percona/inventory/Inventory.types'; +import { AgentsOption, AgentType, Node, NodeDB, NodesOption } from 'app/percona/inventory/Inventory.types'; import { getAgentsMonitoringStatus } from 'app/percona/inventory/Tabs/Services.utils'; import { DbAgent } from 'app/percona/shared/services/services/Services.types'; const MAIN_COLUMNS = ['address', 'services', 'agents', 'node_type', 'node_id', 'node_name', 'status', 'custom_labels']; -export const nodeFromDbMapper = (nodeFromDb: NodeDB[]) => { +export const nodeFromDbMapper = (nodeFromDb: NodeDB[]): Node[] => { return nodeFromDb.map((node) => { const properties: Record = {}; @@ -51,28 +51,20 @@ export const nodeFromDbMapper = (nodeFromDb: NodeDB[]) => { })), properties: properties, agentsStatus: getAgentsMonitoringStatus(agents ?? []), - } as Node; + }; }); }; -export const nodesOptionsMapper = (nodeFromDb: NodeDB[]) => { +export const nodesOptionsMapper = (nodeFromDb: NodeDB[]): NodesOption[] => { return nodeFromDb.map((node) => { - - const agents = node.agents?.map( - (agent) => { - if (agent.agent_type === AgentType.pmmAgent) { - return { - value: agent.agent_type, - label: agent.agent_id - } as AgentsOptions; - } else { return null; } - } - ).filter(agent => agent !== null) as AgentsOptions[]; + const agents = (node.agents || []) + .filter(agent => agent.agent_type === AgentType.pmmAgent) + .map(agent => ({ value: agent.agent_type, label: agent.agent_id })) return { value: node.node_id, label: node.node_name, agents: agents, - } as NodesOptions; + }; }); } From 2db183c6d2444813cb947204b332402281c2004f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cdorac-ext=E2=80=9D?= <103416234+doracretu3pillar@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:21:24 +0300 Subject: [PATCH 06/30] Testing NodesAgents in progress --- .../NodesAgents/NodesAgents.test.tsx | 44 ++++++++++-------- .../FormParts/NodesAgents/NodesAgents.tsx | 4 +- .../inventory/__mocks__/Inventory.service.ts | 46 +++++++++++++++++++ 3 files changed, 75 insertions(+), 19 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index 9e2ec22dcc5d8..fff1eb5ad4cf7 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -1,34 +1,42 @@ -import { fireEvent, render, screen } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import React from 'react'; -import { Form } from 'react-final-form'; import { Provider } from 'react-redux'; import { configureStore } from 'app/store/configureStore'; -import { StoreState } from 'app/types'; import { NodesAgents } from './NodesAgents'; +import { Form } from 'react-final-form'; +import * as NodesReducer from 'app/percona/shared/core/reducers/nodes/nodes.ts' + +const fetchNodesActionActionSpy = jest.spyOn(NodesReducer, 'fetchNodesAction'); + +jest.mock('app/percona/inventory/Inventory.service'); describe('Nodes Agents:: ', () => { + + let store = configureStore(); + let formAPI; render( - -
- - + +
{ + formAPI=form; + return + }} + />
); - it('should change the list of agents when changing the nodes', () => { - const nodesValue = screen.getByTestId('nodes-selectbox'); - fireEvent.change(nodesValue, { target: { value: 'pmm-agent' } }); + it('should change the list of agents when changing the nodes', async () => { + await waitFor(() => { + expect(fetchNodesActionActionSpy).toHaveBeenCalled(); + }); + - expect(screen.getByTestId('agents-selectbox')).toHaveValue('pmm-agent'); + fireEvent.change(screen.getByTestId('nodes-selectbox'), { target: { value: 'pmm_agent' } }); + console.log(formAPI.getState().values); + // expect(container.querySelector('#nodes-selectbox input')).toHaveValue('pmm-agent'); }); }); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx index 0fcf0f18e50c4..8b69668f4f63b 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx @@ -25,7 +25,7 @@ export const NodesAgents: FC = ({ form }) => { const { nodes } = useSelector(getNodes); useMemo(() => { - if(nodes.length > 0) { + if(nodes && nodes.length > 0) { setNodesOptions(nodesOptionsMapper(nodes)); } }, @@ -59,6 +59,7 @@ export const NodesAgents: FC = ({ form }) => { } useEffect(() => { + console.log('nodesOptions', nodesOptions); if(nodesOptions.length === 0) { loadData(); } @@ -73,6 +74,7 @@ export const NodesAgents: FC = ({ form }) => { isSearchable={false} options={nodesOptions} name="node" + id="nodes-selectbox" data-testid="nodes-selectbox" onChange={ (event) => setNodeAndAgent(event as NodesOption)} className={styles.selectField} diff --git a/public/app/percona/inventory/__mocks__/Inventory.service.ts b/public/app/percona/inventory/__mocks__/Inventory.service.ts index e4874e2f61203..7c68b4e9461a9 100644 --- a/public/app/percona/inventory/__mocks__/Inventory.service.ts +++ b/public/app/percona/inventory/__mocks__/Inventory.service.ts @@ -29,6 +29,47 @@ export const stubs: DBServiceList = { ], }; +const nodesMock =[ + { + node_id: 'pmm-server', + node_type: 'generic', + node_name: 'pmm-server', + machine_id: '', + distro: '', + node_model: '', + container_id: '', + container_name: '', + address: '127.0.0.1', + region: '', + az: '', + custom_labels: {}, + created_at: '2024-08-20T08:05:31.079300Z', + updated_at: '2024-08-20T08:05:31.079300Z', + status: 'STATUS_UP', + agents: [ + { + agent_id: '05af4544-8fd0-4788-b841-89ed6caa9ac1', + agent_type: 'node_exporter', + status: 'AGENT_STATUS_RUNNING', + is_connected: false + }, + { + agent_id: 'pmm-server', + agent_type: 'pmm-agent', + status: '', + is_connected: true + } + ], + services: [ + { + service_id: '291afb9b-2ae0-41d1-a173-f1a138cf1725', + service_type: 'postgresql', + service_name: 'pmm-server-postgresql' + } + ] + } + ]; + export const InventoryService = jest.genMockFromModule( 'app/percona/inventory/Inventory.service' ).InventoryService; @@ -39,3 +80,8 @@ InventoryService.getService = () => Promise.resolve({ mysql: stubWithLabels, }); + +InventoryService.getNodes = () => + Promise.resolve({ + nodes: nodesMock, + }); From c549be1156af0e82307a32af25cfb15fe919ce09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cdorac-ext=E2=80=9D?= <103416234+doracretu3pillar@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:20:19 +0300 Subject: [PATCH 07/30] Added NodesAgents test --- .../FormParts/NodesAgents/NodesAgents.test.tsx | 13 ++++++++----- .../FormParts/NodesAgents/NodesAgents.tsx | 3 ++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index fff1eb5ad4cf7..08eae05801e33 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -1,4 +1,4 @@ -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; import React from 'react'; import { Provider } from 'react-redux'; @@ -7,6 +7,7 @@ import { configureStore } from 'app/store/configureStore'; import { NodesAgents } from './NodesAgents'; import { Form } from 'react-final-form'; import * as NodesReducer from 'app/percona/shared/core/reducers/nodes/nodes.ts' +import selectEvent from "react-select-event"; const fetchNodesActionActionSpy = jest.spyOn(NodesReducer, 'fetchNodesAction'); @@ -32,11 +33,13 @@ describe('Nodes Agents:: ', () => { await waitFor(() => { expect(fetchNodesActionActionSpy).toHaveBeenCalled(); }); + const nodesSelect = screen.getByLabelText('Nodes'); + await selectEvent.select(nodesSelect, ['pmm-server'], { container: document.body }); - - fireEvent.change(screen.getByTestId('nodes-selectbox'), { target: { value: 'pmm_agent' } }); - console.log(formAPI.getState().values); - // expect(container.querySelector('#nodes-selectbox input')).toHaveValue('pmm-agent'); + const agentsSelect = screen.getByLabelText('Agents'); + const formValues = formAPI.getState().values; + expect(formValues.pmm_agent_id.value).toBe('pmm-agent'); + expect(formValues.node.value).toBe('pmm-server'); }); }); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx index 8b69668f4f63b..b7b280a429eec 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx @@ -59,7 +59,6 @@ export const NodesAgents: FC = ({ form }) => { } useEffect(() => { - console.log('nodesOptions', nodesOptions); if(nodesOptions.length === 0) { loadData(); } @@ -79,6 +78,7 @@ export const NodesAgents: FC = ({ form }) => { onChange={ (event) => setNodeAndAgent(event as NodesOption)} className={styles.selectField} value={selectedNode} + aria-label="Nodes" />
@@ -91,6 +91,7 @@ export const NodesAgents: FC = ({ form }) => { data-testid="agents-selectbox" onChange={ (event) => setSelectedAgent(event as AgentsOption)} className={styles.selectField} + aria-label="Agents" />
From af059844d4bca8fa312246797d692fb9be9a74d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cdorac-ext=E2=80=9D?= <103416234+doracretu3pillar@users.noreply.github.com> Date: Thu, 29 Aug 2024 11:36:20 +0300 Subject: [PATCH 08/30] Fix from PR --- .../FormParts/NodesAgents/NodesAgents.tsx | 12 ++++-------- public/app/percona/inventory/Tabs/Agents.tsx | 7 +------ public/app/percona/inventory/Tabs/Nodes.tsx | 7 +------ .../shared/core/reducers/nodes/nodes.utils.ts | 5 ++--- 4 files changed, 8 insertions(+), 23 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx index b7b280a429eec..638f533ed4929 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx @@ -4,10 +4,10 @@ import { useStyles2 } from '@grafana/ui'; import { getStyles } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.styles'; import { NodesAgentsProps } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.types'; import { GET_NODES_CANCEL_TOKEN } from 'app/percona/inventory/Inventory.constants'; -import { AgentsOption, NodesOption } from 'app/percona/inventory/Inventory.types'; +import { AgentsOption, Node, NodesOption } from 'app/percona/inventory/Inventory.types'; import { SelectField } from 'app/percona/shared/components/Form/SelectFieldCore'; import { useCancelToken } from 'app/percona/shared/components/hooks/cancelToken.hook'; -import { nodesOptionsMapper } from 'app/percona/shared/core/reducers/nodes'; +import { nodeFromDbMapper, nodesOptionsMapper } from 'app/percona/shared/core/reducers/nodes'; import { fetchNodesAction } from 'app/percona/shared/core/reducers/nodes/nodes'; import { getNodes } from 'app/percona/shared/core/selectors'; import { isApiCancelError } from 'app/percona/shared/helpers/api'; @@ -21,14 +21,10 @@ export const NodesAgents: FC = ({ form }) => { const [generateToken] = useCancelToken(); const [selectedNode, setSelectedNode] = useState(); const [selectedAgent, setSelectedAgent] = useState(); - const [nodesOptions, setNodesOptions] = useState([]); const { nodes } = useSelector(getNodes); - useMemo(() => { - if(nodes && nodes.length > 0) { - setNodesOptions(nodesOptionsMapper(nodes)); - } - }, + const nodesOptions = useMemo( + (): NodesOption[] => nodesOptionsMapper(nodes), [nodes] ); diff --git a/public/app/percona/inventory/Tabs/Agents.tsx b/public/app/percona/inventory/Tabs/Agents.tsx index 708ed7155260c..fca3defb22433 100644 --- a/public/app/percona/inventory/Tabs/Agents.tsx +++ b/public/app/percona/inventory/Tabs/Agents.tsx @@ -53,12 +53,7 @@ export const Agents: FC { - if(nodes.length > 0) { - return nodeFromDbMapper(nodes).sort((a, b) => a.nodeName.localeCompare(b.nodeName)); - } - return []; - }, + (): Node[] => nodeFromDbMapper(nodes).sort((a, b) => a.nodeName.localeCompare(b.nodeName)), [nodes] ); diff --git a/public/app/percona/inventory/Tabs/Nodes.tsx b/public/app/percona/inventory/Tabs/Nodes.tsx index 4584bbd346ea3..0f8a8a510edd6 100644 --- a/public/app/percona/inventory/Tabs/Nodes.tsx +++ b/public/app/percona/inventory/Tabs/Nodes.tsx @@ -52,12 +52,7 @@ export const NodesTab = () => { const dispatch = useAppDispatch(); const mappedNodes: Node[] = useMemo( - (): Node[] => { - if(nodes.length > 0) { - return nodeFromDbMapper(nodes).sort((a, b) => a.nodeName.localeCompare(b.nodeName)); - } - return []; - }, + (): Node[] => nodeFromDbMapper(nodes).sort((a, b) => a.nodeName.localeCompare(b.nodeName)), [nodes] ); diff --git a/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts b/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts index 0d9ce4da072a9..ab1844a806cc0 100644 --- a/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts +++ b/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts @@ -55,8 +55,8 @@ export const nodeFromDbMapper = (nodeFromDb: NodeDB[]): Node[] => { }); }; -export const nodesOptionsMapper = (nodeFromDb: NodeDB[]): NodesOption[] => { - return nodeFromDb.map((node) => { +export const nodesOptionsMapper = (nodeFromDb: NodeDB[]): NodesOption[] => + nodeFromDb.map((node) => { const agents = (node.agents || []) .filter(agent => agent.agent_type === AgentType.pmmAgent) .map(agent => ({ value: agent.agent_type, label: agent.agent_id })) @@ -67,4 +67,3 @@ export const nodesOptionsMapper = (nodeFromDb: NodeDB[]): NodesOption[] => { agents: agents, }; }); -} From cd89d7b55123a782258bb9573cbc48596e4ec225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cdorac-ext=E2=80=9D?= <103416234+doracretu3pillar@users.noreply.github.com> Date: Fri, 6 Sep 2024 10:59:49 +0300 Subject: [PATCH 09/30] Fixes after PR --- .../AddRemoteInstance.service.tsx | 2 +- .../NodesAgents/NodesAgents.constants.tsx | 3 ++ .../NodesAgents/NodesAgents.test.tsx | 52 ++++++++++++------- .../FormParts/NodesAgents/NodesAgents.tsx | 8 ++- .../shared/core/reducers/nodes/nodes.utils.ts | 2 +- 5 files changed, 43 insertions(+), 24 deletions(-) create mode 100644 public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx index 10c90406522ec..a40e266221766 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx @@ -179,7 +179,7 @@ export const toPayload = (values: any, discoverName?: string, type?: InstanceAva } } - data.pmm_agent_id = values.pmm_agent_id.label; + data.pmm_agent_id = values.pmm_agent_id.value; data.metrics_mode = 1; delete data.tracking; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx new file mode 100644 index 0000000000000..82b230ffd3d9e --- /dev/null +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx @@ -0,0 +1,3 @@ +export const agentTypes = { + pmmServer: 'pmm-server', +} diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index 08eae05801e33..fb45e2cdd9598 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -1,30 +1,30 @@ -import { render, screen, waitFor } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import React from 'react'; +import { Form } from 'react-final-form'; import { Provider } from 'react-redux'; +import selectEvent from 'react-select-event'; +import * as NodesReducer from 'app/percona/shared/core/reducers/nodes/nodes.ts'; import { configureStore } from 'app/store/configureStore'; import { NodesAgents } from './NodesAgents'; -import { Form } from 'react-final-form'; -import * as NodesReducer from 'app/percona/shared/core/reducers/nodes/nodes.ts' -import selectEvent from "react-select-event"; const fetchNodesActionActionSpy = jest.spyOn(NodesReducer, 'fetchNodesAction'); jest.mock('app/percona/inventory/Inventory.service'); -describe('Nodes Agents:: ', () => { +const submitMock = jest.fn(); - let store = configureStore(); - let formAPI; +describe('Nodes Agents:: ', () => { render( - + { - formAPI=form; - return - }} + onSubmit={submitMock} + render={({ handleSubmit, form }) => ( + + + + )} /> ); @@ -33,13 +33,25 @@ describe('Nodes Agents:: ', () => { await waitFor(() => { expect(fetchNodesActionActionSpy).toHaveBeenCalled(); }); - const nodesSelect = screen.getByLabelText('Nodes'); - await selectEvent.select(nodesSelect, ['pmm-server'], { container: document.body }); - const agentsSelect = screen.getByLabelText('Agents'); - const formValues = formAPI.getState().values; - expect(formValues.pmm_agent_id.value).toBe('pmm-agent'); - expect(formValues.node.value).toBe('pmm-server'); - }); + const form = screen.getByTestId('node-agents-form'); + const nodesSelect = screen.getByLabelText('Nodes'); + await selectEvent.select(nodesSelect, 'pmm-server', { container: document.body }); + + fireEvent.submit(form); + + expect(submitMock).toHaveBeenCalledWith( + expect.objectContaining({ + node: expect.objectContaining({ + value: 'pmm-server', + }), + pmm_agent_id: expect.objectContaining({ + value: 'pmm-agent', + }), + }), + expect.anything(), + expect.anything() + ); + }); }); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx index 638f533ed4929..866efd963d899 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx @@ -2,6 +2,7 @@ import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { useStyles2 } from '@grafana/ui'; import { getStyles } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.styles'; +import { agentTypes } from "app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants"; import { NodesAgentsProps } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.types'; import { GET_NODES_CANCEL_TOKEN } from 'app/percona/inventory/Inventory.constants'; import { AgentsOption, Node, NodesOption } from 'app/percona/inventory/Inventory.types'; @@ -44,12 +45,15 @@ export const NodesAgents: FC = ({ form }) => { const setNodeAndAgent = (value: NodesOption) => { setSelectedNode(value); if (value.agents && value.agents.length > 1) { - form?.change('pmm_agent_id', value.agents[1]); + const pmmServerAgent = value.agents.find(item => item.key === agentTypes.pmmServer) + if(pmmServerAgent) { + form?.change('pmm_agent_id', pmmServerAgent); + } } else if (value.agents && value.agents.length === 1) { form?.change('pmm_agent_id', value.agents[0]); } - if(selectedAgent && selectedAgent.label !== "pmm-server") { + if(selectedAgent && selectedAgent.label !== agentTypes.pmmServer) { form?.change('address', 'localhost'); } } diff --git a/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts b/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts index ab1844a806cc0..25097f9658556 100644 --- a/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts +++ b/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts @@ -59,7 +59,7 @@ export const nodesOptionsMapper = (nodeFromDb: NodeDB[]): NodesOption[] => nodeFromDb.map((node) => { const agents = (node.agents || []) .filter(agent => agent.agent_type === AgentType.pmmAgent) - .map(agent => ({ value: agent.agent_type, label: agent.agent_id })) + .map(agent => ({ value: agent.agent_id, label: agent.agent_id, key: agent.agent_type })) return { value: node.node_id, From cc639cdecd59505dcaf9e8f25501111078c3009d Mon Sep 17 00:00:00 2001 From: DoraCretu594118 Date: Tue, 10 Sep 2024 13:18:14 +0300 Subject: [PATCH 10/30] Prettier fix --- .../AddRemoteInstance.tools.tsx | 2 +- .../ExternalServiceConnectionDetails.tsx | 2 +- .../HAProxyConnectionDetails.tsx | 2 +- .../FormParts/MainDetails/MainDetails.tsx | 2 +- .../MongoDBConnectionDetails.tsx | 2 +- .../MySQLConnectionDetails.tsx | 2 +- .../NodesAgents/NodesAgents.constants.tsx | 2 +- .../FormParts/NodesAgents/NodesAgents.tsx | 25 +++--- .../PostgreSQLConnectionDetails.tsx | 2 +- public/app/percona/inventory/Tabs/Agents.tsx | 2 - public/app/percona/inventory/Tabs/Nodes.tsx | 2 +- .../inventory/__mocks__/Inventory.service.ts | 80 +++++++++---------- .../shared/core/reducers/nodes/nodes.ts | 4 +- .../shared/core/reducers/nodes/nodes.utils.ts | 4 +- 14 files changed, 63 insertions(+), 70 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.tsx index 08cf6b9886876..c087c2626632e 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.tsx @@ -117,7 +117,7 @@ export const getInstanceData = (instanceType: InstanceAvailableType, credentials remoteInstanceCredentials: { metricsParameters: MetricsParameters.manually, schema: Schema.HTTPS, - pmm_agent_id: "", + pmm_agent_id: '', }, }; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/ExternalServiceConnectionDetails/ExternalServiceConnectionDetails.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/ExternalServiceConnectionDetails/ExternalServiceConnectionDetails.tsx index 3c3f7f5cc9f39..59a8703512e3d 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/ExternalServiceConnectionDetails/ExternalServiceConnectionDetails.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/ExternalServiceConnectionDetails/ExternalServiceConnectionDetails.tsx @@ -1,7 +1,7 @@ import React, { FC, useCallback, useEffect, useMemo } from 'react'; import { useStyles2 } from '@grafana/ui'; -import { NodesAgents } from "app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents"; +import { NodesAgents } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents'; import { PasswordInputField } from 'app/percona/shared/components/Form/PasswordInput'; import { RadioButtonGroupField } from 'app/percona/shared/components/Form/RadioButtonGroup'; import { TextInputField } from 'app/percona/shared/components/Form/TextInput'; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/HAProxyConnectionDetails/HAProxyConnectionDetails.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/HAProxyConnectionDetails/HAProxyConnectionDetails.tsx index 616b16821f6de..d4f687c9c8678 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/HAProxyConnectionDetails/HAProxyConnectionDetails.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/HAProxyConnectionDetails/HAProxyConnectionDetails.tsx @@ -1,7 +1,7 @@ import React, { FC, useCallback, useMemo } from 'react'; import { useStyles2 } from '@grafana/ui'; -import { NodesAgents } from "app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents"; +import { NodesAgents } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents'; import { PasswordInputField } from 'app/percona/shared/components/Form/PasswordInput'; import { TextInputField } from 'app/percona/shared/components/Form/TextInput'; import Validators from 'app/percona/shared/helpers/validators'; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MainDetails/MainDetails.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MainDetails/MainDetails.tsx index ba918bf9e59c6..8c073c7b0c5b8 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MainDetails/MainDetails.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MainDetails/MainDetails.tsx @@ -1,7 +1,7 @@ import React, { FC, useMemo } from 'react'; import { useStyles2 } from '@grafana/ui'; -import { NodesAgents } from "app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents"; +import { NodesAgents } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents'; import { PasswordInputField } from 'app/percona/shared/components/Form/PasswordInput'; import { TextInputField } from 'app/percona/shared/components/Form/TextInput'; import Validators from 'app/percona/shared/helpers/validators'; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MongoDBConnectionDetails/MongoDBConnectionDetails.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MongoDBConnectionDetails/MongoDBConnectionDetails.tsx index 0dcb9a22b974c..5aa423d14f7ac 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MongoDBConnectionDetails/MongoDBConnectionDetails.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MongoDBConnectionDetails/MongoDBConnectionDetails.tsx @@ -1,7 +1,7 @@ import React, { FC, useMemo } from 'react'; import { useStyles2 } from '@grafana/ui'; -import { NodesAgents } from "app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents"; +import { NodesAgents } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents'; import { PasswordInputField } from 'app/percona/shared/components/Form/PasswordInput'; import { TextInputField } from 'app/percona/shared/components/Form/TextInput'; import Validators from 'app/percona/shared/helpers/validators'; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx index 33fe24de63379..ac3b5e5d10f4a 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.tsx @@ -1,7 +1,7 @@ import React, { FC, useMemo } from 'react'; import { useStyles2 } from '@grafana/ui'; -import { PasswordInputField } from 'app/percona/shared/components/Form/PasswordInput' +import { PasswordInputField } from 'app/percona/shared/components/Form/PasswordInput'; import { TextInputField } from 'app/percona/shared/components/Form/TextInput'; import Validators from 'app/percona/shared/helpers/validators'; import { validators } from 'app/percona/shared/helpers/validatorsForm'; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx index 82b230ffd3d9e..e2db02ccf36f2 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx @@ -1,3 +1,3 @@ export const agentTypes = { pmmServer: 'pmm-server', -} +}; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx index 866efd963d899..24e08e4b05736 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx @@ -2,7 +2,7 @@ import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { useStyles2 } from '@grafana/ui'; import { getStyles } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.styles'; -import { agentTypes } from "app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants"; +import { agentTypes } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants'; import { NodesAgentsProps } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.types'; import { GET_NODES_CANCEL_TOKEN } from 'app/percona/inventory/Inventory.constants'; import { AgentsOption, Node, NodesOption } from 'app/percona/inventory/Inventory.types'; @@ -24,11 +24,7 @@ export const NodesAgents: FC = ({ form }) => { const [selectedAgent, setSelectedAgent] = useState(); const { nodes } = useSelector(getNodes); - const nodesOptions = useMemo( - (): NodesOption[] => nodesOptionsMapper(nodes), - [nodes] - ); - + const nodesOptions = useMemo((): NodesOption[] => nodesOptionsMapper(nodes), [nodes]); const loadData = useCallback(async () => { try { @@ -45,21 +41,21 @@ export const NodesAgents: FC = ({ form }) => { const setNodeAndAgent = (value: NodesOption) => { setSelectedNode(value); if (value.agents && value.agents.length > 1) { - const pmmServerAgent = value.agents.find(item => item.key === agentTypes.pmmServer) - if(pmmServerAgent) { + const pmmServerAgent = value.agents.find((item) => item.key === agentTypes.pmmServer); + if (pmmServerAgent) { form?.change('pmm_agent_id', pmmServerAgent); } } else if (value.agents && value.agents.length === 1) { form?.change('pmm_agent_id', value.agents[0]); } - if(selectedAgent && selectedAgent.label !== agentTypes.pmmServer) { + if (selectedAgent && selectedAgent.label !== agentTypes.pmmServer) { form?.change('address', 'localhost'); } - } + }; useEffect(() => { - if(nodesOptions.length === 0) { + if (nodesOptions.length === 0) { loadData(); } // eslint-disable-next-line react-hooks/exhaustive-deps @@ -75,7 +71,7 @@ export const NodesAgents: FC = ({ form }) => { name="node" id="nodes-selectbox" data-testid="nodes-selectbox" - onChange={ (event) => setNodeAndAgent(event as NodesOption)} + onChange={(event) => setNodeAndAgent(event as NodesOption)} className={styles.selectField} value={selectedNode} aria-label="Nodes" @@ -89,12 +85,11 @@ export const NodesAgents: FC = ({ form }) => { options={selectedNode?.agents || []} name="pmm_agent_id" data-testid="agents-selectbox" - onChange={ (event) => setSelectedAgent(event as AgentsOption)} + onChange={(event) => setSelectedAgent(event as AgentsOption)} className={styles.selectField} aria-label="Agents" /> ); - -} +}; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.tsx index 6eb1dd7e82e0b..1ae0318217c47 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.tsx @@ -9,7 +9,7 @@ import { validators } from 'app/percona/shared/helpers/validatorsForm'; import { Messages } from '../FormParts.messages'; import { getStyles } from '../FormParts.styles'; import { MainDetailsFormPartProps } from '../FormParts.types'; -import { NodesAgents } from "../NodesAgents/NodesAgents"; +import { NodesAgents } from '../NodesAgents/NodesAgents'; export const PostgreSQLConnectionDetails: FC = ({ form, remoteInstanceCredentials }) => { const styles = useStyles2(getStyles); diff --git a/public/app/percona/inventory/Tabs/Agents.tsx b/public/app/percona/inventory/Tabs/Agents.tsx index fca3defb22433..00136bb89494a 100644 --- a/public/app/percona/inventory/Tabs/Agents.tsx +++ b/public/app/percona/inventory/Tabs/Agents.tsx @@ -61,8 +61,6 @@ export const Agents: FC s.nodeId === nodeId); const flattenAgents = useMemo(() => data.map((value) => ({ type: value.type, ...value.params })), [data]); - - const columns = useMemo( (): Array> => [ { diff --git a/public/app/percona/inventory/Tabs/Nodes.tsx b/public/app/percona/inventory/Tabs/Nodes.tsx index 0f8a8a510edd6..192d4fd8c9bf6 100644 --- a/public/app/percona/inventory/Tabs/Nodes.tsx +++ b/public/app/percona/inventory/Tabs/Nodes.tsx @@ -51,7 +51,7 @@ export const NodesTab = () => { const styles = useStyles2(getStyles); const dispatch = useAppDispatch(); - const mappedNodes: Node[] = useMemo( + const mappedNodes: Node[] = useMemo( (): Node[] => nodeFromDbMapper(nodes).sort((a, b) => a.nodeName.localeCompare(b.nodeName)), [nodes] ); diff --git a/public/app/percona/inventory/__mocks__/Inventory.service.ts b/public/app/percona/inventory/__mocks__/Inventory.service.ts index 7c68b4e9461a9..c5bf669b653a8 100644 --- a/public/app/percona/inventory/__mocks__/Inventory.service.ts +++ b/public/app/percona/inventory/__mocks__/Inventory.service.ts @@ -29,46 +29,46 @@ export const stubs: DBServiceList = { ], }; -const nodesMock =[ - { - node_id: 'pmm-server', - node_type: 'generic', - node_name: 'pmm-server', - machine_id: '', - distro: '', - node_model: '', - container_id: '', - container_name: '', - address: '127.0.0.1', - region: '', - az: '', - custom_labels: {}, - created_at: '2024-08-20T08:05:31.079300Z', - updated_at: '2024-08-20T08:05:31.079300Z', - status: 'STATUS_UP', - agents: [ - { - agent_id: '05af4544-8fd0-4788-b841-89ed6caa9ac1', - agent_type: 'node_exporter', - status: 'AGENT_STATUS_RUNNING', - is_connected: false - }, - { - agent_id: 'pmm-server', - agent_type: 'pmm-agent', - status: '', - is_connected: true - } - ], - services: [ - { - service_id: '291afb9b-2ae0-41d1-a173-f1a138cf1725', - service_type: 'postgresql', - service_name: 'pmm-server-postgresql' - } - ] - } - ]; +const nodesMock = [ + { + node_id: 'pmm-server', + node_type: 'generic', + node_name: 'pmm-server', + machine_id: '', + distro: '', + node_model: '', + container_id: '', + container_name: '', + address: '127.0.0.1', + region: '', + az: '', + custom_labels: {}, + created_at: '2024-08-20T08:05:31.079300Z', + updated_at: '2024-08-20T08:05:31.079300Z', + status: 'STATUS_UP', + agents: [ + { + agent_id: '05af4544-8fd0-4788-b841-89ed6caa9ac1', + agent_type: 'node_exporter', + status: 'AGENT_STATUS_RUNNING', + is_connected: false, + }, + { + agent_id: 'pmm-server', + agent_type: 'pmm-agent', + status: '', + is_connected: true, + }, + ], + services: [ + { + service_id: '291afb9b-2ae0-41d1-a173-f1a138cf1725', + service_type: 'postgresql', + service_name: 'pmm-server-postgresql', + }, + ], + }, +]; export const InventoryService = jest.genMockFromModule( 'app/percona/inventory/Inventory.service' diff --git a/public/app/percona/shared/core/reducers/nodes/nodes.ts b/public/app/percona/shared/core/reducers/nodes/nodes.ts index 91187818c39f0..8c5c7dedf0fec 100644 --- a/public/app/percona/shared/core/reducers/nodes/nodes.ts +++ b/public/app/percona/shared/core/reducers/nodes/nodes.ts @@ -37,8 +37,8 @@ const nodesSlice = createSlice({ export const fetchNodesAction = createAsyncThunk( 'percona/fetchNodes', async (params = {}) => { - const { nodes } = await InventoryService.getNodes(params.token); - return nodes; + const { nodes } = await InventoryService.getNodes(params.token); + return nodes; } ); diff --git a/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts b/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts index 25097f9658556..19817dfd11a8b 100644 --- a/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts +++ b/public/app/percona/shared/core/reducers/nodes/nodes.utils.ts @@ -58,8 +58,8 @@ export const nodeFromDbMapper = (nodeFromDb: NodeDB[]): Node[] => { export const nodesOptionsMapper = (nodeFromDb: NodeDB[]): NodesOption[] => nodeFromDb.map((node) => { const agents = (node.agents || []) - .filter(agent => agent.agent_type === AgentType.pmmAgent) - .map(agent => ({ value: agent.agent_id, label: agent.agent_id, key: agent.agent_type })) + .filter((agent) => agent.agent_type === AgentType.pmmAgent) + .map((agent) => ({ value: agent.agent_id, label: agent.agent_id, key: agent.agent_type })); return { value: node.node_id, From 395a1a76939bb244996cfa6f7fbbe9d688d830a3 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 Date: Tue, 10 Sep 2024 13:46:33 +0300 Subject: [PATCH 11/30] Fixed ts issues --- .../FormParts/NodesAgents/NodesAgents.test.tsx | 2 +- .../FormParts/NodesAgents/NodesAgents.tsx | 4 ++-- public/app/percona/inventory/Inventory.types.ts | 1 + .../inventory/__mocks__/Inventory.service.ts | 15 ++++++++------- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index fb45e2cdd9598..2b6b2fd515789 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -4,7 +4,7 @@ import { Form } from 'react-final-form'; import { Provider } from 'react-redux'; import selectEvent from 'react-select-event'; -import * as NodesReducer from 'app/percona/shared/core/reducers/nodes/nodes.ts'; +import * as NodesReducer from 'app/percona/shared/core/reducers/nodes/nodes'; import { configureStore } from 'app/store/configureStore'; import { NodesAgents } from './NodesAgents'; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx index 24e08e4b05736..037c4556bdf93 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx @@ -5,10 +5,10 @@ import { getStyles } from 'app/percona/add-instance/components/AddRemoteInstance import { agentTypes } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants'; import { NodesAgentsProps } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.types'; import { GET_NODES_CANCEL_TOKEN } from 'app/percona/inventory/Inventory.constants'; -import { AgentsOption, Node, NodesOption } from 'app/percona/inventory/Inventory.types'; +import { AgentsOption, NodesOption } from 'app/percona/inventory/Inventory.types'; import { SelectField } from 'app/percona/shared/components/Form/SelectFieldCore'; import { useCancelToken } from 'app/percona/shared/components/hooks/cancelToken.hook'; -import { nodeFromDbMapper, nodesOptionsMapper } from 'app/percona/shared/core/reducers/nodes'; +import { nodesOptionsMapper } from 'app/percona/shared/core/reducers/nodes'; import { fetchNodesAction } from 'app/percona/shared/core/reducers/nodes/nodes'; import { getNodes } from 'app/percona/shared/core/selectors'; import { isApiCancelError } from 'app/percona/shared/helpers/api'; diff --git a/public/app/percona/inventory/Inventory.types.ts b/public/app/percona/inventory/Inventory.types.ts index 82a2c70102a95..073dca94164e7 100644 --- a/public/app/percona/inventory/Inventory.types.ts +++ b/public/app/percona/inventory/Inventory.types.ts @@ -186,4 +186,5 @@ export interface NodesOption { export interface AgentsOption { value: string; label: string; + key: string; } diff --git a/public/app/percona/inventory/__mocks__/Inventory.service.ts b/public/app/percona/inventory/__mocks__/Inventory.service.ts index c5bf669b653a8..118935a08ad2b 100644 --- a/public/app/percona/inventory/__mocks__/Inventory.service.ts +++ b/public/app/percona/inventory/__mocks__/Inventory.service.ts @@ -1,5 +1,6 @@ import * as service from 'app/percona/inventory/Inventory.service'; -import { DBServiceList } from 'app/percona/inventory/Inventory.types'; +import { AgentType, DBServiceList, ServiceAgentStatus } from 'app/percona/inventory/Inventory.types'; +import { ServiceStatus, ServiceType } from 'app/percona/shared/services/services/Services.types'; export const stubWithLabels = { service_id: 'service_id', @@ -45,25 +46,25 @@ const nodesMock = [ custom_labels: {}, created_at: '2024-08-20T08:05:31.079300Z', updated_at: '2024-08-20T08:05:31.079300Z', - status: 'STATUS_UP', + status: ServiceStatus.UP, agents: [ { agent_id: '05af4544-8fd0-4788-b841-89ed6caa9ac1', - agent_type: 'node_exporter', - status: 'AGENT_STATUS_RUNNING', + agent_type: AgentType.nodeExporter, + status: ServiceAgentStatus.RUNNING, is_connected: false, }, { agent_id: 'pmm-server', - agent_type: 'pmm-agent', - status: '', + agent_type: AgentType.pmmAgent, + status: ServiceAgentStatus.RUNNING, is_connected: true, }, ], services: [ { service_id: '291afb9b-2ae0-41d1-a173-f1a138cf1725', - service_type: 'postgresql', + service_type: ServiceType.posgresql, service_name: 'pmm-server-postgresql', }, ], From 088e3767d8c5401f1c02ce02ff52aaecbd9f61ba Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Thu, 19 Sep 2024 17:16:20 +0300 Subject: [PATCH 12/30] Added the types to mappedNodes, nodesOptions, changed the agent name object --- .../FormParts/FormParts.messages.ts | 4 ++++ .../NodesAgents/NodesAgents.constants.tsx | 2 +- .../FormParts/NodesAgents/NodesAgents.tsx | 18 ++++++++++-------- .../app/percona/inventory/Inventory.types.ts | 1 - public/app/percona/inventory/Tabs/Agents.tsx | 6 +++--- public/app/percona/inventory/Tabs/Nodes.tsx | 4 ++-- 6 files changed, 20 insertions(+), 15 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.messages.ts b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.messages.ts index 98f7fd6c7b1e3..6b5425e36913b 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.messages.ts +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.messages.ts @@ -19,6 +19,10 @@ export const Messages = { username: 'Username', password: 'Password', }, + nodesAgents: { + nodes: "Nodes", + agents: "Agents" + }, mainDetails: { address: 'Hostname', serviceName: 'Service name', diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx index e2db02ccf36f2..f5f201d60f483 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx @@ -1,3 +1,3 @@ -export const agentTypes = { +export const agentId = { pmmServer: 'pmm-server', }; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx index 037c4556bdf93..18e2513c86518 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx @@ -1,8 +1,9 @@ import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { useStyles2 } from '@grafana/ui'; +import { Messages } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.messages'; import { getStyles } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.styles'; -import { agentTypes } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants'; +import { agentId } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants'; import { NodesAgentsProps } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.types'; import { GET_NODES_CANCEL_TOKEN } from 'app/percona/inventory/Inventory.constants'; import { AgentsOption, NodesOption } from 'app/percona/inventory/Inventory.types'; @@ -24,7 +25,7 @@ export const NodesAgents: FC = ({ form }) => { const [selectedAgent, setSelectedAgent] = useState(); const { nodes } = useSelector(getNodes); - const nodesOptions = useMemo((): NodesOption[] => nodesOptionsMapper(nodes), [nodes]); + const nodesOptions = useMemo(() => nodesOptionsMapper(nodes), [nodes]); const loadData = useCallback(async () => { try { @@ -40,8 +41,9 @@ export const NodesAgents: FC = ({ form }) => { const setNodeAndAgent = (value: NodesOption) => { setSelectedNode(value); + if (value.agents && value.agents.length > 1) { - const pmmServerAgent = value.agents.find((item) => item.key === agentTypes.pmmServer); + const pmmServerAgent = value.agents.find((item) => item.value === agentId.pmmServer); if (pmmServerAgent) { form?.change('pmm_agent_id', pmmServerAgent); } @@ -49,7 +51,7 @@ export const NodesAgents: FC = ({ form }) => { form?.change('pmm_agent_id', value.agents[0]); } - if (selectedAgent && selectedAgent.label !== agentTypes.pmmServer) { + if (selectedAgent && selectedAgent.label !== agentId.pmmServer) { form?.change('address', 'localhost'); } }; @@ -65,7 +67,7 @@ export const NodesAgents: FC = ({ form }) => {
= ({ form }) => { onChange={(event) => setNodeAndAgent(event as NodesOption)} className={styles.selectField} value={selectedNode} - aria-label="Nodes" + aria-label={Messages.form.labels.nodesAgents.nodes} />
= ({ form }) => { data-testid="agents-selectbox" onChange={(event) => setSelectedAgent(event as AgentsOption)} className={styles.selectField} - aria-label="Agents" + aria-label={Messages.form.labels.nodesAgents.agents} />
diff --git a/public/app/percona/inventory/Inventory.types.ts b/public/app/percona/inventory/Inventory.types.ts index 073dca94164e7..82a2c70102a95 100644 --- a/public/app/percona/inventory/Inventory.types.ts +++ b/public/app/percona/inventory/Inventory.types.ts @@ -186,5 +186,4 @@ export interface NodesOption { export interface AgentsOption { value: string; label: string; - key: string; } diff --git a/public/app/percona/inventory/Tabs/Agents.tsx b/public/app/percona/inventory/Tabs/Agents.tsx index 00136bb89494a..8daedb475c1d1 100644 --- a/public/app/percona/inventory/Tabs/Agents.tsx +++ b/public/app/percona/inventory/Tabs/Agents.tsx @@ -7,7 +7,7 @@ import { AppEvents } from '@grafana/data'; import { Badge, Button, HorizontalGroup, Icon, Link, Modal, TagList, useStyles2 } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; -import { Agent, FlattenAgent, Node, ServiceAgentStatus } from 'app/percona/inventory/Inventory.types'; +import { Agent, FlattenAgent, ServiceAgentStatus } from 'app/percona/inventory/Inventory.types'; import { SelectedTableRows } from 'app/percona/shared/components/Elements/AnotherTableInstance/Table.types'; import { CheckboxField } from 'app/percona/shared/components/Elements/Checkbox'; import { DetailsRow } from 'app/percona/shared/components/Elements/DetailsRow/DetailsRow'; @@ -52,8 +52,8 @@ export const Agents: FC nodeFromDbMapper(nodes).sort((a, b) => a.nodeName.localeCompare(b.nodeName)), + const mappedNodes = useMemo( + () => nodeFromDbMapper(nodes).sort((a, b) => a.nodeName.localeCompare(b.nodeName)), [nodes] ); diff --git a/public/app/percona/inventory/Tabs/Nodes.tsx b/public/app/percona/inventory/Tabs/Nodes.tsx index 192d4fd8c9bf6..cb43820d4930f 100644 --- a/public/app/percona/inventory/Tabs/Nodes.tsx +++ b/public/app/percona/inventory/Tabs/Nodes.tsx @@ -51,8 +51,8 @@ export const NodesTab = () => { const styles = useStyles2(getStyles); const dispatch = useAppDispatch(); - const mappedNodes: Node[] = useMemo( - (): Node[] => nodeFromDbMapper(nodes).sort((a, b) => a.nodeName.localeCompare(b.nodeName)), + const mappedNodes = useMemo( + () => nodeFromDbMapper(nodes).sort((a, b) => a.nodeName.localeCompare(b.nodeName)), [nodes] ); From 17f05474fd2ed54f566c81c90427a3cce85f71e3 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Thu, 19 Sep 2024 17:16:42 +0300 Subject: [PATCH 13/30] Updated tests - partial --- .../NodesAgents/NodesAgents.test.tsx | 84 ++++++++++--------- .../NodesAgents/NodesAgents1.test.tsx | 57 +++++++++++++ .../NodesAgents/NodesAgentsOld.test.tsx | 44 ++++++++++ .../inventory/__mocks__/Inventory.service.ts | 48 ++++++++++- 4 files changed, 193 insertions(+), 40 deletions(-) create mode 100644 public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents1.test.tsx create mode 100644 public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgentsOld.test.tsx diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index 2b6b2fd515789..3f087e7b9c4c5 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -1,57 +1,63 @@ -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; -import React from 'react'; -import { Form } from 'react-final-form'; -import { Provider } from 'react-redux'; -import selectEvent from 'react-select-event'; +//import { render, screen, waitFor } from '@testing-library/react'; +//import React from 'react'; +//import { Form } from 'react-final-form'; +//import { Provider } from 'react-redux'; +//import selectEvent from 'react-select-event'; -import * as NodesReducer from 'app/percona/shared/core/reducers/nodes/nodes'; -import { configureStore } from 'app/store/configureStore'; +//import { configureStore } from 'app/store/configureStore'; -import { NodesAgents } from './NodesAgents'; +//import { NodesAgents } from './NodesAgents'; +// import { nodesMockMultipleAgentsNoPMMServer, nodesMock } from 'app/percona/inventory/__mocks__/Inventory.service'; +// import { fetchNodesAction } from 'app/percona/shared/core/reducers/nodes/nodes'; +//import { FormApi } from 'final-form'; -const fetchNodesActionActionSpy = jest.spyOn(NodesReducer, 'fetchNodesAction'); +// const fetchNodesActionActionSpy = jest.mocked(fetchNodesAction); jest.mock('app/percona/inventory/Inventory.service'); -const submitMock = jest.fn(); +/*describe('Nodes Agents:: ', () => { -describe('Nodes Agents:: ', () => { + let store = configureStore(); + let formAPI: FormApi; render( - +
( - - - - )} + onSubmit={jest.fn()} + render={({ form }) => { + formAPI=form; + return + }} />
- ); + );*/ - it('should change the list of agents when changing the nodes', async () => { +/* it('should pick the first agent when the selected node is not pmm-server', async () => { + fetchNodesActionActionSpy.mockImplementation(nodesMockMultipleAgentsNoPMMServer); await waitFor(() => { expect(fetchNodesActionActionSpy).toHaveBeenCalled(); }); - const form = screen.getByTestId('node-agents-form'); - const nodesSelect = screen.getByLabelText('Nodes'); - await selectEvent.select(nodesSelect, 'pmm-server', { container: document.body }); - - fireEvent.submit(form); - - expect(submitMock).toHaveBeenCalledWith( - expect.objectContaining({ - node: expect.objectContaining({ - value: 'pmm-server', - }), - pmm_agent_id: expect.objectContaining({ - value: 'pmm-agent', - }), - }), - expect.anything(), - expect.anything() - ); + await selectEvent.select(nodesSelect, ['pmm-server'], { container: document.body }); + + const agentsSelect = screen.getByLabelText('Agents'); + const formValues = formAPI.getState().values; + expect(formValues.pmm_agent_id.value).toBe('pmm-agent'); + expect(formValues.node.value).toBe('pmm-server'); }); -}); + + it('should pick the pmm-server from the list of agents when pmm-server node is choosen', async () => { + fetchNodesActionActionSpy.mockImplementation(nodesMockMultipleAgentsNoPMMServer); + await waitFor(() => { + expect(fetchNodesActionActionSpy).toHaveBeenCalled(); + }); + const nodesSelect = screen.getByLabelText('Nodes'); + await selectEvent.select(nodesSelect, ['pmm-server'], { container: document.body }); + + const agentsSelect = screen.getByLabelText('Agents'); + const formValues = formAPI.getState().values; + expect(formValues.pmm_agent_id.value).toBe('pmm-agent'); + expect(formValues.node.value).toBe('pmm-server'); + });*/ + +//}); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents1.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents1.test.tsx new file mode 100644 index 0000000000000..9e3105c7e22db --- /dev/null +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents1.test.tsx @@ -0,0 +1,57 @@ +// import { fireEvent, render, screen, waitFor } from '@testing-library/react'; + import { render } from '@testing-library/react'; +import React from 'react'; +import { Form } from 'react-final-form'; +import { Provider } from 'react-redux'; +// import selectEvent from 'react-select-event'; + +import { configureStore } from 'app/store/configureStore'; + +import { NodesAgents } from './NodesAgents'; + +// const fetchNodesActionActionSpy = jest.spyOn(NodesReducer, 'fetchNodesAction'); + +jest.mock('app/percona/inventory/Inventory.service'); + +const submitMock = jest.fn(); + +describe('Nodes Agents:: ', () => { + render( + +
( + + + + )} + /> +
+ ); + + /*it('should change the list of agents when changing the nodes', async () => { + await waitFor(() => { + expect(fetchNodesActionActionSpy).toHaveBeenCalled(); + }); + + const form = screen.getByTestId('node-agents-form'); + + const nodesSelect = screen.getByLabelText('Nodes'); + await selectEvent.select(nodesSelect, 'pmm-server', { container: document.body }); + + fireEvent.submit(form); + + expect(submitMock).toHaveBeenCalledWith( + expect.objectContaining({ + node: expect.objectContaining({ + value: 'pmm-server', + }), + pmm_agent_id: expect.objectContaining({ + value: 'pmm-agent', + }), + }), + expect.anything(), + expect.anything() + ); + });*/ +}); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgentsOld.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgentsOld.test.tsx new file mode 100644 index 0000000000000..a2c5215fce380 --- /dev/null +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgentsOld.test.tsx @@ -0,0 +1,44 @@ +import { render, screen, waitFor } from '@testing-library/react'; +import React from 'react'; +import { Provider } from 'react-redux'; + +import { configureStore } from 'app/store/configureStore'; + +import { NodesAgents } from './NodesAgents'; +import { Form } from 'react-final-form'; +import * as NodesReducer from 'app/percona/shared/core/reducers/nodes/nodes'; +import selectEvent from 'react-select-event'; +import { FormApi } from 'final-form'; + +const fetchNodesActionActionSpy = jest.spyOn(NodesReducer, 'fetchNodesAction'); + +jest.mock('app/percona/inventory/Inventory.service'); + +describe('Nodes Agents:: ', () => { + let store = configureStore(); + let formAPI: FormApi; + render( + +
{ + formAPI = form; + return ; + }} + /> +
+ ); + + it('should pick the pmm-server agent when pmm-server node is picked', async () => { + await waitFor(() => { + expect(fetchNodesActionActionSpy).toHaveBeenCalled(); + }); + const nodesSelect = screen.getByLabelText('Nodes'); + await selectEvent.select(nodesSelect, ['pmm-server'], { container: document.body }); + + // const agentsSelect = screen.getByLabelText('Agents'); + const formValues = formAPI.getState().values; + expect(formValues.pmm_agent_id.value).toBe('pmm-server'); + expect(formValues.node.value).toBe('pmm-server'); + }); +}); diff --git a/public/app/percona/inventory/__mocks__/Inventory.service.ts b/public/app/percona/inventory/__mocks__/Inventory.service.ts index 118935a08ad2b..3148ad6bcc4c1 100644 --- a/public/app/percona/inventory/__mocks__/Inventory.service.ts +++ b/public/app/percona/inventory/__mocks__/Inventory.service.ts @@ -30,7 +30,7 @@ export const stubs: DBServiceList = { ], }; -const nodesMock = [ +export const nodesMock = [ { node_id: 'pmm-server', node_type: 'generic', @@ -71,6 +71,52 @@ const nodesMock = [ }, ]; +export const nodesMockMultipleAgentsNoPMMServer = [ + { + node_id: '324234234', + node_name: 'node1', + custom_labels: {}, + machine_id: '', + distro: '', + node_model: '', + container_id: '', + container_name: '', + address: '127.0.0.1', + region: '', + az: '', + created_at: '2024-08-20T08:05:31.079300Z', + updated_at: '2024-08-20T08:05:31.079300Z', + status: ServiceStatus.UP, + agents: [ + { + agent_id: '05af4544-8fd0-4788-b841-89ed6caa9ac1', + agent_type: AgentType.nodeExporter, + status: ServiceAgentStatus.RUNNING, + is_connected: false, + }, + { + agent_id: '12132132', + agent_type: AgentType.amazonRdsMysql, + status: ServiceAgentStatus.RUNNING, + is_connected: true, + }, + { + agent_id: '4534534534534', + agent_type: AgentType.externalExporter, + status: ServiceAgentStatus.RUNNING, + is_connected: true, + }, + ], + services: [ + { + service_id: '291afb9b-2ae0-41d1-a173-f1a138cf1725', + service_type: ServiceType.posgresql, + service_name: 'pmm-server-postgresql', + }, + ], + }, +]; + export const InventoryService = jest.genMockFromModule( 'app/percona/inventory/Inventory.service' ).InventoryService; From fee3eedb8057ff0aa2183e2c7cd174b96d364a7c Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Fri, 20 Sep 2024 11:06:51 +0300 Subject: [PATCH 14/30] Partially tests --- .../NodesAgents/NodesAgents.test.tsx | 32 +++++++++---------- .../NodesAgents/NodesAgents1.test.tsx | 12 +++---- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index 3f087e7b9c4c5..7a944fea47c84 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -1,21 +1,21 @@ -//import { render, screen, waitFor } from '@testing-library/react'; -//import React from 'react'; -//import { Form } from 'react-final-form'; -//import { Provider } from 'react-redux'; -//import selectEvent from 'react-select-event'; +import { render, screen, waitFor } from '@testing-library/react'; +import React from 'react'; +import { Form } from 'react-final-form'; +import { Provider } from 'react-redux'; +import selectEvent from 'react-select-event'; -//import { configureStore } from 'app/store/configureStore'; +import { configureStore } from 'app/store/configureStore'; -//import { NodesAgents } from './NodesAgents'; -// import { nodesMockMultipleAgentsNoPMMServer, nodesMock } from 'app/percona/inventory/__mocks__/Inventory.service'; -// import { fetchNodesAction } from 'app/percona/shared/core/reducers/nodes/nodes'; -//import { FormApi } from 'final-form'; +import { NodesAgents } from './NodesAgents'; +import { nodesMockMultipleAgentsNoPMMServer, nodesMock } from 'app/percona/inventory/__mocks__/Inventory.service'; +import { fetchNodesAction } from 'app/percona/shared/core/reducers/nodes/nodes'; +import { FormApi } from 'final-form'; -// const fetchNodesActionActionSpy = jest.mocked(fetchNodesAction); +const fetchNodesActionActionSpy = jest.mocked(fetchNodesAction); jest.mock('app/percona/inventory/Inventory.service'); -/*describe('Nodes Agents:: ', () => { +describe('Nodes Agents:: ', () => { let store = configureStore(); let formAPI: FormApi; @@ -29,9 +29,9 @@ jest.mock('app/percona/inventory/Inventory.service'); }} />
- );*/ + ); -/* it('should pick the first agent when the selected node is not pmm-server', async () => { + it('should pick the first agent when the selected node is not pmm-server', async () => { fetchNodesActionActionSpy.mockImplementation(nodesMockMultipleAgentsNoPMMServer); await waitFor(() => { expect(fetchNodesActionActionSpy).toHaveBeenCalled(); @@ -58,6 +58,6 @@ jest.mock('app/percona/inventory/Inventory.service'); const formValues = formAPI.getState().values; expect(formValues.pmm_agent_id.value).toBe('pmm-agent'); expect(formValues.node.value).toBe('pmm-server'); - });*/ + }); -//}); +}); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents1.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents1.test.tsx index 9e3105c7e22db..fb45e2cdd9598 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents1.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents1.test.tsx @@ -1,15 +1,15 @@ -// import { fireEvent, render, screen, waitFor } from '@testing-library/react'; - import { render } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import React from 'react'; import { Form } from 'react-final-form'; import { Provider } from 'react-redux'; -// import selectEvent from 'react-select-event'; +import selectEvent from 'react-select-event'; +import * as NodesReducer from 'app/percona/shared/core/reducers/nodes/nodes.ts'; import { configureStore } from 'app/store/configureStore'; import { NodesAgents } from './NodesAgents'; -// const fetchNodesActionActionSpy = jest.spyOn(NodesReducer, 'fetchNodesAction'); +const fetchNodesActionActionSpy = jest.spyOn(NodesReducer, 'fetchNodesAction'); jest.mock('app/percona/inventory/Inventory.service'); @@ -29,7 +29,7 @@ describe('Nodes Agents:: ', () => {
); - /*it('should change the list of agents when changing the nodes', async () => { + it('should change the list of agents when changing the nodes', async () => { await waitFor(() => { expect(fetchNodesActionActionSpy).toHaveBeenCalled(); }); @@ -53,5 +53,5 @@ describe('Nodes Agents:: ', () => { expect.anything(), expect.anything() ); - });*/ + }); }); From 44c2d5ded87bb6e01076809e3f1918566fa37ab2 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Fri, 20 Sep 2024 13:09:33 +0300 Subject: [PATCH 15/30] Fixed tests --- .../FormParts/FormParts.messages.ts | 4 +- .../NodesAgents/NodesAgents.test.tsx | 126 +++++++++++++----- .../FormParts/NodesAgents/NodesAgents.tsx | 10 +- .../NodesAgents/NodesAgents1.test.tsx | 57 -------- .../NodesAgents/NodesAgentsOld.test.tsx | 44 ------ .../inventory/__mocks__/Inventory.service.ts | 4 +- 6 files changed, 109 insertions(+), 136 deletions(-) delete mode 100644 public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents1.test.tsx delete mode 100644 public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgentsOld.test.tsx diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.messages.ts b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.messages.ts index 6b5425e36913b..99482003a9c8a 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.messages.ts +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.messages.ts @@ -20,8 +20,8 @@ export const Messages = { password: 'Password', }, nodesAgents: { - nodes: "Nodes", - agents: "Agents" + nodes: 'Nodes', + agents: 'Agents', }, mainDetails: { address: 'Hostname', diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index 7a944fea47c84..d7661df43afa8 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -1,53 +1,67 @@ -import { render, screen, waitFor } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { FormApi } from 'final-form'; import React from 'react'; import { Form } from 'react-final-form'; import { Provider } from 'react-redux'; import selectEvent from 'react-select-event'; -import { configureStore } from 'app/store/configureStore'; - -import { NodesAgents } from './NodesAgents'; +import { InventoryService } from 'app/percona/inventory/Inventory.service'; import { nodesMockMultipleAgentsNoPMMServer, nodesMock } from 'app/percona/inventory/__mocks__/Inventory.service'; import { fetchNodesAction } from 'app/percona/shared/core/reducers/nodes/nodes'; -import { FormApi } from 'final-form'; +import * as NodesReducer from 'app/percona/shared/core/reducers/nodes/nodes'; +import { configureStore } from 'app/store/configureStore'; -const fetchNodesActionActionSpy = jest.mocked(fetchNodesAction); +import { NodesAgents } from './NodesAgents'; -jest.mock('app/percona/inventory/Inventory.service'); +const fetchNodesActionActionSpy = jest.spyOn(NodesReducer, 'fetchNodesAction'); describe('Nodes Agents:: ', () => { - - let store = configureStore(); let formAPI: FormApi; - render( - - { - formAPI=form; - return - }} - /> - - ); - - it('should pick the first agent when the selected node is not pmm-server', async () => { - fetchNodesActionActionSpy.mockImplementation(nodesMockMultipleAgentsNoPMMServer); + const submitMock = jest.fn(); + + function setup() { + render( + + { + formAPI = form; + return ( + + + + ); + }} + /> + + ); + } + + it('should not pick any agent when the selected node is not pmm-server', async () => { + jest + .spyOn(InventoryService, 'getNodes') + .mockReturnValue(Promise.resolve({ nodes: nodesMockMultipleAgentsNoPMMServer })); + setup(); await waitFor(() => { expect(fetchNodesActionActionSpy).toHaveBeenCalled(); }); const nodesSelect = screen.getByLabelText('Nodes'); - await selectEvent.select(nodesSelect, ['pmm-server'], { container: document.body }); + await selectEvent.select(nodesSelect, [nodesMockMultipleAgentsNoPMMServer[0].node_name], { + container: document.body, + }); - const agentsSelect = screen.getByLabelText('Agents'); const formValues = formAPI.getState().values; - expect(formValues.pmm_agent_id.value).toBe('pmm-agent'); - expect(formValues.node.value).toBe('pmm-server'); + expect(formValues.pmm_agent_id).toBe(undefined); + expect(formValues.node.value).toBe(nodesMockMultipleAgentsNoPMMServer[0].node_id); }); - it('should pick the pmm-server from the list of agents when pmm-server node is choosen', async () => { - fetchNodesActionActionSpy.mockImplementation(nodesMockMultipleAgentsNoPMMServer); + it('should pick the pmm-server from the list of agents when pmm-server node is chosen', async () => { + InventoryService.getNodes = () => + Promise.resolve({ + nodes: nodesMock, + }); + setup(); await waitFor(() => { expect(fetchNodesActionActionSpy).toHaveBeenCalled(); }); @@ -56,8 +70,60 @@ describe('Nodes Agents:: ', () => { const agentsSelect = screen.getByLabelText('Agents'); const formValues = formAPI.getState().values; - expect(formValues.pmm_agent_id.value).toBe('pmm-agent'); + expect(formValues.pmm_agent_id.value).toBe('pmm-server'); expect(formValues.node.value).toBe('pmm-server'); }); + it('should change the address to localhost when the agent id is not pmmServer', async () => { + InventoryService.getNodes = () => + Promise.resolve({ + nodes: nodesMockMultipleAgentsNoPMMServer, + }); + setup(); + await waitFor(() => { + expect(fetchNodesActionActionSpy).toHaveBeenCalled(); + }); + const nodesSelect = screen.getByLabelText('Nodes'); + const agentsSelect = screen.getByLabelText('Agents'); + await selectEvent.select(nodesSelect, [nodesMockMultipleAgentsNoPMMServer[0].node_name], { + container: document.body, + }); + await selectEvent.select(agentsSelect, [nodesMockMultipleAgentsNoPMMServer[0].agents[0].agent_id], { + container: document.body, + }); + + const formValues = formAPI.getState().values; + expect(formValues.address).toBe('localhost'); + }); + + it('should have the node/agent selected values when submit', async () => { + InventoryService.getNodes = () => + Promise.resolve({ + nodes: nodesMock, + }); + setup(); + await waitFor(() => { + expect(fetchNodesActionActionSpy).toHaveBeenCalled(); + }); + + const form = screen.getByTestId('node-agents-form'); + + const nodesSelect = screen.getByLabelText('Nodes'); + await selectEvent.select(nodesSelect, 'pmm-server', { container: document.body }); + + fireEvent.submit(form); + + expect(submitMock).toHaveBeenCalledWith( + expect.objectContaining({ + node: expect.objectContaining({ + value: 'pmm-server', + }), + pmm_agent_id: expect.objectContaining({ + value: 'pmm-server', + }), + }), + expect.anything(), + expect.anything() + ); + }); }); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx index 18e2513c86518..3d406c587e326 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx @@ -39,6 +39,14 @@ export const NodesAgents: FC = ({ form }) => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const changeAgentValue = (value: AgentsOption) => { + setSelectedAgent(value); + + if (value.label !== agentId.pmmServer) { + form?.change('address', 'localhost'); + } + }; + const setNodeAndAgent = (value: NodesOption) => { setSelectedNode(value); @@ -87,7 +95,7 @@ export const NodesAgents: FC = ({ form }) => { options={selectedNode?.agents || []} name="pmm_agent_id" data-testid="agents-selectbox" - onChange={(event) => setSelectedAgent(event as AgentsOption)} + onChange={(event) => changeAgentValue(event as AgentsOption)} className={styles.selectField} aria-label={Messages.form.labels.nodesAgents.agents} /> diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents1.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents1.test.tsx deleted file mode 100644 index fb45e2cdd9598..0000000000000 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents1.test.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; -import React from 'react'; -import { Form } from 'react-final-form'; -import { Provider } from 'react-redux'; -import selectEvent from 'react-select-event'; - -import * as NodesReducer from 'app/percona/shared/core/reducers/nodes/nodes.ts'; -import { configureStore } from 'app/store/configureStore'; - -import { NodesAgents } from './NodesAgents'; - -const fetchNodesActionActionSpy = jest.spyOn(NodesReducer, 'fetchNodesAction'); - -jest.mock('app/percona/inventory/Inventory.service'); - -const submitMock = jest.fn(); - -describe('Nodes Agents:: ', () => { - render( - -
( - - - - )} - /> -
- ); - - it('should change the list of agents when changing the nodes', async () => { - await waitFor(() => { - expect(fetchNodesActionActionSpy).toHaveBeenCalled(); - }); - - const form = screen.getByTestId('node-agents-form'); - - const nodesSelect = screen.getByLabelText('Nodes'); - await selectEvent.select(nodesSelect, 'pmm-server', { container: document.body }); - - fireEvent.submit(form); - - expect(submitMock).toHaveBeenCalledWith( - expect.objectContaining({ - node: expect.objectContaining({ - value: 'pmm-server', - }), - pmm_agent_id: expect.objectContaining({ - value: 'pmm-agent', - }), - }), - expect.anything(), - expect.anything() - ); - }); -}); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgentsOld.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgentsOld.test.tsx deleted file mode 100644 index a2c5215fce380..0000000000000 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgentsOld.test.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { render, screen, waitFor } from '@testing-library/react'; -import React from 'react'; -import { Provider } from 'react-redux'; - -import { configureStore } from 'app/store/configureStore'; - -import { NodesAgents } from './NodesAgents'; -import { Form } from 'react-final-form'; -import * as NodesReducer from 'app/percona/shared/core/reducers/nodes/nodes'; -import selectEvent from 'react-select-event'; -import { FormApi } from 'final-form'; - -const fetchNodesActionActionSpy = jest.spyOn(NodesReducer, 'fetchNodesAction'); - -jest.mock('app/percona/inventory/Inventory.service'); - -describe('Nodes Agents:: ', () => { - let store = configureStore(); - let formAPI: FormApi; - render( - -
{ - formAPI = form; - return ; - }} - /> -
- ); - - it('should pick the pmm-server agent when pmm-server node is picked', async () => { - await waitFor(() => { - expect(fetchNodesActionActionSpy).toHaveBeenCalled(); - }); - const nodesSelect = screen.getByLabelText('Nodes'); - await selectEvent.select(nodesSelect, ['pmm-server'], { container: document.body }); - - // const agentsSelect = screen.getByLabelText('Agents'); - const formValues = formAPI.getState().values; - expect(formValues.pmm_agent_id.value).toBe('pmm-server'); - expect(formValues.node.value).toBe('pmm-server'); - }); -}); diff --git a/public/app/percona/inventory/__mocks__/Inventory.service.ts b/public/app/percona/inventory/__mocks__/Inventory.service.ts index 3148ad6bcc4c1..a8dd5909ce453 100644 --- a/public/app/percona/inventory/__mocks__/Inventory.service.ts +++ b/public/app/percona/inventory/__mocks__/Inventory.service.ts @@ -90,13 +90,13 @@ export const nodesMockMultipleAgentsNoPMMServer = [ agents: [ { agent_id: '05af4544-8fd0-4788-b841-89ed6caa9ac1', - agent_type: AgentType.nodeExporter, + agent_type: AgentType.pmmAgent, status: ServiceAgentStatus.RUNNING, is_connected: false, }, { agent_id: '12132132', - agent_type: AgentType.amazonRdsMysql, + agent_type: AgentType.pmmAgent, status: ServiceAgentStatus.RUNNING, is_connected: true, }, From d64b7e8df0e40b903c64a9b41be7a9fc9038303f Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:33:05 +0300 Subject: [PATCH 16/30] Added node_type to node mocks and fixed eslint for NodesAgents --- .../FormParts/NodesAgents/NodesAgents.test.tsx | 2 -- public/app/percona/inventory/__mocks__/Inventory.service.ts | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index d7661df43afa8..e3dc4287c4ff4 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -7,7 +7,6 @@ import selectEvent from 'react-select-event'; import { InventoryService } from 'app/percona/inventory/Inventory.service'; import { nodesMockMultipleAgentsNoPMMServer, nodesMock } from 'app/percona/inventory/__mocks__/Inventory.service'; -import { fetchNodesAction } from 'app/percona/shared/core/reducers/nodes/nodes'; import * as NodesReducer from 'app/percona/shared/core/reducers/nodes/nodes'; import { configureStore } from 'app/store/configureStore'; @@ -68,7 +67,6 @@ describe('Nodes Agents:: ', () => { const nodesSelect = screen.getByLabelText('Nodes'); await selectEvent.select(nodesSelect, ['pmm-server'], { container: document.body }); - const agentsSelect = screen.getByLabelText('Agents'); const formValues = formAPI.getState().values; expect(formValues.pmm_agent_id.value).toBe('pmm-server'); expect(formValues.node.value).toBe('pmm-server'); diff --git a/public/app/percona/inventory/__mocks__/Inventory.service.ts b/public/app/percona/inventory/__mocks__/Inventory.service.ts index a8dd5909ce453..864cd45b1fcbe 100644 --- a/public/app/percona/inventory/__mocks__/Inventory.service.ts +++ b/public/app/percona/inventory/__mocks__/Inventory.service.ts @@ -74,6 +74,7 @@ export const nodesMock = [ export const nodesMockMultipleAgentsNoPMMServer = [ { node_id: '324234234', + node_type: 'generic', node_name: 'node1', custom_labels: {}, machine_id: '', From d8318aea71cf5aedabe9810054791d498bb99687 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Fri, 20 Sep 2024 15:04:26 +0300 Subject: [PATCH 17/30] Fixed other tests related to Add Service --- .../AddRemoteInstance.test.tsx | 20 ++++++- .../ExternalServiceConnectionDetails.test.tsx | 23 ++++--- .../FormParts/FormParts.test.tsx | 60 +++++++++++-------- .../HAProxyConnectionDetails.test.tsx | 9 ++- .../MongoDBConnectionDetails.test.tsx | 9 ++- .../MySQLConnectionDetails.test.tsx | 9 ++- .../PostgreSQLConnectionDetails.test.tsx | 15 ++++- 7 files changed, 103 insertions(+), 42 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.test.tsx index 93dd7c141af00..9cef7b6233ea8 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.test.tsx @@ -1,7 +1,9 @@ import { fireEvent, render, screen } from '@testing-library/react'; import React from 'react'; +import { Provider } from 'react-redux'; import { Databases } from 'app/percona/shared/core'; +import { configureStore } from 'app/store/configureStore'; import { InstanceTypesExtra } from '../../panel.types'; @@ -20,7 +22,11 @@ jest.mock('app/percona/shared/helpers/logger', () => { describe('Add remote instance:: ', () => { it('should render correct for mysql and postgres and highlight empty mandatory fields on submit', async () => { const type = Databases.mysql; - render(); + render( + + + + ); expect(screen.getByTestId('address-text-input').classList.contains('invalid')).toBe(false); expect(screen.getByTestId('username-text-input').classList.contains('invalid')).toBe(false); @@ -35,7 +41,11 @@ describe('Add remote instance:: ', () => { it('should render for external service and highlight empty mandatory fields on submit', async () => { const type = InstanceTypesExtra.external; - render(); + render( + + + + ); expect(screen.getByTestId('address-text-input').classList.contains('invalid')).toBe(false); expect(screen.getByTestId('metrics_path-text-input').classList.contains('invalid')).toBe(false); @@ -55,7 +65,11 @@ describe('Add remote instance:: ', () => { it('should render correct for HAProxy and highlight empty mandatory fields on submit', async () => { const type = Databases.haproxy; - render(); + render( + + + + ); expect(screen.getByTestId('address-text-input').classList.contains('invalid')).toBe(false); expect(screen.getByTestId('username-text-input').classList.contains('invalid')).toBe(false); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/ExternalServiceConnectionDetails/ExternalServiceConnectionDetails.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/ExternalServiceConnectionDetails/ExternalServiceConnectionDetails.test.tsx index f5decfb2fa137..cb1524fb44dae 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/ExternalServiceConnectionDetails/ExternalServiceConnectionDetails.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/ExternalServiceConnectionDetails/ExternalServiceConnectionDetails.test.tsx @@ -1,21 +1,26 @@ import { render, fireEvent, screen } from '@testing-library/react'; import React from 'react'; import { Form } from 'react-final-form'; +import { Provider } from 'react-redux'; + +import { configureStore } from 'app/store/configureStore'; import { ExternalServiceConnectionDetails } from './ExternalServiceConnectionDetails'; describe('Add remote instance:: ', () => { it('should render correct for mysql and postgres and highlight empty mandatory fields on submit', async () => { render( - { - changeValue(state, field, () => value); - }, - }} - render={({ form }) => } - /> + + { + changeValue(state, field, () => value); + }, + }} + render={({ form }) => } + /> + ); const metricsParametrsRadioState = screen.getByTestId('metricsParameters-radio-state'); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.test.tsx index 64ab6b28cf813..f7050cf756c07 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.test.tsx @@ -2,8 +2,10 @@ import { render, screen } from '@testing-library/react'; import { FormApi, FormState } from 'final-form'; import React from 'react'; import { Form } from 'react-final-form'; +import { Provider } from 'react-redux'; import { Databases } from 'app/percona/shared/core'; +import { configureStore } from 'app/store/configureStore'; import { AdditionalOptionsFormPart, getAdditionalOptions } from './AdditionalOptions/AdditionalOptions'; import { ExternalServiceConnectionDetails } from './ExternalServiceConnectionDetails/ExternalServiceConnectionDetails'; @@ -20,14 +22,16 @@ const form: Partial = { describe('MainDetailsFormPart ::', () => { it('should disable fields with sat isRDS flag', async () => { const { container } = render( - } - /> + + } + /> + ); const fields = container.querySelectorAll('input'); - expect(fields.length).toBe(5); + expect(fields.length).toBe(8); expect(screen.getByTestId('address-text-input')).toBeDisabled(); expect(screen.getByTestId('serviceName-text-input')).not.toBeDisabled(); @@ -38,14 +42,16 @@ describe('MainDetailsFormPart ::', () => { it('should disable fields with not sat isRDS flag', async () => { const { container } = render( - } - /> + + } + /> + ); const fields = container.querySelectorAll('input'); - expect(fields.length).toBe(5); + expect(fields.length).toBe(8); expect(screen.getByTestId('address-text-input')).not.toBeDisabled(); expect(screen.getByTestId('serviceName-text-input')).not.toBeDisabled(); @@ -58,10 +64,12 @@ describe('MainDetailsFormPart ::', () => { describe('ExternalServiceConnectionDetails ::', () => { it('should render', async () => { const { container } = render( - } - /> + + } + /> + ); const fields = container.querySelectorAll('input'); @@ -89,17 +97,19 @@ describe('AdditionalOptionsFormPart ::', () => { }; render( - ( - - )} - /> + + ( + + )} + /> + ); expect(screen.getByTestId('skip_connection_check-checkbox-input')).toBeInTheDocument(); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/HAProxyConnectionDetails/HAProxyConnectionDetails.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/HAProxyConnectionDetails/HAProxyConnectionDetails.test.tsx index d33f2db214fef..54ee600051076 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/HAProxyConnectionDetails/HAProxyConnectionDetails.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/HAProxyConnectionDetails/HAProxyConnectionDetails.test.tsx @@ -1,12 +1,19 @@ import { fireEvent, render, screen } from '@testing-library/react'; import React from 'react'; import { Form } from 'react-final-form'; +import { Provider } from 'react-redux'; + +import { configureStore } from 'app/store/configureStore'; import { HAProxyConnectionDetails } from './HAProxyConnectionDetails'; describe('HAProxy connection details:: ', () => { it('should trim username and password values right', () => { - render( } />); + render( + + } /> + + ); const userNameTextInput = screen.getByTestId('username-text-input'); fireEvent.change(userNameTextInput, { target: { value: ' test ' } }); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MongoDBConnectionDetails/MongoDBConnectionDetails.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MongoDBConnectionDetails/MongoDBConnectionDetails.test.tsx index 9d2548c63425a..8057d857b0813 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MongoDBConnectionDetails/MongoDBConnectionDetails.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MongoDBConnectionDetails/MongoDBConnectionDetails.test.tsx @@ -1,12 +1,19 @@ import { render, screen, fireEvent } from '@testing-library/react'; import React from 'react'; import { Form } from 'react-final-form'; +import { Provider } from 'react-redux'; + +import { configureStore } from 'app/store/configureStore'; import { MongoDBConnectionDetails } from './MongoDBConnectionDetails'; describe('MongoDB connection details:: ', () => { it('should have max query length attribute', () => { - render( } />); + render( + + } /> + + ); const textInput = screen.getByTestId('maxQueryLength-text-input'); fireEvent.change(textInput, { target: { value: '1000' } }); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.test.tsx index f814b359556f0..902f9960fe5e6 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/MySQLConnectionDetails/MySQLConnectionDetails.test.tsx @@ -1,12 +1,19 @@ import { render, screen, fireEvent } from '@testing-library/react'; import React from 'react'; import { Form } from 'react-final-form'; +import { Provider } from 'react-redux'; + +import { configureStore } from 'app/store/configureStore'; import { MySQLConnectionDetails } from './MySQLConnectionDetails'; describe('MySQL connection details:: ', () => { it('should have max query length attribute', () => { - render( } />); + render( + + } /> + + ); const textInput = screen.getByTestId('maxQueryLength-text-input'); fireEvent.change(textInput, { target: { value: '1000' } }); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.test.tsx index c169872521614..4b817753588a9 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/PostgreSQLConnectionDetails/PostgreSQLConnectionDetails.test.tsx @@ -1,12 +1,19 @@ import { render, screen, fireEvent } from '@testing-library/react'; import React from 'react'; import { Form } from 'react-final-form'; +import { Provider } from 'react-redux'; + +import { configureStore } from 'app/store/configureStore'; import { PostgreSQLConnectionDetails } from './PostgreSQLConnectionDetails'; describe('PostgreSQL connection details:: ', () => { it('should have database attribute', () => { - render( } />); + render( + + } /> + + ); const textInput = screen.getByTestId('database-text-input'); fireEvent.change(textInput, { target: { value: 'db1' } }); @@ -15,7 +22,11 @@ describe('PostgreSQL connection details:: ', () => { }); it('should have max query length attribute', () => { - render( } />); + render( + + } /> + + ); const textInput = screen.getByTestId('maxQueryLength-text-input'); fireEvent.change(textInput, { target: { value: '1000' } }); From b95747bd4870e7c0e14a4de5035a34235cdc2da5 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Fri, 20 Sep 2024 15:27:14 +0300 Subject: [PATCH 18/30] More tests fixed --- .../AddRemoteInstance/AddRemoteInstance.service.test.tsx | 7 +++++-- .../AddRemoteInstance/AddRemoteInstance.tools.test.ts | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx index ed5183d5e4e35..038be2063b193 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx @@ -65,6 +65,9 @@ describe('AddRemoteInstanceService:: ', () => { replication_set: 'test', cluster: 'test', custom_labels: 'test:test', + pmm_agent_id: { + value: 'pmm-server' + } }; const payload = { @@ -93,7 +96,7 @@ describe('AddRemoteInstanceService:: ', () => { qan_postgresql_pgstatements_agent: true, metrics_mode: 1, }; - - expect(toPayload(data)).toStrictEqual(payload); + const expected = toPayload(data); + expect(expected).toStrictEqual(payload); }); }); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.test.ts b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.test.ts index 0c9ff829f3c02..007f22a2a44b9 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.test.ts +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.tools.test.ts @@ -23,6 +23,7 @@ describe('Get instance data:: ', () => { port: '5432', metricsParameters: 'manually', schema: 'https', + pmm_agent_id: '', }, }; @@ -77,6 +78,7 @@ describe('Get instance data:: ', () => { port: '27017', metricsParameters: 'manually', schema: 'https', + pmm_agent_id: '', }, }; @@ -100,6 +102,7 @@ describe('Get instance data:: ', () => { port: '3306', metricsParameters: 'manually', schema: 'https', + pmm_agent_id: '', }, }; @@ -123,6 +126,7 @@ describe('Get instance data:: ', () => { port: '6032', metricsParameters: 'manually', schema: 'https', + pmm_agent_id: '', }, }; From 78507cb44677a7367f59bd001680576e6442e842 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Fri, 20 Sep 2024 15:40:53 +0300 Subject: [PATCH 19/30] Fixed prettier --- .../AddRemoteInstance/AddRemoteInstance.service.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx index 038be2063b193..2c679532bab3b 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx @@ -66,8 +66,8 @@ describe('AddRemoteInstanceService:: ', () => { cluster: 'test', custom_labels: 'test:test', pmm_agent_id: { - value: 'pmm-server' - } + value: 'pmm-server', + }, }; const payload = { From ced9f39e401a8e1016b3104a1f577092313952a9 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Sat, 21 Sep 2024 18:39:07 +0300 Subject: [PATCH 20/30] Added spy on console.error --- .../AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index e3dc4287c4ff4..857ecea2cfdec 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -13,6 +13,7 @@ import { configureStore } from 'app/store/configureStore'; import { NodesAgents } from './NodesAgents'; const fetchNodesActionActionSpy = jest.spyOn(NodesReducer, 'fetchNodesAction'); +jest.spyOn(console, 'error').mockImplementation(() => {}); describe('Nodes Agents:: ', () => { let formAPI: FormApi; From c478147de96347b273ad1e5a1e9643d55a56e289 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Sat, 21 Sep 2024 19:12:30 +0300 Subject: [PATCH 21/30] Added test for console error --- .../FormParts/NodesAgents/NodesAgents.test.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index 857ecea2cfdec..c3f82e9601ded 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -13,7 +13,6 @@ import { configureStore } from 'app/store/configureStore'; import { NodesAgents } from './NodesAgents'; const fetchNodesActionActionSpy = jest.spyOn(NodesReducer, 'fetchNodesAction'); -jest.spyOn(console, 'error').mockImplementation(() => {}); describe('Nodes Agents:: ', () => { let formAPI: FormApi; @@ -38,6 +37,8 @@ describe('Nodes Agents:: ', () => { } it('should not pick any agent when the selected node is not pmm-server', async () => { + const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + jest .spyOn(InventoryService, 'getNodes') .mockReturnValue(Promise.resolve({ nodes: nodesMockMultipleAgentsNoPMMServer })); @@ -54,6 +55,9 @@ describe('Nodes Agents:: ', () => { const formValues = formAPI.getState().values; expect(formValues.pmm_agent_id).toBe(undefined); expect(formValues.node.value).toBe(nodesMockMultipleAgentsNoPMMServer[0].node_id); + expect(consoleErrorSpy).toHaveBeenCalled(); + + consoleErrorSpy.mockRestore(); }); it('should pick the pmm-server from the list of agents when pmm-server node is chosen', async () => { From 40fbcbb0caf72c815caa985b92d661971067b762 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Sat, 21 Sep 2024 20:22:14 +0300 Subject: [PATCH 22/30] Added console error check to every test --- .../FormParts/NodesAgents/NodesAgents.test.tsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index c3f82e9601ded..8ccad36239593 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -61,6 +61,8 @@ describe('Nodes Agents:: ', () => { }); it('should pick the pmm-server from the list of agents when pmm-server node is chosen', async () => { + const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + InventoryService.getNodes = () => Promise.resolve({ nodes: nodesMock, @@ -75,9 +77,14 @@ describe('Nodes Agents:: ', () => { const formValues = formAPI.getState().values; expect(formValues.pmm_agent_id.value).toBe('pmm-server'); expect(formValues.node.value).toBe('pmm-server'); + expect(consoleErrorSpy).toHaveBeenCalled(); + + consoleErrorSpy.mockRestore(); }); it('should change the address to localhost when the agent id is not pmmServer', async () => { + const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + InventoryService.getNodes = () => Promise.resolve({ nodes: nodesMockMultipleAgentsNoPMMServer, @@ -97,9 +104,14 @@ describe('Nodes Agents:: ', () => { const formValues = formAPI.getState().values; expect(formValues.address).toBe('localhost'); + expect(consoleErrorSpy).toHaveBeenCalled(); + + consoleErrorSpy.mockRestore(); }); it('should have the node/agent selected values when submit', async () => { + const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + InventoryService.getNodes = () => Promise.resolve({ nodes: nodesMock, @@ -128,5 +140,8 @@ describe('Nodes Agents:: ', () => { expect.anything(), expect.anything() ); + expect(consoleErrorSpy).toHaveBeenCalled(); + + consoleErrorSpy.mockRestore(); }); }); From 864dfe425279a0cb1f0008220d3111de3f798332 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Mon, 23 Sep 2024 10:33:37 +0300 Subject: [PATCH 23/30] Fixes after PR --- .../AddRemoteInstance.service.test.tsx | 3 +-- .../NodesAgents/NodesAgents.constants.tsx | 4 +--- .../NodesAgents/NodesAgents.test.tsx | 7 ++----- .../FormParts/NodesAgents/NodesAgents.tsx | 21 ++++++++++--------- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx index 2c679532bab3b..a95f556d6fa1c 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx @@ -96,7 +96,6 @@ describe('AddRemoteInstanceService:: ', () => { qan_postgresql_pgstatements_agent: true, metrics_mode: 1, }; - const expected = toPayload(data); - expect(expected).toStrictEqual(payload); + expect(toPayload(data)).toStrictEqual(payload); }); }); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx index f5f201d60f483..262ceefc161b7 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants.tsx @@ -1,3 +1 @@ -export const agentId = { - pmmServer: 'pmm-server', -}; +export const PMM_SERVER_NODE_AGENT_ID = 'pmm-server'; diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index 8ccad36239593..5a4cff059bfbf 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -63,10 +63,7 @@ describe('Nodes Agents:: ', () => { it('should pick the pmm-server from the list of agents when pmm-server node is chosen', async () => { const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - InventoryService.getNodes = () => - Promise.resolve({ - nodes: nodesMock, - }); + jest.spyOn(InventoryService, 'getNodes').mockReturnValue(Promise.resolve({ nodes: nodesMock })); setup(); await waitFor(() => { expect(fetchNodesActionActionSpy).toHaveBeenCalled(); @@ -109,7 +106,7 @@ describe('Nodes Agents:: ', () => { consoleErrorSpy.mockRestore(); }); - it('should have the node/agent selected values when submit', async () => { + it('should have the node/agent selected values when submitted', async () => { const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); InventoryService.getNodes = () => diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx index 3d406c587e326..41ce522b640c2 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx @@ -3,7 +3,7 @@ import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { useStyles2 } from '@grafana/ui'; import { Messages } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.messages'; import { getStyles } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/FormParts.styles'; -import { agentId } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants'; +import { PMM_SERVER_NODE_AGENT_ID } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants'; import { NodesAgentsProps } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.types'; import { GET_NODES_CANCEL_TOKEN } from 'app/percona/inventory/Inventory.constants'; import { AgentsOption, NodesOption } from 'app/percona/inventory/Inventory.types'; @@ -50,17 +50,18 @@ export const NodesAgents: FC = ({ form }) => { const setNodeAndAgent = (value: NodesOption) => { setSelectedNode(value); - if (value.agents && value.agents.length > 1) { - const pmmServerAgent = value.agents.find((item) => item.value === agentId.pmmServer); - if (pmmServerAgent) { - form?.change('pmm_agent_id', pmmServerAgent); - } - } else if (value.agents && value.agents.length === 1) { - form?.change('pmm_agent_id', value.agents[0]); + let selectedAgent: AgentsOption; + if (value.agents?.length > 1) { + selectedAgent = value.agents.find((item) => item.value === agentId.pmmServer); + } else if (value.agents?.length === 1) { + selectedAgent = value.agents[0]; } + if (selectedAgent) { + form?.change('pmm_agent_id', selectedAgent); - if (selectedAgent && selectedAgent.label !== agentId.pmmServer) { - form?.change('address', 'localhost'); + if (selectedAgent.value !== PMM_SERVER_NODE_AGENT_ID) { + form?.change('address', 'localhost'); + } } }; From 68548b76f64c3cf754db42865b264af73e7338c1 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Mon, 23 Sep 2024 11:25:28 +0300 Subject: [PATCH 24/30] Replaced the formAPI with taken values from the form, and added new mock with one non-pmm-server agent --- .../NodesAgents/NodesAgents.test.tsx | 93 ++++++++----------- .../FormParts/NodesAgents/NodesAgents.tsx | 16 ++-- .../inventory/__mocks__/Inventory.service.ts | 41 ++++++++ 3 files changed, 90 insertions(+), 60 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index 5a4cff059bfbf..5ba18bf48e6e8 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -6,7 +6,11 @@ import { Provider } from 'react-redux'; import selectEvent from 'react-select-event'; import { InventoryService } from 'app/percona/inventory/Inventory.service'; -import { nodesMockMultipleAgentsNoPMMServer, nodesMock } from 'app/percona/inventory/__mocks__/Inventory.service'; +import { + nodesMockMultipleAgentsNoPMMServer, + nodesMock, + nodesMockOneAgentNoPMMServer, +} from 'app/percona/inventory/__mocks__/Inventory.service'; import * as NodesReducer from 'app/percona/shared/core/reducers/nodes/nodes'; import { configureStore } from 'app/store/configureStore'; @@ -15,7 +19,6 @@ import { NodesAgents } from './NodesAgents'; const fetchNodesActionActionSpy = jest.spyOn(NodesReducer, 'fetchNodesAction'); describe('Nodes Agents:: ', () => { - let formAPI: FormApi; const submitMock = jest.fn(); function setup() { @@ -23,22 +26,20 @@ describe('Nodes Agents:: ', () => { { - formAPI = form; - return ( - - - - ); - }} + render={({ handleSubmit, form, values }) => ( +
+ +

{values.node?.value}

+

{values.pmm_agent_id?.value}

+

{values.address}

+ + )} />
); } it('should not pick any agent when the selected node is not pmm-server', async () => { - const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - jest .spyOn(InventoryService, 'getNodes') .mockReturnValue(Promise.resolve({ nodes: nodesMockMultipleAgentsNoPMMServer })); @@ -48,71 +49,60 @@ describe('Nodes Agents:: ', () => { }); const nodesSelect = screen.getByLabelText('Nodes'); - await selectEvent.select(nodesSelect, [nodesMockMultipleAgentsNoPMMServer[0].node_name], { - container: document.body, - }); - - const formValues = formAPI.getState().values; - expect(formValues.pmm_agent_id).toBe(undefined); - expect(formValues.node.value).toBe(nodesMockMultipleAgentsNoPMMServer[0].node_id); - expect(consoleErrorSpy).toHaveBeenCalled(); + await waitFor(() => + selectEvent.select(nodesSelect, [nodesMockMultipleAgentsNoPMMServer[0].node_name], { + container: document.body, + }) + ); - consoleErrorSpy.mockRestore(); + expect(screen.getByTestId('agent')).toHaveTextContent(''); + expect(screen.getByTestId('node')).toHaveTextContent(nodesMockMultipleAgentsNoPMMServer[0].node_id); }); it('should pick the pmm-server from the list of agents when pmm-server node is chosen', async () => { - const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - jest.spyOn(InventoryService, 'getNodes').mockReturnValue(Promise.resolve({ nodes: nodesMock })); setup(); await waitFor(() => { expect(fetchNodesActionActionSpy).toHaveBeenCalled(); }); const nodesSelect = screen.getByLabelText('Nodes'); - await selectEvent.select(nodesSelect, ['pmm-server'], { container: document.body }); - const formValues = formAPI.getState().values; - expect(formValues.pmm_agent_id.value).toBe('pmm-server'); - expect(formValues.node.value).toBe('pmm-server'); - expect(consoleErrorSpy).toHaveBeenCalled(); + await waitFor(() => + selectEvent.select(nodesSelect, ['pmm-server'], { + container: document.body, + }) + ); - consoleErrorSpy.mockRestore(); + expect(screen.getByTestId('agent')).toHaveTextContent('pmm-server'); + expect(screen.getByTestId('node')).toHaveTextContent('pmm-server'); }); it('should change the address to localhost when the agent id is not pmmServer', async () => { - const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - - InventoryService.getNodes = () => - Promise.resolve({ - nodes: nodesMockMultipleAgentsNoPMMServer, - }); + jest.spyOn(InventoryService, 'getNodes').mockReturnValue(Promise.resolve({ nodes: nodesMockOneAgentNoPMMServer })); setup(); await waitFor(() => { expect(fetchNodesActionActionSpy).toHaveBeenCalled(); }); const nodesSelect = screen.getByLabelText('Nodes'); const agentsSelect = screen.getByLabelText('Agents'); - await selectEvent.select(nodesSelect, [nodesMockMultipleAgentsNoPMMServer[0].node_name], { - container: document.body, - }); - await selectEvent.select(agentsSelect, [nodesMockMultipleAgentsNoPMMServer[0].agents[0].agent_id], { - container: document.body, - }); - const formValues = formAPI.getState().values; - expect(formValues.address).toBe('localhost'); - expect(consoleErrorSpy).toHaveBeenCalled(); + await waitFor(() => + selectEvent.select(nodesSelect, [nodesMockOneAgentNoPMMServer[0].node_name], { + container: document.body, + }) + ); + await waitFor(() => + selectEvent.select(nodesSelect, [nodesMockOneAgentNoPMMServer[0].agents[0].agent_id], { + container: document.body, + }) + ); - consoleErrorSpy.mockRestore(); + expect(screen.getByTestId('address')).toHaveTextContent('localhost'); }); it('should have the node/agent selected values when submitted', async () => { - const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.spyOn(InventoryService, 'getNodes').mockReturnValue(Promise.resolve({ nodes: nodesMock })); - InventoryService.getNodes = () => - Promise.resolve({ - nodes: nodesMock, - }); setup(); await waitFor(() => { expect(fetchNodesActionActionSpy).toHaveBeenCalled(); @@ -137,8 +127,5 @@ describe('Nodes Agents:: ', () => { expect.anything(), expect.anything() ); - expect(consoleErrorSpy).toHaveBeenCalled(); - - consoleErrorSpy.mockRestore(); }); }); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx index 41ce522b640c2..8b2362f2fc2a7 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx @@ -22,7 +22,6 @@ export const NodesAgents: FC = ({ form }) => { const dispatch = useAppDispatch(); const [generateToken] = useCancelToken(); const [selectedNode, setSelectedNode] = useState(); - const [selectedAgent, setSelectedAgent] = useState(); const { nodes } = useSelector(getNodes); const nodesOptions = useMemo(() => nodesOptionsMapper(nodes), [nodes]); @@ -40,10 +39,10 @@ export const NodesAgents: FC = ({ form }) => { }, []); const changeAgentValue = (value: AgentsOption) => { - setSelectedAgent(value); - - if (value.label !== agentId.pmmServer) { + if (value.label !== PMM_SERVER_NODE_AGENT_ID) { form?.change('address', 'localhost'); + } else { + form?.change('address', ''); } }; @@ -51,9 +50,9 @@ export const NodesAgents: FC = ({ form }) => { setSelectedNode(value); let selectedAgent: AgentsOption; - if (value.agents?.length > 1) { - selectedAgent = value.agents.find((item) => item.value === agentId.pmmServer); - } else if (value.agents?.length === 1) { + if (value.agents && value.agents?.length > 1) { + selectedAgent = value.agents.find((item) => item.value === PMM_SERVER_NODE_AGENT_ID); + } else if (value.agents && value.agents?.length === 1) { selectedAgent = value.agents[0]; } if (selectedAgent) { @@ -62,6 +61,9 @@ export const NodesAgents: FC = ({ form }) => { if (selectedAgent.value !== PMM_SERVER_NODE_AGENT_ID) { form?.change('address', 'localhost'); } + } else { + form?.change('pmm_agent_id', undefined); + form?.change('address', ''); } }; diff --git a/public/app/percona/inventory/__mocks__/Inventory.service.ts b/public/app/percona/inventory/__mocks__/Inventory.service.ts index 864cd45b1fcbe..26879e6ee3c13 100644 --- a/public/app/percona/inventory/__mocks__/Inventory.service.ts +++ b/public/app/percona/inventory/__mocks__/Inventory.service.ts @@ -118,6 +118,47 @@ export const nodesMockMultipleAgentsNoPMMServer = [ }, ]; +export const nodesMockOneAgentNoPMMServer = [ + { + node_id: '324234234', + node_type: 'generic', + node_name: 'node2', + custom_labels: {}, + machine_id: '', + distro: '', + node_model: '', + container_id: '', + container_name: '', + address: '127.0.0.1', + region: '', + az: '', + created_at: '2024-08-20T08:05:31.079300Z', + updated_at: '2024-08-20T08:05:31.079300Z', + status: ServiceStatus.UP, + agents: [ + { + agent_id: '12132132', + agent_type: AgentType.pmmAgent, + status: ServiceAgentStatus.RUNNING, + is_connected: true, + }, + { + agent_id: '4534534534534', + agent_type: AgentType.externalExporter, + status: ServiceAgentStatus.RUNNING, + is_connected: true, + }, + ], + services: [ + { + service_id: '291afb9b-2ae0-41d1-a173-f1a138cf1725', + service_type: ServiceType.posgresql, + service_name: 'pmm-server-postgresql', + }, + ], + }, +]; + export const InventoryService = jest.genMockFromModule( 'app/percona/inventory/Inventory.service' ).InventoryService; From 59e041f655cd4eabb50c4339dab26a06c589df26 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Mon, 23 Sep 2024 11:38:10 +0300 Subject: [PATCH 25/30] SelectedAgent can be undefined --- .../FormParts/NodesAgents/NodesAgents.test.tsx | 2 -- .../AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index 5ba18bf48e6e8..7032491920d21 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -1,5 +1,4 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react'; -import { FormApi } from 'final-form'; import React from 'react'; import { Form } from 'react-final-form'; import { Provider } from 'react-redux'; @@ -84,7 +83,6 @@ describe('Nodes Agents:: ', () => { expect(fetchNodesActionActionSpy).toHaveBeenCalled(); }); const nodesSelect = screen.getByLabelText('Nodes'); - const agentsSelect = screen.getByLabelText('Agents'); await waitFor(() => selectEvent.select(nodesSelect, [nodesMockOneAgentNoPMMServer[0].node_name], { diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx index 8b2362f2fc2a7..59a8dc550de77 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.tsx @@ -49,7 +49,7 @@ export const NodesAgents: FC = ({ form }) => { const setNodeAndAgent = (value: NodesOption) => { setSelectedNode(value); - let selectedAgent: AgentsOption; + let selectedAgent: AgentsOption | undefined; if (value.agents && value.agents?.length > 1) { selectedAgent = value.agents.find((item) => item.value === PMM_SERVER_NODE_AGENT_ID); } else if (value.agents && value.agents?.length === 1) { From 09b6adbe1151cb3fe399a8791fdec85452503c68 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Mon, 23 Sep 2024 11:41:30 +0300 Subject: [PATCH 26/30] Clear mock before each test --- .../FormParts/NodesAgents/NodesAgents.test.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index 7032491920d21..07e994c23e57e 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -38,6 +38,10 @@ describe('Nodes Agents:: ', () => { ); } + beforeEach(() => { + submitMock.mockClear(); + }); + it('should not pick any agent when the selected node is not pmm-server', async () => { jest .spyOn(InventoryService, 'getNodes') From 6c07180ffb3d436b88b5d387fa1ca4d7349a784b Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Mon, 23 Sep 2024 12:00:08 +0300 Subject: [PATCH 27/30] Added wait for to last test --- .../FormParts/NodesAgents/NodesAgents.test.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx index 07e994c23e57e..8b677a43b388a 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.test.tsx @@ -113,7 +113,11 @@ describe('Nodes Agents:: ', () => { const form = screen.getByTestId('node-agents-form'); const nodesSelect = screen.getByLabelText('Nodes'); - await selectEvent.select(nodesSelect, 'pmm-server', { container: document.body }); + await waitFor(() => + selectEvent.select(nodesSelect, 'pmm-server', { + container: document.body, + }) + ); fireEvent.submit(form); From 24f3a77e527b03946927c3148c1dea28132f1100 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:57:42 +0300 Subject: [PATCH 28/30] If address is localhost then send node_id instead of add_node, and send metrics_mode=2 if pmm_server --- .../AddRemoteInstance.service.test.tsx | 7 ++++++- .../AddRemoteInstance.service.tsx | 16 ++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx index a95f556d6fa1c..a3dc0beab0a86 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx @@ -68,6 +68,10 @@ describe('AddRemoteInstanceService:: ', () => { pmm_agent_id: { value: 'pmm-server', }, + node: { + value: 'node1', + label: 'node1', + }, }; const payload = { @@ -94,7 +98,8 @@ describe('AddRemoteInstanceService:: ', () => { pmm_agent_id: 'pmm-server', port: '80', qan_postgresql_pgstatements_agent: true, - metrics_mode: 1, + metrics_mode: 2, + node_id: 'node1', }; expect(toPayload(data)).toStrictEqual(payload); }); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx index a40e266221766..edc5208dfb0c7 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx @@ -1,5 +1,6 @@ import { CancelToken } from 'axios'; +import { PMM_SERVER_NODE_AGENT_ID } from 'app/percona/add-instance/components/AddRemoteInstance/FormParts/NodesAgents/NodesAgents.constants'; import { Databases } from 'app/percona/shared/core'; import { apiManagement } from 'app/percona/shared/helpers/api'; @@ -142,13 +143,20 @@ export const toPayload = (values: any, discoverName?: string, type?: InstanceAva data.service_name = data.address; } - if (!values.isAzure && data.add_node === undefined) { + if ( + (!values.isAzure && data.add_node === undefined) || + (data.address !== '127.0.0.1' && data.address !== 'localhost') + ) { data.add_node = { node_name: data.service_name, node_type: 'NODE_TYPE_REMOTE_NODE', }; } + if (data.address === '127.0.0.1' || data.address === 'localhost') { + data.node_id = data.node.value; + } + if (values.isRDS && discoverName) { data.engine = discoverName; } @@ -181,7 +189,11 @@ export const toPayload = (values: any, discoverName?: string, type?: InstanceAva data.pmm_agent_id = values.pmm_agent_id.value; - data.metrics_mode = 1; + if (data.pmm_agent_id === PMM_SERVER_NODE_AGENT_ID) { + data.metrics_mode = 2; + } else { + data.metrics_mode = 1; + } delete data.tracking; delete data.node; From 2618cbf0015bd0480bb954458fc7a141ad13ab6d Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:11:42 +0300 Subject: [PATCH 29/30] Fixes after PR --- .../AddRemoteInstance.service.test.tsx | 6 +----- .../AddRemoteInstance.service.tsx | 15 +++++---------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx index a3dc0beab0a86..3d7a430cc1185 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.test.tsx @@ -91,14 +91,10 @@ describe('AddRemoteInstanceService:: ', () => { custom_labels: { test: 'test', }, - add_node: { - node_name: 'localhost', - node_type: 'NODE_TYPE_REMOTE_NODE', - }, pmm_agent_id: 'pmm-server', port: '80', qan_postgresql_pgstatements_agent: true, - metrics_mode: 2, + metrics_mode: 1, node_id: 'node1', }; expect(toPayload(data)).toStrictEqual(payload); diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx index edc5208dfb0c7..2a181bd06e5a8 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx @@ -143,20 +143,15 @@ export const toPayload = (values: any, discoverName?: string, type?: InstanceAva data.service_name = data.address; } - if ( - (!values.isAzure && data.add_node === undefined) || - (data.address !== '127.0.0.1' && data.address !== 'localhost') - ) { + if (data.address === '127.0.0.1' || data.address === 'localhost') { + data.node_id = data.node.value; + } else if (!values.isAzure && data.add_node === undefined) { data.add_node = { node_name: data.service_name, node_type: 'NODE_TYPE_REMOTE_NODE', }; } - if (data.address === '127.0.0.1' || data.address === 'localhost') { - data.node_id = data.node.value; - } - if (values.isRDS && discoverName) { data.engine = discoverName; } @@ -190,9 +185,9 @@ export const toPayload = (values: any, discoverName?: string, type?: InstanceAva data.pmm_agent_id = values.pmm_agent_id.value; if (data.pmm_agent_id === PMM_SERVER_NODE_AGENT_ID) { - data.metrics_mode = 2; - } else { data.metrics_mode = 1; + } else { + data.metrics_mode = 2; } delete data.tracking; delete data.node; From 09097c3deb3bdec05c29b4b55391c0c6dec75302 Mon Sep 17 00:00:00 2001 From: DoraCretu594118 <103416234+doracretu3pillar@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:21:22 +0300 Subject: [PATCH 30/30] Fixed prettier --- .../components/AddRemoteInstance/AddRemoteInstance.service.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx index 2a181bd06e5a8..5d48b4f9cec81 100644 --- a/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx +++ b/public/app/percona/add-instance/components/AddRemoteInstance/AddRemoteInstance.service.tsx @@ -145,7 +145,7 @@ export const toPayload = (values: any, discoverName?: string, type?: InstanceAva if (data.address === '127.0.0.1' || data.address === 'localhost') { data.node_id = data.node.value; - } else if (!values.isAzure && data.add_node === undefined) { + } else if (!values.isAzure && data.add_node === undefined) { data.add_node = { node_name: data.service_name, node_type: 'NODE_TYPE_REMOTE_NODE',