From ef3251f49f5d2321060ac9380b16a74bf566612d Mon Sep 17 00:00:00 2001 From: vshanthe Date: Fri, 19 Sep 2025 18:50:56 +0530 Subject: [PATCH 1/6] fix failing tests --- test/integration/helpers.py | 4 +++ .../models/account/test_account.py | 34 +++++++++---------- .../models/firewall/test_firewall.py | 29 +++++++++++----- .../models/nodebalancer/test_nodebalancer.py | 21 +++++++++--- 4 files changed, 58 insertions(+), 30 deletions(-) diff --git a/test/integration/helpers.py b/test/integration/helpers.py index 969ca70a9..9d6efd5b9 100644 --- a/test/integration/helpers.py +++ b/test/integration/helpers.py @@ -37,6 +37,10 @@ def retry_sending_request( "Api Error: Failed after all retry attempts" ) from e time.sleep(backoff) + wait = backoff * attempt + random.uniform(0, 2) + print(f"Attempt {attempt} failed ({e}), retrying in {wait:.1f}s...") + time.sleep(wait) + return None def send_request_when_resource_available( diff --git a/test/integration/models/account/test_account.py b/test/integration/models/account/test_account.py index 805f713b6..0fc5a56b9 100644 --- a/test/integration/models/account/test_account.py +++ b/test/integration/models/account/test_account.py @@ -47,7 +47,7 @@ def test_get_login(test_linode_client): assert "ip" in str(login._raw_json) assert "datetime" in str(login._raw_json) assert "status" in str(login._raw_json) - assert login_updated < 15 + assert login_updated < 60 def test_get_account_settings(test_linode_client): @@ -101,29 +101,29 @@ def test_latest_get_event(test_linode_client, e2e_test_firewall): firewall=e2e_test_firewall, ) - events = client.load(Event, "") + try: + for _ in range(5): + events = client.load(Event, "") + latest_events = events._raw_json.get("data", [])[:50] - latest_events = events._raw_json.get("data") - - linode.delete() - - for event in latest_events[:15]: - if label == event["entity"]["label"]: - break - else: - assert False, f"Linode '{label}' not found in the last 15 events" + if any( + event["entity"]["id"] == linode.id for event in latest_events + ): + break + time.sleep(5) + else: + assert False, f"Linode '{label}' not found in recent events" + finally: + linode.delete() def test_get_user(test_linode_client): client = test_linode_client - events = client.load(Event, "") - - username = events._raw_json.get("data")[0]["username"] - - user = client.load(User, username) + profile = client.profile() + user = client.load(User, profile.username) - assert username == user.username + assert user.username == profile.username assert "email" in user._raw_json diff --git a/test/integration/models/firewall/test_firewall.py b/test/integration/models/firewall/test_firewall.py index 16805f3b8..a9035a3f9 100644 --- a/test/integration/models/firewall/test_firewall.py +++ b/test/integration/models/firewall/test_firewall.py @@ -63,22 +63,35 @@ def test_update_firewall_rules(test_linode_client, test_firewall): assert firewall.rules.outbound_policy == "DROP" -def test_get_devices(test_linode_client, linode_fw, test_firewall): +def test_get_devices(test_linode_client, linode_fw): linode = linode_fw - test_firewall.device_create(int(linode.id)) + firewalls = list(linode.firewalls()) + assert len(firewalls) > 0 - firewall = test_linode_client.load(Firewall, test_firewall.id) + firewall = test_linode_client.load(Firewall, firewalls[0].id) + + devices = list(firewall.devices) + assert any(d.entity.id == linode.id for d in devices) + + +def test_get_device(test_linode_client, linode_fw): + linode = linode_fw + + firewalls = list(linode.firewalls()) + assert firewalls, "No firewalls found on Linode" - assert len(firewall.devices) > 0 + firewall = test_linode_client.load(Firewall, firewalls[0].id) + devices = list(firewall.devices) + assert devices, "No devices found on Firewall" -def test_get_device(test_linode_client, test_firewall, linode_fw): - firewall = test_firewall + device = next((d for d in devices if d.entity.id == linode.id), None) + assert device is not None, f"No FirewallDevice found for Linode {linode.id}" firewall_device = test_linode_client.load( - FirewallDevice, firewall.devices.first().id, firewall.id + FirewallDevice, device.id, firewall.id ) assert firewall_device.entity.type == "linode" - assert "/v4/linode/instances/" in firewall_device.entity.url + assert f"/v4/linode/instances/{linode.id}" in firewall_device.entity.url diff --git a/test/integration/models/nodebalancer/test_nodebalancer.py b/test/integration/models/nodebalancer/test_nodebalancer.py index 9e7537897..d891eb190 100644 --- a/test/integration/models/nodebalancer/test_nodebalancer.py +++ b/test/integration/models/nodebalancer/test_nodebalancer.py @@ -48,20 +48,31 @@ def linode_with_private_ip(test_linode_client, e2e_test_firewall): @pytest.fixture(scope="session") -def create_nb_config(test_linode_client, e2e_test_firewall): +def create_nb_config(test_linode_client, e2e_test_firewall, linode_with_private_ip): client = test_linode_client - label = get_test_label(8) + nb_label = get_test_label() + node_label = get_test_label(8) nb = client.nodebalancer_create( - region=TEST_REGION, label=label, firewall=e2e_test_firewall.id + region=TEST_REGION, + label=nb_label, + firewall=e2e_test_firewall.id, ) config = nb.config_create() + linode = linode_with_private_ip + address = next(a for a in linode.ipv4 if a.startswith("192.168")) + node = config.node_create(node_label, f"{address}:80", weight=50, mode="accept") yield config - config.delete() - nb.delete() + # cleanup + for obj in [node, config, nb]: + try: + obj.delete() + except ApiError as e: + if e.status != 404: + raise @pytest.fixture(scope="session") From 20e02783e4c022d850b1719bca02c4ab25cf0fd6 Mon Sep 17 00:00:00 2001 From: vshanthe Date: Fri, 19 Sep 2025 19:03:17 +0530 Subject: [PATCH 2/6] address lint --- test/integration/models/nodebalancer/test_nodebalancer.py | 8 ++++++-- test/unit/objects/linode_test.py | 1 - test/unit/objects/monitor_test.py | 2 -- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/test/integration/models/nodebalancer/test_nodebalancer.py b/test/integration/models/nodebalancer/test_nodebalancer.py index d891eb190..2b8e0a49b 100644 --- a/test/integration/models/nodebalancer/test_nodebalancer.py +++ b/test/integration/models/nodebalancer/test_nodebalancer.py @@ -48,7 +48,9 @@ def linode_with_private_ip(test_linode_client, e2e_test_firewall): @pytest.fixture(scope="session") -def create_nb_config(test_linode_client, e2e_test_firewall, linode_with_private_ip): +def create_nb_config( + test_linode_client, e2e_test_firewall, linode_with_private_ip +): client = test_linode_client nb_label = get_test_label() node_label = get_test_label(8) @@ -62,7 +64,9 @@ def create_nb_config(test_linode_client, e2e_test_firewall, linode_with_private_ config = nb.config_create() linode = linode_with_private_ip address = next(a for a in linode.ipv4 if a.startswith("192.168")) - node = config.node_create(node_label, f"{address}:80", weight=50, mode="accept") + node = config.node_create( + node_label, f"{address}:80", weight=50, mode="accept" + ) yield config diff --git a/test/unit/objects/linode_test.py b/test/unit/objects/linode_test.py index 8fa3cdbb3..5e4c9fe47 100644 --- a/test/unit/objects/linode_test.py +++ b/test/unit/objects/linode_test.py @@ -575,7 +575,6 @@ def test_get_stackscript(self): class TypeTest(ClientBaseCase): - def test_get_type_by_id(self): """ Tests that a Linode type is loaded correctly by ID diff --git a/test/unit/objects/monitor_test.py b/test/unit/objects/monitor_test.py index a010514c2..e122b3e6a 100644 --- a/test/unit/objects/monitor_test.py +++ b/test/unit/objects/monitor_test.py @@ -90,7 +90,6 @@ def test_specific_service_details(self): self.assertEqual(data.service_type, "dbaas") def test_metric_definitions(self): - metrics = self.client.monitor.metric_definitions(service_type="dbaas") self.assertEqual( metrics[0].available_aggregate_functions, @@ -109,7 +108,6 @@ def test_metric_definitions(self): ) def test_create_token(self): - with self.mock_post("/monitor/services/dbaas/token") as m: self.client.monitor.create_token( service_type="dbaas", entity_ids=[189690, 188020] From 3f1bc7f04dd0218295dfd816ded4a80267af8d5e Mon Sep 17 00:00:00 2001 From: vshanthe Date: Mon, 22 Sep 2025 12:50:47 +0530 Subject: [PATCH 3/6] fix --- test/integration/helpers.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/integration/helpers.py b/test/integration/helpers.py index 9d6efd5b9..bd32cfff0 100644 --- a/test/integration/helpers.py +++ b/test/integration/helpers.py @@ -36,11 +36,9 @@ def retry_sending_request( raise Exception( "Api Error: Failed after all retry attempts" ) from e - time.sleep(backoff) wait = backoff * attempt + random.uniform(0, 2) print(f"Attempt {attempt} failed ({e}), retrying in {wait:.1f}s...") time.sleep(wait) - return None def send_request_when_resource_available( From 5bf5aea656b1f14bec2147a7db3d5b8027809427 Mon Sep 17 00:00:00 2001 From: vshanthe Date: Wed, 24 Sep 2025 11:32:56 +0530 Subject: [PATCH 4/6] reduce_sleep_time --- test/integration/models/account/test_account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/models/account/test_account.py b/test/integration/models/account/test_account.py index 0fc5a56b9..4d9aa2034 100644 --- a/test/integration/models/account/test_account.py +++ b/test/integration/models/account/test_account.py @@ -110,7 +110,7 @@ def test_latest_get_event(test_linode_client, e2e_test_firewall): event["entity"]["id"] == linode.id for event in latest_events ): break - time.sleep(5) + time.sleep(1) else: assert False, f"Linode '{label}' not found in recent events" finally: From 7a06d21bf8160124eb9b7e1e0348c3c21ab9e765 Mon Sep 17 00:00:00 2001 From: vshanthe Date: Mon, 29 Sep 2025 12:32:01 +0530 Subject: [PATCH 5/6] fix_firewall_test --- .../models/firewall/test_firewall.py | 65 +++++++++++-------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/test/integration/models/firewall/test_firewall.py b/test/integration/models/firewall/test_firewall.py index a9035a3f9..8f25884fe 100644 --- a/test/integration/models/firewall/test_firewall.py +++ b/test/integration/models/firewall/test_firewall.py @@ -8,18 +8,43 @@ @pytest.fixture(scope="session") -def linode_fw(test_linode_client): +def linode_fw(test_linode_client, test_firewall): client = test_linode_client region = get_region(client, {"Linodes", "Cloud Firewall"}, site_type="core") label = get_test_label() - linode_instance, password = client.linode.instance_create( + linode_instance, _ = client.linode.instance_create( "g6-nanode-1", region, image="linode/debian12", label=label ) - yield linode_instance + for fw in linode_instance.firewalls(): + fw_device = next((d for d in fw.devices if d.entity.id == linode_instance.id), None) + if fw_device: + fw_device.delete() + + firewall = client.networking.firewall_create( + label=f"{label}-fw", + rules={ + "inbound": [], + "inbound_policy": "DROP", + "outbound": [], + "outbound_policy": "ACCEPT", + }, + ) + + client.post( + f"/networking/firewalls/{firewall.id}/devices", + data={"id": linode_instance.id, "type": "linode"}, + ) - linode_instance.delete() + try: + yield linode_instance, firewall + finally: + for obj, name in ((firewall, "firewall"), (linode_instance, "Linode")): + try: + obj.delete() + except Exception as e: + print(f"Warning: failed to delete {name} {obj.id}: {e}") @pytest.mark.smoke @@ -64,34 +89,18 @@ def test_update_firewall_rules(test_linode_client, test_firewall): def test_get_devices(test_linode_client, linode_fw): - linode = linode_fw - - firewalls = list(linode.firewalls()) - assert len(firewalls) > 0 - - firewall = test_linode_client.load(Firewall, firewalls[0].id) - - devices = list(firewall.devices) + linode, firewall = linode_fw + devices = list(test_linode_client.load(Firewall, firewall.id).devices) assert any(d.entity.id == linode.id for d in devices) def test_get_device(test_linode_client, linode_fw): - linode = linode_fw - - firewalls = list(linode.firewalls()) - assert firewalls, "No firewalls found on Linode" - - firewall = test_linode_client.load(Firewall, firewalls[0].id) - - devices = list(firewall.devices) + linode, firewall = linode_fw + devices = list(test_linode_client.load(Firewall, firewall.id).devices) assert devices, "No devices found on Firewall" - device = next((d for d in devices if d.entity.id == linode.id), None) - assert device is not None, f"No FirewallDevice found for Linode {linode.id}" - - firewall_device = test_linode_client.load( - FirewallDevice, device.id, firewall.id - ) + device = next(d for d in devices if d.entity.id == linode.id) + fw_device = test_linode_client.load(FirewallDevice, device.id, firewall.id) - assert firewall_device.entity.type == "linode" - assert f"/v4/linode/instances/{linode.id}" in firewall_device.entity.url + assert fw_device.entity.type == "linode" + assert f"/v4/linode/instances/{linode.id}" in fw_device.entity.url \ No newline at end of file From 9cc5c6f300c554e45dab4d49dfd02bb550a9c9aa Mon Sep 17 00:00:00 2001 From: vshanthe Date: Mon, 29 Sep 2025 12:36:45 +0530 Subject: [PATCH 6/6] format --- .../linode_client/test_linode_client.py | 6 +----- .../models/firewall/test_firewall.py | 6 ++++-- test/integration/models/linode/test_linode.py | 18 ++++++++++++------ test/unit/groups/linode_test.py | 5 +---- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/test/integration/linode_client/test_linode_client.py b/test/integration/linode_client/test_linode_client.py index da7e93cef..eb1b06369 100644 --- a/test/integration/linode_client/test_linode_client.py +++ b/test/integration/linode_client/test_linode_client.py @@ -6,11 +6,7 @@ import pytest from linode_api4 import ApiError -from linode_api4.objects import ( - ConfigInterface, - ObjectStorageKeys, - Region, -) +from linode_api4.objects import ConfigInterface, ObjectStorageKeys, Region @pytest.fixture(scope="session") diff --git a/test/integration/models/firewall/test_firewall.py b/test/integration/models/firewall/test_firewall.py index 8f25884fe..321d1dae6 100644 --- a/test/integration/models/firewall/test_firewall.py +++ b/test/integration/models/firewall/test_firewall.py @@ -18,7 +18,9 @@ def linode_fw(test_linode_client, test_firewall): ) for fw in linode_instance.firewalls(): - fw_device = next((d for d in fw.devices if d.entity.id == linode_instance.id), None) + fw_device = next( + (d for d in fw.devices if d.entity.id == linode_instance.id), None + ) if fw_device: fw_device.delete() @@ -103,4 +105,4 @@ def test_get_device(test_linode_client, linode_fw): fw_device = test_linode_client.load(FirewallDevice, device.id, firewall.id) assert fw_device.entity.type == "linode" - assert f"/v4/linode/instances/{linode.id}" in fw_device.entity.url \ No newline at end of file + assert f"/v4/linode/instances/{linode.id}" in fw_device.entity.url diff --git a/test/integration/models/linode/test_linode.py b/test/integration/models/linode/test_linode.py index 5c1548a57..2354e2ba7 100644 --- a/test/integration/models/linode/test_linode.py +++ b/test/integration/models/linode/test_linode.py @@ -888,9 +888,12 @@ def test_create_vpc( test_linode_client, linode_and_vpc_for_legacy_interface_tests_offline, ): - vpc, subnet, linode, _ = ( - linode_and_vpc_for_legacy_interface_tests_offline - ) + ( + vpc, + subnet, + linode, + _, + ) = linode_and_vpc_for_legacy_interface_tests_offline config: Config = linode.configs[0] @@ -945,9 +948,12 @@ def test_update_vpc( self, linode_and_vpc_for_legacy_interface_tests_offline, ): - vpc, subnet, linode, _ = ( - linode_and_vpc_for_legacy_interface_tests_offline - ) + ( + vpc, + subnet, + linode, + _, + ) = linode_and_vpc_for_legacy_interface_tests_offline config: Config = linode.configs[0] diff --git a/test/unit/groups/linode_test.py b/test/unit/groups/linode_test.py index a495284fd..03278f03b 100644 --- a/test/unit/groups/linode_test.py +++ b/test/unit/groups/linode_test.py @@ -5,10 +5,7 @@ build_interface_options_vpc, ) -from linode_api4 import ( - InstancePlacementGroupAssignment, - InterfaceGeneration, -) +from linode_api4 import InstancePlacementGroupAssignment, InterfaceGeneration from linode_api4.objects import ConfigInterface