From f78ad275dbc0a5650db47aac32b63fd5833f668e Mon Sep 17 00:00:00 2001 From: Louis Parkin Date: Mon, 18 May 2026 15:56:09 +0200 Subject: [PATCH 1/4] STAC-24699 Align Python and shared deps with DD 7.78.2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The agent embeds Python 3.13.13 (omnibus/config/software/python3.rb). Our dev target was 3.11.10, so dep failures that only manifest under 3.13 (e.g. ddtrace 3.12.5 Cython compile of removed PyInt_Check) slipped past integrations CI and broke agent build_deb. Bump dev/CI Python to match runtime. Python: .python-version 3.11.10 -> 3.13.13 .gitlab-ci.yml PYTHON_VERSION 3.11.14 -> 3.13.13 Shared deps where DD 7.78.2 is ahead of us (take DD's pin): boto3 1.34.11 -> 1.42.54 ddtrace 3.12.5 -> 3.19.5 (also fixes Cython issue at Py3.13) kubernetes 33.1.0 -> 35.0.0 orjson 3.11.6 -> 3.11.7 prometheus-client 0.19.0 -> 0.24.1 protobuf 5.29.6 -> 6.33.5 (major bump — verify proto contracts) pydantic 2.9.1 -> 2.12.5 PyJWT 2.12.0 -> 2.12.1 Kept STS pins where we're ahead: cryptography 46.0.7 (DD: 46.0.6) STS-only deps left alone (orionsdk, pg8000, zeep, vsphere-automation-sdk, pynag, requests-ntlm, flatten-dict, iso8601, simplejson, uuid, pytz, deprecated, enum34, pywin32, psycopg2-binary). Image tag in .gitlab-ci.yml still says ...:20241120-py311. conda creates envs at PYTHON_VERSION on demand so the bump should work as-is, but the runner image should be rebuilt as py313 in a follow-up to avoid drift. --- .gitlab-ci.yml | 2 +- .python-version | 2 +- .../base/data/agent_requirements.in | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4f72a126..073f19cd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,7 +6,7 @@ stages: variables: CONDA_ENV: "stackstate-agent-integrations-py-3" - PYTHON_VERSION: 3.11.14 + PYTHON_VERSION: 3.13.13 .rules: - &pull_requests diff --git a/.python-version b/.python-version index 3e72aa69..655354de 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.11.10 +3.13.13 diff --git a/stackstate_checks_base/stackstate_checks/base/data/agent_requirements.in b/stackstate_checks_base/stackstate_checks/base/data/agent_requirements.in index 46c3ca12..5992d4ae 100644 --- a/stackstate_checks_base/stackstate_checks/base/data/agent_requirements.in +++ b/stackstate_checks_base/stackstate_checks/base/data/agent_requirements.in @@ -1,29 +1,29 @@ -boto3==1.34.11; python_version > '3.0' +boto3==1.42.54; python_version > '3.0' cm-client==45.0.4 cryptography==46.0.7; python_version > '3.0' -ddtrace==3.12.5; python_version > '3.0' +ddtrace==3.19.5; python_version > '3.0' deprecated==1.2.10 docker==6.1.3 enum34==1.1.10; python_version < "3.0" flatten-dict==0.2.0 iso8601==0.1.14 -kubernetes==33.1.0; python_version > '3.0' +kubernetes==35.0.0; python_version > '3.0' orionsdk==0.3.0 -orjson==3.11.6; python_version > '3.0' +orjson==3.11.7; python_version > '3.0' pg8000==1.31.5 -prometheus-client==0.19.0; python_version > '3.0' -protobuf==5.29.6; python_version > '3.0' +prometheus-client==0.24.1; python_version > '3.0' +protobuf==6.33.5; python_version > '3.0' psutil==6.0.0 psycopg2-binary==2.9.9; python_version > '3.0' pymysql==1.1.2; python_version > '3.0' pynag==1.1.2 -PyJWT==2.12.0 +PyJWT==2.12.1 pytz==2021.1 pywin32==306; sys_platform == 'win32' and python_version > '3.0' pyyaml==6.0.2; python_version > '3.0' requests-ntlm==1.3.0; python_version > '3.0' requests==2.33.0; python_version > '3.0' -pydantic==2.9.1 +pydantic==2.12.5 simplejson==3.20.1 six==1.16.0 urllib3==2.7.0 From 61e9d4f3781e67f0f65cce8d0bdeaf1728ae9265 Mon Sep 17 00:00:00 2001 From: Louis Parkin Date: Mon, 18 May 2026 16:03:30 +0200 Subject: [PATCH 2/4] STAC-24699 Sweep per-check requirements.in / requirements-dev.txt for shared dep bumps. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to f78ad275 — that commit only updated the central stackstate_checks_base/stackstate_checks/base/data/agent_requirements.in. This commit sweeps every other requirements.in / requirements-dev.txt for the same shared-dep pins (boto3, ddtrace, kubernetes, orjson, prometheus-client, protobuf, pydantic, pyjwt) and applies the same DD-7.78.2-derived bumps. Files touched: stackstate_checks_base/requirements.in (6 pins) splunk_base/requirements.in (pyjwt) splunk_metric/requirements.in (pydantic + pyjwt) dynatrace_base/requirements-dev.txt (pyjwt) dynatrace_health/requirements-dev.txt (pyjwt) dynatrace_topology/requirements-dev.txt (pyjwt) --- dynatrace_base/requirements-dev.txt | 2 +- dynatrace_health/requirements-dev.txt | 2 +- dynatrace_topology/requirements-dev.txt | 2 +- splunk_base/requirements.in | 2 +- splunk_metric/requirements.in | 4 ++-- stackstate_checks_base/requirements.in | 12 ++++++------ 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/dynatrace_base/requirements-dev.txt b/dynatrace_base/requirements-dev.txt index 3a62307c..922d3614 100644 --- a/dynatrace_base/requirements-dev.txt +++ b/dynatrace_base/requirements-dev.txt @@ -1,3 +1,3 @@ -e ../stackstate_checks_dev requests-mock==1.9.3 -pyjwt==2.12.0 +pyjwt==2.12.1 diff --git a/dynatrace_health/requirements-dev.txt b/dynatrace_health/requirements-dev.txt index 7a1637e7..6de2367f 100644 --- a/dynatrace_health/requirements-dev.txt +++ b/dynatrace_health/requirements-dev.txt @@ -1,4 +1,4 @@ -e ../stackstate_checks_dev requests-mock==1.9.3 freezegun -pyjwt==2.12.0 \ No newline at end of file +pyjwt==2.12.1 \ No newline at end of file diff --git a/dynatrace_topology/requirements-dev.txt b/dynatrace_topology/requirements-dev.txt index 0ba47990..4e2ed76b 100644 --- a/dynatrace_topology/requirements-dev.txt +++ b/dynatrace_topology/requirements-dev.txt @@ -1,4 +1,4 @@ -e ../stackstate_checks_dev requests-mock==1.9.3 deepdiff~=8.6.2 -pyjwt==2.12.0 +pyjwt==2.12.1 diff --git a/splunk_base/requirements.in b/splunk_base/requirements.in index 2e474c5b..2b9bc4e3 100644 --- a/splunk_base/requirements.in +++ b/splunk_base/requirements.in @@ -1,3 +1,3 @@ pytz==2021.1 iso8601==0.1.14 -PyJWT==2.12.0 +PyJWT==2.12.1 diff --git a/splunk_metric/requirements.in b/splunk_metric/requirements.in index a191903c..e25ece33 100644 --- a/splunk_metric/requirements.in +++ b/splunk_metric/requirements.in @@ -1,3 +1,3 @@ -pydantic==2.9.1 -PyJWT==2.12.0 +pydantic==2.12.5 +PyJWT==2.12.1 docker==6.1.3 \ No newline at end of file diff --git a/stackstate_checks_base/requirements.in b/stackstate_checks_base/requirements.in index fa2e2ac2..c0ead270 100644 --- a/stackstate_checks_base/requirements.in +++ b/stackstate_checks_base/requirements.in @@ -1,19 +1,19 @@ -kubernetes==33.1.0; python_version > '3.0' +kubernetes==35.0.0; python_version > '3.0' pyyaml==6.0.2; python_version > '3.0' -prometheus-client==0.19.0; python_version > '3.0' -protobuf==5.29.6; python_version > '3.0' +prometheus-client==0.24.1; python_version > '3.0' +protobuf==6.33.5; python_version > '3.0' pywin32==306; sys_platform == 'win32' and python_version > '3.0' requests==2.33.0; python_version > '3.0' urllib3==2.7.0 simplejson==3.20.1 six==1.16.0 uuid==1.30 -boto3==1.34.11; python_version > '3.0' +boto3==1.42.54; python_version > '3.0' flatten-dict==0.2.0 Deprecated==1.2.10 enum34==1.1.10; python_version < '3.0' -pydantic==2.9.1 -orjson==3.11.6; python_version > '3.0' +pydantic==2.12.5 +orjson==3.11.7; python_version > '3.0' pytz==2021.1 iso8601==0.1.14 docker==6.1.3 From cca8b5877d8a76d20dda06db658819039ebed3c1 Mon Sep 17 00:00:00 2001 From: Louis Parkin Date: Mon, 18 May 2026 16:24:28 +0200 Subject: [PATCH 3/4] STAC-24699 Fix dep-resolution and pydantic 2.12 test assertion URLs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to 61e9d4f3 — the pipeline (2534428169) surfaced two blockers the earlier sweep missed: 1. stackstate_checks_dev/setup.py:36 still hard-pinned pydantic==2.9.1, causing dep resolution conflicts with stackstate_checks_base[deps]==2.12.5 in every check that has a tox env (11 of 12 failing test_* jobs). setup.py files weren't in the earlier sweep grep — only requirements*.in/txt were. Now bumped to 2.12.5. 2. Pydantic 2.9 -> 2.12 changed the docs URL embedded in ValidationError messages from errors.pydantic.dev/2.9/v/... to .../2.12/v/... Tests in 7 files asserted against the literal expected message string, so all 16 assertions in test_agent_check.py/test_agent_check_v2.py broke (with same brittleness in 5 other test files that never ran due to #1). Updated all 7 to /2.12/. NOTE: these are still version-pinned and will break again on the next pydantic bump — version-agnostic assertion helper would be the durable fix, deferred to a separate refactor. --- servicenow/tests/test_servicenow.py | 8 ++++---- splunk_base/tests/test_splunk_instance_config.py | 4 ++-- splunk_metric/tests/test_unit.py | 4 ++-- stackstate_checks_base/tests/test_agent_check.py | 14 +++++++------- .../tests/test_agent_check_v2.py | 16 ++++++++-------- stackstate_checks_base/tests/test_utils.py | 2 +- stackstate_checks_dev/setup.py | 2 +- static_health/tests/test_static_health.py | 2 +- 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/servicenow/tests/test_servicenow.py b/servicenow/tests/test_servicenow.py index f9ca8d09..dd76327b 100644 --- a/servicenow/tests/test_servicenow.py +++ b/servicenow/tests/test_servicenow.py @@ -562,7 +562,7 @@ def test_mandatory_instance_values(self): 1 validation error for InstanceInfo url Field required [type=missing, input_value={'user': 'name', 'password': 'secret'}, input_type=dict] - For further information visit https://errors.pydantic.dev/2.9/v/missing""") + For further information visit https://errors.pydantic.dev/2.12/v/missing""") }, { 'instance': {'user': 'name', 'url': "https://website.com"}, @@ -570,7 +570,7 @@ def test_mandatory_instance_values(self): 1 validation error for InstanceInfo password Field required [type=missing, input_value={'user': 'name', 'url': 'https://website.com'}, input_type=dict] - For further information visit https://errors.pydantic.dev/2.9/v/missing""") + For further information visit https://errors.pydantic.dev/2.12/v/missing""") }, { 'instance': {'password': 'secret', 'url': "https://website.com"}, @@ -579,7 +579,7 @@ def test_mandatory_instance_values(self): user Field required [type=missing, input_value={'password': \ 'secret', 'u...: 'https://website.com'}, input_type=dict] - For further information visit https://errors.pydantic.dev/2.9/v/missing""") + For further information visit https://errors.pydantic.dev/2.12/v/missing""") } ] for test in tests: @@ -696,7 +696,7 @@ def test_batch_size(self): Input should be less than or equal to 10000 [type=less_than_equal, \ input_value=20000, input_type=int] For further information visit \ -https://errors.pydantic.dev/2.9/v/less_than_equal"""), result[0]['message']) +https://errors.pydantic.dev/2.12/v/less_than_equal"""), result[0]['message']) @mock.patch('requests.Session.get') def test_get_json_timeout(self, mock_request_get): diff --git a/splunk_base/tests/test_splunk_instance_config.py b/splunk_base/tests/test_splunk_instance_config.py index b4e810e8..d6f2b7cf 100644 --- a/splunk_base/tests/test_splunk_instance_config.py +++ b/splunk_base/tests/test_splunk_instance_config.py @@ -119,7 +119,7 @@ def test_check_audience_param_not_set(self): authentication.token_auth.audience Field required [type=missing, input_value={'name': 'admin', 'initia...dx', \ 'renewal_days': 10}, input_type=dict] - For further information visit https://errors.pydantic.dev/2.9/v/missing""") + For further information visit https://errors.pydantic.dev/2.12/v/missing""") def test_check_name_param_not_set(self): """ @@ -152,4 +152,4 @@ def test_check_name_param_not_set(self): authentication.token_auth.name Field required [type=missing, input_value={'initial_token': 'dsfdgf...ch', \ 'renewal_days': 10}, input_type=dict] - For further information visit https://errors.pydantic.dev/2.9/v/missing""") + For further information visit https://errors.pydantic.dev/2.12/v/missing""") diff --git a/splunk_metric/tests/test_unit.py b/splunk_metric/tests/test_unit.py index 4e456740..e2d9b1fd 100644 --- a/splunk_metric/tests/test_unit.py +++ b/splunk_metric/tests/test_unit.py @@ -561,7 +561,7 @@ def test_authentication_token_no_audience_parameter_check(set_authentication_mod authentication.token_auth.audience Field required [type=missing, input_value={'name': 'api-admin', 'in... 90, \ 'renewal_days': 10}, input_type=dict] - For further information visit https://errors.pydantic.dev/2.9/v/missing""")) + For further information visit https://errors.pydantic.dev/2.12/v/missing""")) def test_authentication_token_no_name_parameter_check(set_authentication_mode_to_token, @@ -576,7 +576,7 @@ def test_authentication_token_no_name_parameter_check(set_authentication_mode_to authentication.token_auth.name Field required [type=missing, input_value={'audience': 'search', 'i... 90, \ 'renewal_days': 10}, input_type=dict] - For further information visit https://errors.pydantic.dev/2.9/v/missing""")) + For further information visit https://errors.pydantic.dev/2.12/v/missing""")) def test_authentication_prefer_token_over_basic_check(config_authentication_prefer_token_over_basic_check, diff --git a/stackstate_checks_base/tests/test_agent_check.py b/stackstate_checks_base/tests/test_agent_check.py index 11fad9a0..83fd004a 100644 --- a/stackstate_checks_base/tests/test_agent_check.py +++ b/stackstate_checks_base/tests/test_agent_check.py @@ -1274,7 +1274,7 @@ def test_verify_types(self): 1 validation error for HealthStreamUrn source Input should be a valid string [type=string_type, input_value=None, input_type=NoneType] - For further information visit https://errors.pydantic.dev/2.9/v/string_type""") + For further information visit https://errors.pydantic.dev/2.12/v/string_type""") with pytest.raises(ValidationError) as e2: HealthStreamUrn("source", None) @@ -1282,7 +1282,7 @@ def test_verify_types(self): 1 validation error for HealthStreamUrn stream_id Input should be a valid string [type=string_type, input_value=None, input_type=NoneType] - For further information visit https://errors.pydantic.dev/2.9/v/string_type""") + For further information visit https://errors.pydantic.dev/2.12/v/string_type""") class TestHealthStream: @@ -1293,7 +1293,7 @@ def test_throws_error_when_expiry_on_sub_stream(self): 1 validation error for HealthStream Value error, Expiry cannot be disabled if a substream is specified \ [type=value_error, input_value={'urn': HealthStreamUrn(s...ne, 'expiry_seconds': 0}, input_type=dict] - For further information visit https://errors.pydantic.dev/2.9/v/value_error""") + For further information visit https://errors.pydantic.dev/2.12/v/value_error""") def test_verify_types(self): with pytest.raises(ValidationError) as e: @@ -1303,7 +1303,7 @@ def test_verify_types(self): urn Input should be a valid dictionary or instance of HealthStreamUrn \ [type=model_type, input_value='str', input_type=str] - For further information visit https://errors.pydantic.dev/2.9/v/model_type""") + For further information visit https://errors.pydantic.dev/2.12/v/model_type""") with pytest.raises(ValidationError) as e: HealthStream(HealthStreamUrn("source", "urn"), sub_stream=1) @@ -1312,7 +1312,7 @@ def test_verify_types(self): sub_stream Input should be a valid string \ [type=string_type, input_value=1, input_type=int] - For further information visit https://errors.pydantic.dev/2.9/v/string_type""") + For further information visit https://errors.pydantic.dev/2.12/v/string_type""") with pytest.raises(ValidationError) as e: HealthStream(HealthStreamUrn("source", "urn"), repeat_interval_seconds="") @@ -1321,7 +1321,7 @@ def test_verify_types(self): repeat_interval_seconds Input should be a valid integer, unable to parse \ string as an integer [type=int_parsing, input_value='', input_type=str] - For further information visit https://errors.pydantic.dev/2.9/v/int_parsing""") + For further information visit https://errors.pydantic.dev/2.12/v/int_parsing""") with pytest.raises(ValidationError) as e: HealthStream(HealthStreamUrn("source", "urn"), expiry_seconds="") @@ -1330,7 +1330,7 @@ def test_verify_types(self): expiry_seconds Input should be a valid integer, unable to parse string \ as an integer [type=int_parsing, input_value='', input_type=str] - For further information visit https://errors.pydantic.dev/2.9/v/int_parsing""") + For further information visit https://errors.pydantic.dev/2.12/v/int_parsing""") class TestHealth: diff --git a/stackstate_checks_base/tests/test_agent_check_v2.py b/stackstate_checks_base/tests/test_agent_check_v2.py index d6266876..878ea853 100644 --- a/stackstate_checks_base/tests/test_agent_check_v2.py +++ b/stackstate_checks_base/tests/test_agent_check_v2.py @@ -1151,7 +1151,7 @@ def test_verify_types(self): 1 validation error for HealthStreamUrn source Input should be a valid string [type=string_type, input_value=None, input_type=NoneType] - For further information visit https://errors.pydantic.dev/2.9/v/string_type""") + For further information visit https://errors.pydantic.dev/2.12/v/string_type""") with pytest.raises(ValidationError) as e2: HealthStreamUrn("source", None) @@ -1159,7 +1159,7 @@ def test_verify_types(self): 1 validation error for HealthStreamUrn stream_id Input should be a valid string [type=string_type, input_value=None, input_type=NoneType] - For further information visit https://errors.pydantic.dev/2.9/v/string_type""") + For further information visit https://errors.pydantic.dev/2.12/v/string_type""") class TestHealthStream: @@ -1170,7 +1170,7 @@ def test_throws_error_when_expiry_on_sub_stream(self): 1 validation error for HealthStream Value error, Expiry cannot be disabled if a substream is specified \ [type=value_error, input_value={'urn': HealthStreamUrn(s...ne, 'expiry_seconds': 0}, input_type=dict] - For further information visit https://errors.pydantic.dev/2.9/v/value_error""") + For further information visit https://errors.pydantic.dev/2.12/v/value_error""") def test_verify_types(self): with pytest.raises(ValidationError) as e: @@ -1180,7 +1180,7 @@ def test_verify_types(self): urn Input should be a valid dictionary or instance of HealthStreamUrn \ [type=model_type, input_value='str', input_type=str] - For further information visit https://errors.pydantic.dev/2.9/v/model_type""") + For further information visit https://errors.pydantic.dev/2.12/v/model_type""") with pytest.raises(ValidationError) as e: HealthStream(HealthStreamUrn("source", "urn"), sub_stream=1) @@ -1189,7 +1189,7 @@ def test_verify_types(self): sub_stream Input should be a valid string \ [type=string_type, input_value=1, input_type=int] - For further information visit https://errors.pydantic.dev/2.9/v/string_type""") + For further information visit https://errors.pydantic.dev/2.12/v/string_type""") with pytest.raises(ValidationError) as e: HealthStream(HealthStreamUrn("source", "urn"), repeat_interval_seconds="") @@ -1198,7 +1198,7 @@ def test_verify_types(self): repeat_interval_seconds Input should be a valid integer, unable to parse \ string as an integer [type=int_parsing, input_value='', input_type=str] - For further information visit https://errors.pydantic.dev/2.9/v/int_parsing""") + For further information visit https://errors.pydantic.dev/2.12/v/int_parsing""") with pytest.raises(ValidationError) as e: HealthStream(HealthStreamUrn("source", "urn"), expiry_seconds="") @@ -1207,7 +1207,7 @@ def test_verify_types(self): expiry_seconds Input should be a valid integer, unable to parse string as \ an integer [type=int_parsing, input_value='', input_type=str] - For further information visit https://errors.pydantic.dev/2.9/v/int_parsing""") + For further information visit https://errors.pydantic.dev/2.12/v/int_parsing""") class TestHealth: @@ -1474,7 +1474,7 @@ def test_stateful_check_with_invalid_schema(self, sample_stateful_check_with_sch 1 validation error for State key_that_is_not_in_schema Extra inputs are not permitted [type=extra_forbidden, input_value='some_value', input_type=str] - For further information visit https://errors.pydantic.dev/2.9/v/extra_forbidden""") + For further information visit https://errors.pydantic.dev/2.12/v/extra_forbidden""") class NormalCheck(AgentCheckV2): diff --git a/stackstate_checks_base/tests/test_utils.py b/stackstate_checks_base/tests/test_utils.py index a1df36ae..713b9ef0 100644 --- a/stackstate_checks_base/tests/test_utils.py +++ b/stackstate_checks_base/tests/test_utils.py @@ -153,7 +153,7 @@ def test_exception_state_without_valid_location(self, state_manager): 1 validation error for StateDescriptorSchema instance_key String should have at least 1 character [type=string_too_short, input_value='', input_type=str] - For further information visit https://errors.pydantic.dev/2.9/v/string_too_short""") + For further information visit https://errors.pydantic.dev/2.12/v/string_too_short""") instance = StateDescriptor("test", "this") # set an invalid file_location for this test diff --git a/stackstate_checks_dev/setup.py b/stackstate_checks_dev/setup.py index f308b1ce..0ee0d127 100644 --- a/stackstate_checks_dev/setup.py +++ b/stackstate_checks_dev/setup.py @@ -33,7 +33,7 @@ 'six==1.16.0', 'Deprecated==1.2.10', "enum34==1.1.10; python_version < '3.4'", - 'pydantic==2.9.1' + 'pydantic==2.12.5' ] diff --git a/static_health/tests/test_static_health.py b/static_health/tests/test_static_health.py index 267332a5..d15dbed8 100644 --- a/static_health/tests/test_static_health.py +++ b/static_health/tests/test_static_health.py @@ -80,7 +80,7 @@ def test_omitted_health_file(self): Field required [type=missing, input_value={'type': 'csv', \ 'delimite...ollection_interval': 15}, input_type=dict] For further information visit \ -https://errors.pydantic.dev/2.9/v/missing""") +https://errors.pydantic.dev/2.12/v/missing""") def test_empty_health_file(self): instance = { From c56da6f5d764d8c77b3ab9370cb73831460fe29c Mon Sep 17 00:00:00 2001 From: Louis Parkin Date: Mon, 18 May 2026 16:35:44 +0200 Subject: [PATCH 4/4] STAC-24699 Make kubelet test_prometheus_filtering tolerate Sample tuple growth. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit prometheus-client 0.24 added a `native_histogram` field to the Sample namedtuple (0.19: 5 fields, 0.24: 6). The test in test_kubelet.py:362 positional-unpacks Sample as a 5-tuple, breaking under the bump. Use a star-rest pattern so future prometheus-client releases that add fields don't break this assertion again. Note: this is the only positional-unpack call site for metric.samples in the repo — every other usage iterates as `for sample in metric.samples:` and accesses fields by attribute name, which is already version-robust. --- kubelet/tests/test_kubelet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubelet/tests/test_kubelet.py b/kubelet/tests/test_kubelet.py index f49bf273..985d1642 100755 --- a/kubelet/tests/test_kubelet.py +++ b/kubelet/tests/test_kubelet.py @@ -359,7 +359,7 @@ def test_prometheus_filtering(monkeypatch, aggregator): mock_method.assert_called_once() metric = mock_method.call_args[0][0] assert len(metric.samples) == 12 - for name, labels, _, _, _ in metric.samples: + for name, labels, *_ in metric.samples: # [sts] tolerate prometheus-client Sample tuple growth (0.19 had 5 fields, 0.24 has 6 with native_histogram) assert name == "container_cpu_usage_seconds_total" assert labels["pod_name"] != ""