diff --git a/CHANGELOG.md b/CHANGELOG.md index 8abef82d09..788df565c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Added macOS log collector tab [#6545](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6545) - Add ability to disable the edition of configuration through API endpoints and UI [#6557](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6557) - Added journald log collector tab [#6572](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6572) +- Added HAProxy helper settings to cluster configuration [#6653](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6653) ### Changed diff --git a/docker/imposter/cluster/configuration/com_cluster.json b/docker/imposter/cluster/configuration/com_cluster.json index 4072ebafe8..dc7915acaf 100644 --- a/docker/imposter/cluster/configuration/com_cluster.json +++ b/docker/imposter/cluster/configuration/com_cluster.json @@ -10,7 +10,24 @@ "port": 1516, "bind_addr": "0.0.0.0", "nodes": ["0.0.0.0"], - "hidden": "no" + "hidden": "no", + "haproxy_helper": { + "haproxy_disabled": false, + "haproxy_address": "wazuh-proxy", + "haproxy_user": "haproxy", + "haproxy_password": "haproxy", + "frequency": 60, + "agent_reconnection_stability_time": 60, + "agent_chunk_size": 300, + "haproxy_protocol": "http", + "haproxy_backend": "wazuh_cluster", + "agent_reconnection_time": 5, + "haproxy_port": 5555, + "haproxy_resolver": null, + "imbalance_tolerance": 0.1, + "remove_disconnected_node_after": 240, + "excluded_nodes": [] + } } ], "total_affected_items": 1, diff --git a/plugins/main/public/controllers/management/components/management/configuration/cluster/__snapshots__/cluster.test.js.snap b/plugins/main/public/controllers/management/components/management/configuration/cluster/__snapshots__/cluster.test.js.snap new file mode 100644 index 0000000000..ee05312cc0 --- /dev/null +++ b/plugins/main/public/controllers/management/components/management/configuration/cluster/__snapshots__/cluster.test.js.snap @@ -0,0 +1,1402 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Cluster settings should render the cluster settings 1`] = ` +
+
+
+

+ Main settings +

+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+

+

+
+
+
+
+
+
+
+
+
+
+
+ Cluster status +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Cluster name +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Node name +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Node type +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Master node IP address +
+
+
+
    +
  • +
    +
    + +
    +
    +
  • +
+
+
+
+
+
+
+ Port to listen to cluster communications +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ IP address to listen to cluster communications +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Hide cluster information in alerts +
+
+
+
+
+ +
+
+
+
+
+
+
+
+`; + +exports[`Cluster settings should render the cluster settings with HAProxy helper 1`] = ` +
+
+
+

+ Main settings +

+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+

+

+
+
+
+
+
+
+
+
+
+
+
+ Cluster status +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Cluster name +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Node name +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Node type +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Master node IP address +
+
+
+
    +
  • +
    +
    + +
    +
    +
  • +
+
+
+
+
+
+
+ Port to listen to cluster communications +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ IP address to listen to cluster communications +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Hide cluster information in alerts +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ HAProxy settings +

+
+
+
+
+
+
+
+
+
+
+
+
+
+ HAProxy status +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Address +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ User +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Password +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Port +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Protocol +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Backend +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Frequency +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Agent chunk size +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Agent reconnection time +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Agent reconnection stability time +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Imbalance tolerance +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Remove disconnected node after +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ Excluded nodes +
+
+
+
+
+ +
+
+
+
+
+
+
+
+`; + +exports[`Cluster settings should render the error message when the cluster setting is a string 1`] = ` +
+
+
+
+
+ + + Configuration not available + +
+
+ +
+
+
+ + There was a problem while fetching the configuration for this section. It may be a server problem or the configuration doesn't exist. + +
+
+

+ Click on the + + icon for help. Check the documentation links to learn more about how to configure it. +

+
+
+
+
+
+
+`; diff --git a/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.js b/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.js index b299763d89..823cf48f0c 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.js +++ b/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.js @@ -17,7 +17,7 @@ import WzConfigurationSettingsGroup from '../util-components/configuration-setti import WzConfigurationSettingsHeader from '../util-components/configuration-settings-header'; import WzNoConfig from '../util-components/no-config'; import withWzConfig from '../util-hocs/wz-config'; -import { isString } from '../utils/utils'; +import { isString, renderValueOrNoValue } from '../utils/utils'; import { connect } from 'react-redux'; import { compose } from 'redux'; @@ -38,6 +38,37 @@ const mainSettings = [ { field: 'hidden', label: 'Hide cluster information in alerts' }, ]; +const haproxySettings = [ + { field: 'haproxy_helper.haproxy_disabled', label: 'HAProxy status' }, + { field: 'haproxy_helper.haproxy_address', label: 'Address' }, + { field: 'haproxy_helper.haproxy_user', label: 'User' }, + { field: 'haproxy_helper.haproxy_password', label: 'Password' }, + { field: 'haproxy_helper.haproxy_port', label: 'Port' }, + { field: 'haproxy_helper.haproxy_protocol', label: 'Protocol' }, + { field: 'haproxy_helper.haproxy_backend', label: 'Backend' }, + { field: 'haproxy_helper.frequency', label: 'Frequency' }, + { field: 'haproxy_helper.agent_chunk_size', label: 'Agent chunk size' }, + { + field: 'haproxy_helper.agent_reconnection_time', + label: 'Agent reconnection time', + }, + { + field: 'haproxy_helper.agent_reconnection_stability_time', + label: 'Agent reconnection stability time', + }, + { field: 'haproxy_helper.imbalance_tolerance', label: 'Imbalance tolerance' }, + { + field: 'haproxy_helper.remove_disconnected_node_after', + label: 'Remove disconnected node after', + }, + { field: 'haproxy_helper.haproxy_resolver', label: 'Resolver' }, + { + field: 'haproxy_helper.excluded_nodes', + label: 'Excluded nodes', + render: renderValueOrNoValue, + }, +]; + const helpLinks = [ { text: 'Configuring a cluster', @@ -49,7 +80,7 @@ const helpLinks = [ }, ]; -class WzCluster extends Component { +export class WzCluster extends Component { constructor(props) { super(props); } @@ -58,10 +89,22 @@ class WzCluster extends Component { let mainSettingsConfig = { ...currentConfig['com-cluster'], disabled: - currentConfig['com-cluster'].disabled === 'yes' - ? 'disabled' - : 'enabled', + currentConfig['com-cluster'].disabled === true ? 'disabled' : 'enabled', }; + + if (currentConfig['com-cluster'].haproxy_helper) { + mainSettingsConfig = { + ...mainSettingsConfig, + haproxy_helper: { + ...currentConfig['com-cluster'].haproxy_helper, + haproxy_disabled: + currentConfig['com-cluster'].haproxy_helper.haproxy_disabled === + true + ? 'disabled' + : 'enabled', + }, + }; + } return ( {currentConfig['com-cluster'] && @@ -82,6 +125,13 @@ class WzCluster extends Component { config={mainSettingsConfig} items={mainSettings} /> + {mainSettingsConfig.haproxy_helper && ( + + )} )} diff --git a/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.test.js b/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.test.js new file mode 100644 index 0000000000..26fb86512f --- /dev/null +++ b/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.test.js @@ -0,0 +1,92 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { WzCluster } from './cluster'; + +const basicClusterSettings = { + 'com-cluster': { + disabled: false, + name: 'wazuh1', + node_name: 'master', + node_type: 'master', + key: 'test1234', + port: 1516, + bind_addr: '0.0.0.0', + nodes: ['0.0.0.0'], + hidden: 'no', + }, +}; + +const clusterSettingsWithHaproxyHelper = { + 'com-cluster': { + disabled: false, + name: 'wazuh1', + node_name: 'master', + node_type: 'master', + key: 'test1234', + port: 1516, + bind_addr: '0.0.0.0', + nodes: ['0.0.0.0'], + hidden: 'no', + haproxy_helper: { + haproxy_disabled: false, + haproxy_address: 'wazuh-proxy', + haproxy_user: 'haproxy', + haproxy_password: 'haproxy', + frequency: 60, + agent_reconnection_stability_time: 60, + agent_chunk_size: 300, + haproxy_protocol: 'http', + haproxy_backend: 'wazuh_cluster', + agent_reconnection_time: 5, + haproxy_port: 5555, + haproxy_resolver: null, + imbalance_tolerance: 0.1, + remove_disconnected_node_after: 240, + excluded_nodes: [], + }, + }, +}; + +describe('Cluster settings', () => { + it('should render the cluster settings', () => { + const { container, getByText, queryByText, getByTestId } = render( + , + ); + + expect(container).toMatchSnapshot(); + + expect(getByText('Cluster status')).toBeInTheDocument(); + expect(getByTestId('cluster-status').value).toBe('enabled'); + expect(queryByText('HAProxy settings')).toBeFalsy(); + }); + + it('should render the cluster settings with HAProxy helper', () => { + const { container, getByText, getByTestId } = render( + , + ); + + expect(container).toMatchSnapshot(); + + expect(getByText('Cluster status')).toBeInTheDocument(); + expect(getByTestId('cluster-status').value).toBe('enabled'); + expect(getByText('HAProxy settings')).toBeInTheDocument(); + expect(getByTestId('haproxy-status').value).toBe('enabled'); + expect(getByTestId('user').value).toBe( + clusterSettingsWithHaproxyHelper['com-cluster'].haproxy_helper + .haproxy_user, + ); + }); + + it('should render the error message when the cluster setting is a string', () => { + const { container, getByText, queryByText } = render( + , + ); + + expect(container).toMatchSnapshot(); + + expect(getByText('Configuration not available')).toBeInTheDocument(); + expect(queryByText('Cluster status')).toBeFalsy(); + expect(queryByText('HAProxy settings')).toBeFalsy(); + }); +});