From 6d4a460bb78c6f6d52f1b0c24aeab7505be5bd18 Mon Sep 17 00:00:00 2001 From: itoussies <65223458+itoussies@users.noreply.github.com> Date: Fri, 29 Aug 2025 15:07:02 +0200 Subject: [PATCH] CTOR-1853 Plugin(cloud::docker::restapi) - Mode(container): fix memory usage calculation (#5711) --- .../docker/restapi/mode/containerusage.pm | 17 +-- tests/cloud/docker/restapi/container.robot | 35 +++++ tests/cloud/docker/restapi/docker.json | 125 ++++++++++++++++++ 3 files changed, 169 insertions(+), 8 deletions(-) create mode 100644 tests/cloud/docker/restapi/container.robot create mode 100644 tests/cloud/docker/restapi/docker.json diff --git a/src/cloud/docker/restapi/mode/containerusage.pm b/src/cloud/docker/restapi/mode/containerusage.pm index c06ed482a..a0a5463f2 100644 --- a/src/cloud/docker/restapi/mode/containerusage.pm +++ b/src/cloud/docker/restapi/mode/containerusage.pm @@ -275,7 +275,7 @@ sub manage_selection { $self->{containers}->{$container_id}->{cpu_number} = scalar(@{$result->{$container_id}->{Stats}->{cpu_stats}->{cpu_usage}->{percpu_usage}}); } - $self->{containers}->{$container_id}->{memory_usage} = $result->{$container_id}->{Stats}->{memory_stats}->{usage}; + $self->{containers}->{$container_id}->{memory_usage} = $result->{$container_id}->{Stats}->{memory_stats}->{usage} - $result->{$container_id}->{Stats}->{memory_stats}->{stats}->{inactive_file} // 0; $self->{containers}->{$container_id}->{memory_total} = $result->{$container_id}->{Stats}->{memory_stats}->{limit}; foreach my $interface (keys %{$result->{$container_id}->{Stats}->{networks}}) { @@ -316,19 +316,20 @@ Check container usage. =item B<--container-id> -Exact container ID. +Set the container ID. =item B<--container-name> -Exact container name (if multiple names: names separated by ':'). +Set the container name(s). Multiple container names should be separated by ':'. +Example: C<--container-name='container1:container2'>. =item B<--use-name> -Use docker name for perfdata and display. +Use the docker name for perfdata and display. =item B<--add-health> -Get container health status (call inspector endpoint). +Get the container health status by calling the /inspector endpoint. =item B<--no-stats> @@ -341,17 +342,17 @@ Filter by container name (can be a regexp). =item B<--filter-counters> Only display some counters (regexp can be used). -Example: --filter-counters='^container-status$' +Example: C<--filter-counters='^container-status$'> =item B<--warning-container-status> Define the conditions to match for the status to be WARNING. -You can use the following variables: %{name}, %{state}, %{health}. +You can use the following variables: C<%{name}>, C<%{state}>, C<%{health}>. =item B<--critical-container-status> Define the conditions to match for the status to be CRITICAL. -You can use the following variables: %{name}, %{state}, %{health}. +You can use the following variables: C<%{name}>, C<%{state}>, C<%{health}>. =item B<--warning-*> B<--critical-*> diff --git a/tests/cloud/docker/restapi/container.robot b/tests/cloud/docker/restapi/container.robot new file mode 100644 index 000000000..c42d7d4b0 --- /dev/null +++ b/tests/cloud/docker/restapi/container.robot @@ -0,0 +1,35 @@ +*** Settings *** +Documentation Cloud Docker REST API Container + +Resource ${CURDIR}${/}..${/}..${/}..${/}resources/import.resource + +Suite Setup Start Mockoon ${MOCKOON_JSON} +Suite Teardown Stop Mockoon +Test Timeout 120s + + +*** Variables *** +${MOCKOON_JSON} ${CURDIR}${/}docker.json +${HOSTNAME} 127.0.0.1 +${APIPORT} 3000 +${CMD} ${CENTREON_PLUGINS} +... --plugin=cloud::docker::restapi::plugin +... --mode=container-usage +... --hostname=${HOSTNAME} +... --port=${APIPORT} + +*** Test Cases *** +Container usage ${tc} + [Tags] cloud kubernetes + + ${command} Catenate + ... ${cmd} + ... ${extraoptions} + + Ctn Run Command And Check Result As Regexp ${command} ${expected_result} + + Examples: tc extraoptions expected_result -- + ... 1 ${EMPTY} OK: Container 'containerId' state: running, cpu : Buffer creation, memory total: 7.65 GB used: 75.97 MB (0.97%) free: 7.58 GB (99.03%), read-iops : Buffer creation, write-iops : Buffer creation - All container traffics are ok | 'memory_used'=79664947B;;;0;8217579520 + ... 2 ${EMPTY} OK: Container 'containerId' state: running, cpu usage: 0.00 %, memory total: 7.65 GB used: 75.97 MB (0.97%) free: 7.58 GB (99.03%), read IOPs: 0.00, write IOPs: 0.00 - All container traffics are ok | 'cpu'=0.00%;;;0;100 'memory_used'=79664947B;;;0;8217579520 'read_iops'=0.00iops;;;0; 'write_iops'=0.00iops;;;0; 'traffic_in_containerId.eth0'=0.00b/s;;;0; 'traffic_out_containerId.eth0'=0.00b/s;;;0; 'traffic_in_containerId.eth5'=0.00b/s;;;0; 'traffic_out_containerId.eth5'=0.00b/s;;;0; + ... 3 --use-name --no-stats OK: Container '/containerName' state: running + ... 4 --critical-container-status='\\\%{state}=~/running/' CRITICAL: Container 'containerId' state: running | 'cpu'=0.00%;;;0;100 'memory_used'=79664947B;;;0;8217579520 'read_iops'=0.00iops;;;0; 'write_iops'=0.00iops;;;0; 'traffic_in_containerId.eth0'=0.00b/s;;;0; 'traffic_out_containerId.eth0'=0.00b/s;;;0; 'traffic_in_containerId.eth5'=0.00b/s;;;0; 'traffic_out_containerId.eth5'=0.00b/s;;;0; diff --git a/tests/cloud/docker/restapi/docker.json b/tests/cloud/docker/restapi/docker.json new file mode 100644 index 000000000..bc81e7734 --- /dev/null +++ b/tests/cloud/docker/restapi/docker.json @@ -0,0 +1,125 @@ +{ + "uuid": "123def66-79b3-46a6-a645-ba1aa0fab6c2", + "lastMigration": 32, + "name": "Docker", + "endpointPrefix": "", + "latency": 0, + "port": 3009, + "hostname": "", + "folders": [], + "routes": [ + { + "uuid": "a182c722-1a15-4968-8f9e-032c48ebb585", + "type": "http", + "documentation": "", + "method": "get", + "endpoint": "containers/containerId/stats", + "responses": [ + { + "uuid": "9024006f-68a7-4ae0-ac0a-b3595ddc7927", + "body": "{\r\n \"name\": \"containerName\",\r\n \"id\": \"containerId\",\r\n \"blkio_stats\": {\r\n \"io_service_bytes_recursive\": [\r\n {\r\n \"major\": 254,\r\n \"minor\": 0,\r\n \"op\": \"read\",\r\n \"value\": 7593984\r\n },\r\n {\r\n \"major\": 254,\r\n \"minor\": 0,\r\n \"op\": \"write\",\r\n \"value\": 100\r\n }\r\n ],\r\n \"io_serviced_recursive\": null,\r\n \"io_queue_recursive\": null,\r\n \"io_service_time_recursive\": null,\r\n \"io_wait_time_recursive\": null,\r\n \"io_merged_recursive\": null,\r\n \"io_time_recursive\": null,\r\n \"sectors_recursive\": null\r\n },\r\n \"cpu_stats\": {\r\n \"cpu_usage\": {\r\n \"total_usage\": 29912000,\r\n \"percpu_usage\": [\r\n 29912000\r\n ],\r\n \"usage_in_kernelmode\": 21994000,\r\n \"usage_in_usermode\": 7918000\r\n },\r\n \"system_cpu_usage\": 5,\r\n \"online_cpus\": 5,\r\n \"throttling_data\": {\r\n \"periods\": 0,\r\n \"throttled_periods\": 0,\r\n \"throttled_time\": 0\r\n }\r\n },\r\n \"memory_stats\": {\r\n \"usage\": 82175795,\r\n \"max_usage\": 0,\r\n \"stats\": {\r\n \"inactive_file\": 2510848\r\n },\r\n \"limit\": 8217579520\r\n },\r\n \"networks\": {\r\n \"eth0\": {\r\n \"rx_bytes\": 5338,\r\n \"rx_dropped\": 0,\r\n \"rx_errors\": 0,\r\n \"rx_packets\": 36,\r\n \"tx_bytes\": 648,\r\n \"tx_dropped\": 0,\r\n \"tx_errors\": 0,\r\n \"tx_packets\": 8\r\n },\r\n \"eth5\": {\r\n \"rx_bytes\": 4641,\r\n \"rx_dropped\": 0,\r\n \"rx_errors\": 0,\r\n \"rx_packets\": 26,\r\n \"tx_bytes\": 690,\r\n \"tx_dropped\": 0,\r\n \"tx_errors\": 0,\r\n \"tx_packets\": 9\r\n }\r\n }\r\n}", + "latency": 0, + "statusCode": 200, + "label": "", + "headers": [], + "bodyType": "INLINE", + "filePath": "", + "databucketID": "", + "sendFileAsBody": false, + "rules": [], + "rulesOperator": "OR", + "disableTemplating": false, + "fallbackTo404": false, + "default": true, + "crudKey": "id", + "callbacks": [] + } + ], + "responseMode": null + }, + { + "uuid": "e7e4e95d-f5d8-4e40-ba95-ffd76264b8ca", + "type": "http", + "documentation": "", + "method": "get", + "endpoint": "containers/json", + "responses": [ + { + "uuid": "6eabce15-4f21-4502-9503-588d4f022c71", + "body": "[\r\n {\r\n \"Id\": \"containerId\",\r\n \"Names\": [\r\n \"/containerName\"\r\n ],\r\n \"State\": \"running\"\r\n }\r\n]", + "latency": 0, + "statusCode": 200, + "label": "", + "headers": [], + "bodyType": "INLINE", + "filePath": "", + "databucketID": "", + "sendFileAsBody": false, + "rules": [], + "rulesOperator": "OR", + "disableTemplating": false, + "fallbackTo404": false, + "default": true, + "crudKey": "id", + "callbacks": [] + } + ], + "responseMode": null + } + ], + "rootChildren": [ + { + "type": "route", + "uuid": "a182c722-1a15-4968-8f9e-032c48ebb585" + }, + { + "type": "route", + "uuid": "e7e4e95d-f5d8-4e40-ba95-ffd76264b8ca" + } + ], + "proxyMode": false, + "proxyHost": "", + "proxyRemovePrefix": false, + "tlsOptions": { + "enabled": false, + "type": "CERT", + "pfxPath": "", + "certPath": "", + "keyPath": "", + "caPath": "", + "passphrase": "" + }, + "cors": true, + "headers": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "Access-Control-Allow-Methods", + "value": "GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS" + }, + { + "key": "Access-Control-Allow-Headers", + "value": "Content-Type, Origin, Accept, Authorization, Content-Length, X-Requested-With" + } + ], + "proxyReqHeaders": [ + { + "key": "", + "value": "" + } + ], + "proxyResHeaders": [ + { + "key": "", + "value": "" + } + ], + "data": [], + "callbacks": [] +} \ No newline at end of file