diff --git a/README.md b/README.md index fcfb2f4..440d1f5 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ pip install opn-cli ``` opn-cli plugin install os-firewall opn-cli plugin install os-haproxy + opn-cli plugin install os-node_exporter ``` ## Usage @@ -856,6 +857,8 @@ Commands: status Show gateway states ``` ### Nodeexporter +This feature needs the opnsense plugin os-node_exporter to be installed. + #### Config ``` Usage: opn-cli nodeexporter config [OPTIONS] COMMAND [ARGS]... diff --git a/opnsense_cli/commands/plugin/haproxy/frontend.py b/opnsense_cli/commands/plugin/haproxy/frontend.py index 689e166..a3f4af1 100644 --- a/opnsense_cli/commands/plugin/haproxy/frontend.py +++ b/opnsense_cli/commands/plugin/haproxy/frontend.py @@ -72,12 +72,12 @@ def list(haproxy_frontend_svc: HaproxyFrontendFacade, **kwargs): "ssl_cipherList,ssl_cipherSuites,ssl_hstsEnabled,ssl_hstsIncludeSubDomains,ssl_hstsPreload,ssl_hstsMaxAge," "ssl_clientAuthEnabled,ssl_clientAuthVerify,ssl_clientAuthCAs,ssl_clientAuthCRLs,basicAuthEnabled," "Users,basicAuthUsers,Groups,basicAuthGroups,tuning_maxConnections,tuning_timeoutClient,tuning_timeoutHttpReq," - "tuning_timeoutHttpKeepAlive,Cpus,linkedCpuAffinityRules,logging_dontLogNull,logging_dontLogNormal," + "tuning_timeoutHttpKeepAlive,Cpus,linkedCpuAffinityRules,tuning_shards, logging_dontLogNull,logging_dontLogNormal," "logging_logSeparateErrors,logging_detailedLog,logging_socketStats,stickiness_pattern,stickiness_dataTypes," "stickiness_expire,stickiness_size,stickiness_counter,stickiness_counter_key,stickiness_length," "stickiness_connRatePeriod,stickiness_sessRatePeriod,stickiness_httpReqRatePeriod,stickiness_httpErrRatePeriod," "stickiness_bytesInRatePeriod,stickiness_bytesOutRatePeriod,http2Enabled,http2Enabled_nontls," - "advertised_protocols,forwardFor,connectionBehaviour,customOptions,Actions," + "advertised_protocols,forwardFor,prometheus_enabled,prometheus_path,connectionBehaviour,customOptions,Actions," "linkedActions,Errorfiles,linkedErrorfiles" ), show_default=True, @@ -396,6 +396,19 @@ def show(haproxy_frontend_svc: HaproxyFrontendFacade, **kwargs): default=None, required=False, ) +@click.option( + '--tuning_shards', + help=( + 'This option automatically creates the specified number of listeners for every IP:port' + ' combination and evenly distributes' + ' them among available threads. This can sometimes be useful when using very large thread ' + ' counts where the in-kernel' + ' locking on a single socket starts to cause a significant overhead.' + ), + show_default=True, + default=None, + required=False, +) @click.option( '--logging_dontLogNull/--no-logging_dontLogNull', help=('Enable or disable logging of connections with no data.'), @@ -640,6 +653,22 @@ def show(haproxy_frontend_svc: HaproxyFrontendFacade, **kwargs): default=True, required=True, ) +@click.option( + '--prometheus_enabled/--no-prometheus_enabled', + help=('Enable HAProxy\'s Prometheus exporter.'), + show_default=True, + is_flag=True, + callback=bool_as_string, + default=False, + required=False, +) +@click.option( + '--prometheus_path', + help=('The path where the Prometheus exporter can be accessed.'), + show_default=True, + default='/metrics', + required=False, +) @click.option( '--connectionBehaviour', help=( @@ -652,7 +681,7 @@ def show(haproxy_frontend_svc: HaproxyFrontendFacade, **kwargs): 'close the outgoing server channel as soon as the server has finished ' 'to respond and release some resources earlier.' ), - type=click.Choice(['http-keep-alive', 'http-tunnel', 'httpclose', 'http-server-close', 'forceclose']), + type=click.Choice(['http-keep-alive', 'httpclose', 'http-server-close']), multiple=False, callback=tuple_to_csv, show_default=True, @@ -736,6 +765,7 @@ def create(haproxy_frontend_svc: HaproxyFrontendFacade, **kwargs): "tuning_timeoutHttpReq": kwargs['tuning_timeouthttpreq'], "tuning_timeoutHttpKeepAlive": kwargs['tuning_timeouthttpkeepalive'], "linkedCpuAffinityRules": kwargs['linkedcpuaffinityrules'], + "tuning_shards": kwargs['tuning_shards'], "logging_dontLogNull": kwargs['logging_dontlognull'], "logging_dontLogNormal": kwargs['logging_dontlognormal'], "logging_logSeparateErrors": kwargs['logging_logseparateerrors'], @@ -758,6 +788,8 @@ def create(haproxy_frontend_svc: HaproxyFrontendFacade, **kwargs): "http2Enabled_nontls": kwargs['http2enabled_nontls'], "advertised_protocols": kwargs['advertised_protocols'], "forwardFor": kwargs['forwardfor'], + "prometheus_enabled": kwargs['prometheus_enabled'], + "prometheus_path": kwargs['prometheus_path'], "connectionBehaviour": kwargs['connectionbehaviour'], "customOptions": kwargs['customoptions'], "linkedActions": kwargs['linkedactions'], @@ -1042,6 +1074,18 @@ def create(haproxy_frontend_svc: HaproxyFrontendFacade, **kwargs): show_default=True, default=None ) +@click.option( + '--tuning_shards', + help=( + 'This option automatically creates the specified number of listeners for every ' + ' IP:port combination and evenly distributes' + ' them among available threads. This can sometimes be useful when using very large ' + ' thread counts where the in-kernel' + ' locking on a single socket starts to cause a significant overhead.' + ), + show_default=True, + default=None +) @click.option( '--logging_dontLogNull/--no-logging_dontLogNull', help=('Enable or disable logging of connections with no data.'), @@ -1264,6 +1308,21 @@ def create(haproxy_frontend_svc: HaproxyFrontendFacade, **kwargs): callback=bool_as_string, default=None ) +@click.option( + '--prometheus_enabled/--no-prometheus_enabled', + help=('Enable HAProxy\'s Prometheus exporter.'), + show_default=True, + is_flag=True, + callback=bool_as_string, + default=None +) +@click.option( + '--prometheus_path', + help=('The path where the Prometheus exporter can be accessed.'), + show_default=True, + default=None, + required=False, +) @click.option( '--connectionBehaviour', help=( @@ -1276,7 +1335,7 @@ def create(haproxy_frontend_svc: HaproxyFrontendFacade, **kwargs): 'close the outgoing server channel as soon as the server has finished ' 'to respond and release some resources earlier.' ), - type=click.Choice(['http-keep-alive', 'http-tunnel', 'httpclose', 'http-server-close', 'forceclose']), + type=click.Choice(['http-keep-alive', 'httpclose', 'http-server-close']), multiple=False, callback=tuple_to_csv, show_default=True, @@ -1331,13 +1390,14 @@ def update(haproxy_frontend_svc: HaproxyFrontendFacade, **kwargs): 'ssl_hstsIncludeSubDomains', 'ssl_hstsPreload', 'ssl_hstsMaxAge', 'ssl_clientAuthEnabled', 'ssl_clientAuthVerify', 'ssl_clientAuthCAs', 'ssl_clientAuthCRLs', 'basicAuthEnabled', 'basicAuthUsers', 'basicAuthGroups', 'tuning_maxConnections', 'tuning_timeoutClient', 'tuning_timeoutHttpReq', - 'tuning_timeoutHttpKeepAlive', 'linkedCpuAffinityRules', 'logging_dontLogNull', 'logging_dontLogNormal', + 'tuning_timeoutHttpKeepAlive', 'linkedCpuAffinityRules', 'tuning_shards', 'logging_dontLogNull', + 'logging_dontLogNormal', 'logging_logSeparateErrors', 'logging_detailedLog', 'logging_socketStats', 'stickiness_pattern', 'stickiness_dataTypes', 'stickiness_expire', 'stickiness_size', 'stickiness_counter', 'stickiness_counter_key', 'stickiness_length', 'stickiness_connRatePeriod', 'stickiness_sessRatePeriod', 'stickiness_httpReqRatePeriod', 'stickiness_httpErrRatePeriod', 'stickiness_bytesInRatePeriod', 'stickiness_bytesOutRatePeriod', - 'http2Enabled', 'http2Enabled_nontls', 'advertised_protocols', 'forwardFor', 'connectionBehaviour', - 'customOptions', 'linkedActions', 'linkedErrorfiles' + 'http2Enabled', 'http2Enabled_nontls', 'advertised_protocols', 'forwardFor', 'prometheus_enabled', 'prometheus_path', + 'connectionBehaviour', 'customOptions', 'linkedActions', 'linkedErrorfiles' ] for option in options: if kwargs[option.lower()] is not None: diff --git a/opnsense_cli/fixtures/tests/commands/plugin/haproxy/model_data.json b/opnsense_cli/fixtures/tests/commands/plugin/haproxy/model_data.json index 87c975c..53f55c0 100644 --- a/opnsense_cli/fixtures/tests/commands/plugin/haproxy/model_data.json +++ b/opnsense_cli/fixtures/tests/commands/plugin/haproxy/model_data.json @@ -611,6 +611,7 @@ "selected": 1 } }, + "tuning_shards": "2", "logging_dontLogNull": "0", "logging_dontLogNormal": "0", "logging_logSeparateErrors": "0", @@ -724,15 +725,13 @@ } }, "forwardFor": "0", + "prometheus_enabled": "1", + "prometheus_path": "/metrics", "connectionBehaviour": { "http-keep-alive": { "value": "http-keep-alive [default]", "selected": 1 }, - "http-tunnel": { - "value": "http-tunnel", - "selected": 0 - }, "httpclose": { "value": "httpclose", "selected": 0 @@ -740,10 +739,6 @@ "http-server-close": { "value": "http-server-close", "selected": 0 - }, - "forceclose": { - "value": "forceclose", - "selected": 0 } }, "customOptions": "", @@ -1003,6 +998,7 @@ "selected": 0 } }, + "tuning_shards": "2", "logging_dontLogNull": "0", "logging_dontLogNormal": "0", "logging_logSeparateErrors": "0", @@ -1116,15 +1112,13 @@ } }, "forwardFor": "0", + "prometheus_enabled": "1", + "prometheus_path": "/metrics", "connectionBehaviour": { "http-keep-alive": { "value": "http-keep-alive [default]", "selected": 1 }, - "http-tunnel": { - "value": "http-tunnel", - "selected": 0 - }, "httpclose": { "value": "httpclose", "selected": 0 @@ -1132,10 +1126,6 @@ "http-server-close": { "value": "http-server-close", "selected": 0 - }, - "forceclose": { - "value": "forceclose", - "selected": 0 } }, "customOptions": "", diff --git a/opnsense_cli/tests/commands/plugin/test_haproxy_frontend.py b/opnsense_cli/tests/commands/plugin/test_haproxy_frontend.py index 2b640f7..eb6aaba 100644 --- a/opnsense_cli/tests/commands/plugin/test_haproxy_frontend.py +++ b/opnsense_cli/tests/commands/plugin/test_haproxy_frontend.py @@ -123,13 +123,15 @@ def test_show(self, api_response_mock: Mock): frontend, [ 'show', '6c19c893-2c38-4944-9540-a2af1eb2b7d3', '-o', 'plain', '-c', - 'uuid,enabled,name,bind,mode,Backend,ssl_enabled,ssl_certificates' + 'uuid,enabled,name,bind,mode,Backend,ssl_enabled,ssl_certificates,' + 'tuning_shards,prometheus_enabled,prometheus_path' ] ) self.assertIn( ( - "6c19c893-2c38-4944-9540-a2af1eb2b7d3 1 frontend_custom 127.0.0.1:8080 http pool2 1 60cc4641eb577\n" + "6c19c893-2c38-4944-9540-a2af1eb2b7d3 1 frontend_custom 127.0.0.1:8080 " + "http pool2 1 60cc4641eb577 2 1 /metrics\n" ), result.output ) @@ -152,10 +154,11 @@ def test_create_OK(self, api_response_mock: Mock): "--basicAuthUsers", "user1", "--basicAuthGroups", "group1", "--linkedCpuAffinityRules", "my_affinit_rule", + "--tuning_shards", "2", "--linkedActions", "my_rule", "--linkedErrorfiles", "custom_error_500", "--ssl_enabled", - "--ssl_certificates", "60cc4641eb577,610d37950266d" + "--ssl_certificates", "60cc4641eb577,610d37950266d", ] )