From 4387826da0705f400e436ae1ebb1b3d57c06d6c1 Mon Sep 17 00:00:00 2001 From: Pawel Snoch Date: Thu, 15 Oct 2026 17:33:07 +0200 Subject: [PATCH 1/3] Add integration tests for Premium NodeBalancer changes --- tests/integration/helpers.py | 5 ++ tests/integration/nodebalancers/fixtures.py | 71 +++++++++++++++ .../nodebalancers/test_node_balancers.py | 90 +++++++++++++++++++ 3 files changed, 166 insertions(+) diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index a1ba7d6ef..2912cd27b 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -224,6 +224,11 @@ def assert_help_actions_list(expected_actions, help_output): assert expected_action in output_actions +def assert_help_parameters_list_for_command(expected_parameters, help_output): + for expected_parameter in expected_parameters: + assert expected_parameter in help_output + + def view_command_attribute( command: str, action: str, item_id: str, attribute: str ) -> str: diff --git a/tests/integration/nodebalancers/fixtures.py b/tests/integration/nodebalancers/fixtures.py index 958b802de..65d5657a2 100644 --- a/tests/integration/nodebalancers/fixtures.py +++ b/tests/integration/nodebalancers/fixtures.py @@ -5,6 +5,8 @@ check_attribute_value, delete_target_id, exec_test_command, + get_random_region_with_caps, + get_random_text, wait_for_condition, ) from tests.integration.linodes.helpers import DEFAULT_TEST_IMAGE @@ -362,3 +364,72 @@ def nodebalancer_with_reserved_ipv4(create_reserved_ip): yield res_ip, nodebalancer_id delete_target_id(target="nodebalancers", id=nodebalancer_id) + + +@pytest.fixture +def nodebalancer_type_premium_backend_connectivity_vpc(linode_cloud_firewall): + vpc_label = get_random_text(5) + "label" + subnet_label = get_random_text(5) + "label" + test_region = get_random_region_with_caps( + ["NodeBalancers", "Premium NodeBalancers"] + ) + + test_vpc_id = exec_test_command( + [ + "linode-cli", + "vpcs", + "create", + "--label", + vpc_label, + "--region", + test_region, + "--subnets.ipv4", + "192.168.0.0/25", + "--subnets.label", + subnet_label, + "--text", + "--suppress-warnings", + "--format", + "id", + "--no-headers", + ] + ) + test_subnet_id = exec_test_command( + BASE_CMDS["vpcs"] + + [ + "subnets-list", + test_vpc_id, + "--text", + "--no-headers", + "--delimiter=,", + ] + ).split(",")[0] + + result = exec_test_command( + BASE_CMDS["nodebalancers"] + + [ + "create", + "--region", + test_region, + "--firewall_id", + linode_cloud_firewall, + "--type", + "premium", + "--backend_connectivity", + "vpc", + "--vpcs.ipv4_range", + "192.168.0.64/30", + "--vpcs.subnet_id", + test_subnet_id, + "--text", + "--delimiter", + ",", + "--suppress-warnings", + "--no-headers", + ] + ) + nodebalancer_id = result.split(",")[0] + + yield nodebalancer_id, result + delete_target_id(target="nodebalancers", id=nodebalancer_id) + delete_target_id(target="vpcs", id=test_vpc_id) diff --git a/tests/integration/nodebalancers/test_node_balancers.py b/tests/integration/nodebalancers/test_node_balancers.py index 69564852a..b4d21cc7a 100644 --- a/tests/integration/nodebalancers/test_node_balancers.py +++ b/tests/integration/nodebalancers/test_node_balancers.py @@ -5,11 +5,15 @@ from linodecli.exit_codes import ExitCodes from tests.integration.helpers import ( BASE_CMDS, + assert_headers_in_lines, + assert_help_parameters_list_for_command, exec_failing_test_command, exec_test_command, + get_random_text, ) from tests.integration.nodebalancers.fixtures import ( # noqa: F401 linode_to_add, + nodebalancer_type_premium_backend_connectivity_vpc, nodebalancer_w_config_and_node, nodebalancer_with_default_conf, nodebalancer_with_reserved_ipv4, @@ -52,6 +56,28 @@ def test_list_nodebalancers_and_status(nodebalancer_w_config_and_node): assert re.search(nodebalancer_created(), result) +def test_verify_columns_for_list_nodebalancers(): + result = exec_test_command( + BASE_CMDS["nodebalancers"] + + [ + "list", + "--text", + "--delimiter", + ",", + ] + ) + lines = result.splitlines() + headers = [ + "id", + "label", + "region", + "type", + "backend_connectivity", + "backend_ipv6_prefix", + ] + assert_headers_in_lines(headers, lines) + + def test_display_public_ipv4_for_nodebalancer(nodebalancer_w_config_and_node): nodebalancer_id = nodebalancer_w_config_and_node[0] @@ -564,3 +590,67 @@ def test_view_node_for_node_balancer_udp_configuration( def nodebalancer_created(): return "[0-9]+,balancer[0-9]+,us-ord,[0-9]+-[0-9]+-[0-9]+-[0-9]+.ip.linodeusercontent.com,0" + + +def test_premium_nodebalancer_with_vpc_backend_connectivity( + nodebalancer_type_premium_backend_connectivity_vpc, +): + result_create = nodebalancer_type_premium_backend_connectivity_vpc[1] + assert "premium" in result_create + assert "vpc" in result_create + assert "/96" in result_create + + result_view = exec_test_command( + BASE_CMDS["nodebalancers"] + + [ + "view", + nodebalancer_type_premium_backend_connectivity_vpc[0], + "--text", + "--no-headers", + "--format", + "type,backend_connectivity,backend_ipv6_prefix", + "--delimiter", + ",", + ] + ).split(",") + assert result_view[0] == "premium" + assert result_view[1] == "vpc" + assert result_view[2].endswith("/96") + + result_update = exec_test_command( + BASE_CMDS["nodebalancers"] + + [ + "update", + nodebalancer_type_premium_backend_connectivity_vpc[0], + "--label", + "update_label_" + get_random_text(5), + "--client_conn_throttle", + "0", + "--text", + "--no-headers", + "--delimiter", + ",", + ] + ) + assert "premium" in result_update + assert "vpc" in result_update + assert "/96" in result_update + + +def test_create_nodebalancer_help_command(): + output = exec_test_command( + BASE_CMDS["nodebalancers"] + ["create", "--help", "--text"] + ) + available_arguments = [ + "backend_connectivity", + "client_conn_throttle", + "configs", + "firewall_id", + "ipv4", + "region", + "type", + "vpcs.ipv4_range", + "vpcs.ipv4_range_auto_assign", + "vpcs.subnet_id", + ] + assert_help_parameters_list_for_command(available_arguments, output) From 36e93f6a75a99a31a2e3c4acc7c399167daf0a91 Mon Sep 17 00:00:00 2001 From: Pawel Snoch Date: Mon, 19 Oct 2026 14:31:54 +0200 Subject: [PATCH 2/3] Apply copilot suggestions --- tests/integration/helpers.py | 6 +- tests/integration/nodebalancers/fixtures.py | 62 +++++++++++-------- .../nodebalancers/test_node_balancers.py | 1 + 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index 2912cd27b..c51c7328d 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -226,7 +226,11 @@ def assert_help_actions_list(expected_actions, help_output): def assert_help_parameters_list_for_command(expected_parameters, help_output): for expected_parameter in expected_parameters: - assert expected_parameter in help_output + re.search( + rf"^\s*--{re.escape(expected_parameter)}(?=\s|:)", + help_output, + re.MULTILINE, + ), f"Missing help parameter: --{expected_parameter}" def view_command_attribute( diff --git a/tests/integration/nodebalancers/fixtures.py b/tests/integration/nodebalancers/fixtures.py index 65d5657a2..22e5981a4 100644 --- a/tests/integration/nodebalancers/fixtures.py +++ b/tests/integration/nodebalancers/fixtures.py @@ -367,38 +367,18 @@ def nodebalancer_with_reserved_ipv4(create_reserved_ip): @pytest.fixture -def nodebalancer_type_premium_backend_connectivity_vpc(linode_cloud_firewall): - vpc_label = get_random_text(5) + "label" - subnet_label = get_random_text(5) + "label" +def nodebalancer_type_premium_backend_connectivity_vpc( + linode_cloud_firewall, + vpc_for_nodebalancer_type_premium_backend_connectivity_vpc, +): test_region = get_random_region_with_caps( ["NodeBalancers", "Premium NodeBalancers"] ) - - test_vpc_id = exec_test_command( - [ - "linode-cli", - "vpcs", - "create", - "--label", - vpc_label, - "--region", - test_region, - "--subnets.ipv4", - "192.168.0.0/25", - "--subnets.label", - subnet_label, - "--text", - "--suppress-warnings", - "--format", - "id", - "--no-headers", - ] - ) test_subnet_id = exec_test_command( BASE_CMDS["vpcs"] + [ "subnets-list", - test_vpc_id, + vpc_for_nodebalancer_type_premium_backend_connectivity_vpc, "--text", "--no-headers", "--delimiter=,", @@ -432,4 +412,36 @@ def nodebalancer_type_premium_backend_connectivity_vpc(linode_cloud_firewall): yield nodebalancer_id, result delete_target_id(target="nodebalancers", id=nodebalancer_id) + + +@pytest.fixture +def vpc_for_nodebalancer_type_premium_backend_connectivity_vpc(): + vpc_label = get_random_text(5) + "label" + subnet_label = get_random_text(5) + "label" + test_region = get_random_region_with_caps( + ["NodeBalancers", "Premium NodeBalancers"] + ) + + test_vpc_id = exec_test_command( + [ + "linode-cli", + "vpcs", + "create", + "--label", + vpc_label, + "--region", + test_region, + "--subnets.ipv4", + "192.168.0.0/25", + "--subnets.label", + subnet_label, + "--text", + "--suppress-warnings", + "--format", + "id", + "--no-headers", + ] + ) + + yield test_vpc_id delete_target_id(target="vpcs", id=test_vpc_id) diff --git a/tests/integration/nodebalancers/test_node_balancers.py b/tests/integration/nodebalancers/test_node_balancers.py index b4d21cc7a..430c97f53 100644 --- a/tests/integration/nodebalancers/test_node_balancers.py +++ b/tests/integration/nodebalancers/test_node_balancers.py @@ -19,6 +19,7 @@ nodebalancer_with_reserved_ipv4, nodebalancer_with_udp_config_and_node, simple_nodebalancer_with_config, + vpc_for_nodebalancer_type_premium_backend_connectivity_vpc, ) From 96aed16639d93d75d7cecf448d6f8ca66759f009 Mon Sep 17 00:00:00 2001 From: Pawel Snoch Date: Tue, 27 Oct 2026 14:30:22 +0100 Subject: [PATCH 3/3] Apply code review suggestions --- tests/integration/helpers.py | 2 +- tests/integration/nodebalancers/fixtures.py | 24 ++++++++----------- .../nodebalancers/test_node_balancers.py | 12 +++++----- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index c51c7328d..84dbc1720 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -226,7 +226,7 @@ def assert_help_actions_list(expected_actions, help_output): def assert_help_parameters_list_for_command(expected_parameters, help_output): for expected_parameter in expected_parameters: - re.search( + assert re.search( rf"^\s*--{re.escape(expected_parameter)}(?=\s|:)", help_output, re.MULTILINE, diff --git a/tests/integration/nodebalancers/fixtures.py b/tests/integration/nodebalancers/fixtures.py index 22e5981a4..3f56de53b 100644 --- a/tests/integration/nodebalancers/fixtures.py +++ b/tests/integration/nodebalancers/fixtures.py @@ -367,18 +367,15 @@ def nodebalancer_with_reserved_ipv4(create_reserved_ip): @pytest.fixture -def nodebalancer_type_premium_backend_connectivity_vpc( +def nodebalancer_premium_with_backend_vpc( linode_cloud_firewall, - vpc_for_nodebalancer_type_premium_backend_connectivity_vpc, + vpc_for_nb_premium_backend_connectivity, ): - test_region = get_random_region_with_caps( - ["NodeBalancers", "Premium NodeBalancers"] - ) test_subnet_id = exec_test_command( BASE_CMDS["vpcs"] + [ "subnets-list", - vpc_for_nodebalancer_type_premium_backend_connectivity_vpc, + vpc_for_nb_premium_backend_connectivity[0], "--text", "--no-headers", "--delimiter=,", @@ -390,7 +387,7 @@ def nodebalancer_type_premium_backend_connectivity_vpc( + [ "create", "--region", - test_region, + vpc_for_nb_premium_backend_connectivity[1], "--firewall_id", linode_cloud_firewall, "--type", @@ -415,17 +412,16 @@ def nodebalancer_type_premium_backend_connectivity_vpc( @pytest.fixture -def vpc_for_nodebalancer_type_premium_backend_connectivity_vpc(): - vpc_label = get_random_text(5) + "label" - subnet_label = get_random_text(5) + "label" +def vpc_for_nb_premium_backend_connectivity(): + vpc_label = "test_vpc_" + get_random_text(5) + subnet_label = "test_vpc_" + get_random_text(5) test_region = get_random_region_with_caps( ["NodeBalancers", "Premium NodeBalancers"] ) test_vpc_id = exec_test_command( - [ - "linode-cli", - "vpcs", + BASE_CMDS["vpcs"] + + [ "create", "--label", vpc_label, @@ -443,5 +439,5 @@ def vpc_for_nodebalancer_type_premium_backend_connectivity_vpc(): ] ) - yield test_vpc_id + yield test_vpc_id, test_region delete_target_id(target="vpcs", id=test_vpc_id) diff --git a/tests/integration/nodebalancers/test_node_balancers.py b/tests/integration/nodebalancers/test_node_balancers.py index 430c97f53..95c8023e3 100644 --- a/tests/integration/nodebalancers/test_node_balancers.py +++ b/tests/integration/nodebalancers/test_node_balancers.py @@ -13,13 +13,13 @@ ) from tests.integration.nodebalancers.fixtures import ( # noqa: F401 linode_to_add, - nodebalancer_type_premium_backend_connectivity_vpc, + nodebalancer_premium_with_backend_vpc, nodebalancer_w_config_and_node, nodebalancer_with_default_conf, nodebalancer_with_reserved_ipv4, nodebalancer_with_udp_config_and_node, simple_nodebalancer_with_config, - vpc_for_nodebalancer_type_premium_backend_connectivity_vpc, + vpc_for_nb_premium_backend_connectivity, ) @@ -594,9 +594,9 @@ def nodebalancer_created(): def test_premium_nodebalancer_with_vpc_backend_connectivity( - nodebalancer_type_premium_backend_connectivity_vpc, + nodebalancer_premium_with_backend_vpc, ): - result_create = nodebalancer_type_premium_backend_connectivity_vpc[1] + result_create = nodebalancer_premium_with_backend_vpc[1] assert "premium" in result_create assert "vpc" in result_create assert "/96" in result_create @@ -605,7 +605,7 @@ def test_premium_nodebalancer_with_vpc_backend_connectivity( BASE_CMDS["nodebalancers"] + [ "view", - nodebalancer_type_premium_backend_connectivity_vpc[0], + nodebalancer_premium_with_backend_vpc[0], "--text", "--no-headers", "--format", @@ -622,7 +622,7 @@ def test_premium_nodebalancer_with_vpc_backend_connectivity( BASE_CMDS["nodebalancers"] + [ "update", - nodebalancer_type_premium_backend_connectivity_vpc[0], + nodebalancer_premium_with_backend_vpc[0], "--label", "update_label_" + get_random_text(5), "--client_conn_throttle",