From 090d12d75bb58fc827db230a51acca7449289962 Mon Sep 17 00:00:00 2001 From: Luca Comellini Date: Tue, 23 Aug 2022 09:41:32 -0700 Subject: [PATCH] Add isort and Black (#2929) --- .github/workflows/lint.yml | 7 + Makefile | 7 + perf-tests/conftest.py | 50 +- perf-tests/suite/ap_request_perf.py | 34 +- perf-tests/suite/test_ap_reload_perf.py | 59 +- pyproject.toml | 13 + tests/conftest.py | 27 +- tests/suite/ap_resources_utils.py | 67 +- tests/suite/custom_assertions.py | 39 +- tests/suite/custom_resource_fixtures.py | 150 +-- tests/suite/custom_resources_utils.py | 84 +- tests/suite/dos_utils.py | 13 +- tests/suite/fixtures.py | 104 +- tests/suite/ic_fixtures.py | 135 +-- tests/suite/kube_config_utils.py | 6 +- tests/suite/nginx_api_utils.py | 7 +- tests/suite/policy_resources_utils.py | 13 +- tests/suite/resources_utils.py | 82 +- tests/suite/ssl_utils.py | 5 +- tests/suite/test_ac_policies.py | 90 +- tests/suite/test_ac_policies_vsr.py | 58 +- tests/suite/test_annotations.py | 529 ++++++---- tests/suite/test_app_protect.py | 64 +- tests/suite/test_app_protect_grpc.py | 97 +- tests/suite/test_app_protect_integration.py | 141 +-- tests/suite/test_app_protect_waf_policies.py | 153 +-- .../test_app_protect_waf_policies_grpc.py | 281 ++--- .../suite/test_app_protect_watch_namespace.py | 65 +- tests/suite/test_auth_basic_auth_mergeable.py | 197 ++-- tests/suite/test_auth_basic_policies.py | 119 ++- tests/suite/test_auth_basic_policies_vsr.py | 119 +-- tests/suite/test_auth_basic_secrets.py | 137 ++- tests/suite/test_batch_startup_times.py | 117 +-- tests/suite/test_build_info.py | 24 +- tests/suite/test_custom_annotations.py | 103 +- tests/suite/test_default_server.py | 29 +- tests/suite/test_dos.py | 1 - tests/suite/test_externalname_service.py | 159 ++- tests/suite/test_healthcheck_uri.py | 41 +- tests/suite/test_hsts.py | 91 +- tests/suite/test_ingress_class.py | 24 +- tests/suite/test_ingress_mtls.py | 35 +- tests/suite/test_jwt_auth_mergeable.py | 222 ++-- tests/suite/test_jwt_policies.py | 125 ++- tests/suite/test_jwt_policies_vsr.py | 130 +-- tests/suite/test_jwt_secrets.py | 107 +- tests/suite/test_policy_ingress_class.py | 100 +- tests/suite/test_prometheus_metrics.py | 110 +- tests/suite/test_rewrites.py | 52 +- tests/suite/test_rl_policies.py | 137 ++- tests/suite/test_rl_policies_vsr.py | 53 +- tests/suite/test_smoke.py | 67 +- tests/suite/test_snippet_flag.py | 55 +- tests/suite/test_tls.py | 63 +- tests/suite/test_transport_server.py | 40 +- tests/suite/test_transport_server_status.py | 33 +- .../test_transport_server_tcp_load_balance.py | 179 ++-- .../test_transport_server_udp_load_balance.py | 119 +-- tests/suite/test_ts_tls_passthrough.py | 96 +- tests/suite/test_v_s_route.py | 389 +++---- .../suite/test_v_s_route_advanced_routing.py | 173 +-- tests/suite/test_v_s_route_api.py | 53 +- .../suite/test_v_s_route_canned_responses.py | 160 +-- tests/suite/test_v_s_route_error_pages.py | 288 ++--- tests/suite/test_v_s_route_externalname.py | 182 ++-- tests/suite/test_v_s_route_focused_canary.py | 79 +- tests/suite/test_v_s_route_grpc.py | 158 +-- tests/suite/test_v_s_route_redirects.py | 103 +- tests/suite/test_v_s_route_regexp_location.py | 258 +++-- tests/suite/test_v_s_route_split_traffic.py | 44 +- tests/suite/test_v_s_route_status.py | 54 +- .../suite/test_v_s_route_upstream_options.py | 990 ++++++++++++------ tests/suite/test_v_s_route_upstream_tls.py | 184 ++-- tests/suite/test_virtual_server.py | 173 +-- .../test_virtual_server_advanced_routing.py | 130 ++- tests/suite/test_virtual_server_api.py | 42 +- .../test_virtual_server_canned_responses.py | 163 +-- .../suite/test_virtual_server_certmanager.py | 88 +- .../test_virtual_server_configmap_keys.py | 290 +++-- tests/suite/test_virtual_server_dos.py | 1 - .../suite/test_virtual_server_error_pages.py | 193 ++-- .../test_virtual_server_external_name.py | 133 ++- .../suite/test_virtual_server_externaldns.py | 34 +- .../test_virtual_server_focused_canary.py | 42 +- tests/suite/test_virtual_server_grpc.py | 262 +++-- tests/suite/test_virtual_server_mixed_grpc.py | 86 +- tests/suite/test_virtual_server_redirects.py | 136 ++- .../test_virtual_server_split_traffic.py | 39 +- tests/suite/test_virtual_server_status.py | 37 +- tests/suite/test_virtual_server_tls.py | 93 +- .../suite/test_virtual_server_tls_redirect.py | 368 ++++--- .../test_virtual_server_upstream_options.py | 833 ++++++++++----- .../suite/test_virtual_server_upstream_tls.py | 132 ++- tests/suite/test_virtual_server_validation.py | 95 +- tests/suite/test_watch_namespace.py | 78 +- tests/suite/test_wildcard_tls_secret.py | 195 ++-- tests/suite/vs_vsr_resources_utils.py | 51 +- tests/suite/yaml_utils.py | 26 +- 98 files changed, 6877 insertions(+), 5222 deletions(-) create mode 100644 pyproject.toml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 89f08a5a85..db60e07a2d 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -38,3 +38,10 @@ jobs: uses: golangci/golangci-lint-action@v3 with: only-new-issues: true + + lint-python: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - uses: isort/isort-action@v1.0.0 + - uses: psf/black@stable diff --git a/Makefile b/Makefile index 4d00e8f0d2..3b1a05a127 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,13 @@ lint: ## Run linter @git fetch docker run --pull always --rm -v $(shell pwd):/kubernetes-ingress -w /kubernetes-ingress -v $(shell go env GOCACHE):/cache/go -e GOCACHE=/cache/go -e GOLANGCI_LINT_CACHE=/cache/go -v $(shell go env GOPATH)/pkg:/go/pkg golangci/golangci-lint:latest git diff -p origin/main > /tmp/diff.patch && golangci-lint --color always run -v --new-from-patch=/tmp/diff.patch +.PHONY: lint-python +lint-python: ## Run linter for python tests + @isort -V || (code=$$?; printf "\033[0;31mError\033[0m: there was a problem with isort, use 'brew install isort' to install it\n"; exit $$code) + @black --version || (code=$$?; printf "\033[0;31mError\033[0m: there was a problem with black, use 'brew install black' to install it\n"; exit $$code) + @isort . + @black . + .PHONY: test test: ## Run tests go test -tags=aws -shuffle=on -race ./... diff --git a/perf-tests/conftest.py b/perf-tests/conftest.py index 8f3aad4e11..fb9f875dba 100644 --- a/perf-tests/conftest.py +++ b/perf-tests/conftest.py @@ -1,18 +1,13 @@ """Describe overall framework configuration.""" -from suite.resources_utils import get_first_pod_name -from settings import ( - DEFAULT_IMAGE, - DEFAULT_PULL_POLICY, - DEFAULT_IC_TYPE, - DEFAULT_SERVICE, - DEFAULT_DEPLOYMENT_TYPE, -) -from kubernetes.config.kube_config import KUBE_CONFIG_DEFAULT_LOCATION import os -import pytest import sys +import pytest +from kubernetes.config.kube_config import KUBE_CONFIG_DEFAULT_LOCATION +from settings import DEFAULT_DEPLOYMENT_TYPE, DEFAULT_IC_TYPE, DEFAULT_IMAGE, DEFAULT_PULL_POLICY, DEFAULT_SERVICE +from suite.resources_utils import get_first_pod_name + sys.path.insert(0, "../tests") @@ -23,10 +18,16 @@ def pytest_addoption(parser) -> None: :return: """ parser.addoption( - "--context", action="store", default="", help="The context to use in the kubeconfig file.", + "--context", + action="store", + default="", + help="The context to use in the kubeconfig file.", ) parser.addoption( - "--image", action="store", default=DEFAULT_IMAGE, help="The Ingress Controller image.", + "--image", + action="store", + default=DEFAULT_IMAGE, + help="The Ingress Controller image.", ) parser.addoption( "--image-pull-policy", @@ -70,10 +71,16 @@ def pytest_addoption(parser) -> None: help="Show IC logs in stdout on test failure", ) parser.addoption( - "--users", action="store", default="10", help="No. of users for response perf tests", + "--users", + action="store", + default="10", + help="No. of users for response perf tests", ) parser.addoption( - "--hatch-rate", action="store", default="5", help="No. of users hatched per second", + "--hatch-rate", + action="store", + default="5", + help="No. of users hatched per second", ) parser.addoption( "--time", @@ -97,20 +104,17 @@ def pytest_collection_modifyitems(config, items) -> None: :return: """ if config.getoption("--ic-type") == "nginx-ingress": - skip_for_nginx_oss = pytest.mark.skip( - reason="Skip a test for Nginx OSS") + skip_for_nginx_oss = pytest.mark.skip(reason="Skip a test for Nginx OSS") for item in items: if "skip_for_nginx_oss" in item.keywords: item.add_marker(skip_for_nginx_oss) if config.getoption("--ic-type") == "nginx-plus-ingress": - skip_for_nginx_plus = pytest.mark.skip( - reason="Skip a test for Nginx Plus") + skip_for_nginx_plus = pytest.mark.skip(reason="Skip a test for Nginx Plus") for item in items: if "skip_for_nginx_plus" in item.keywords: item.add_marker(skip_for_nginx_plus) if "-ap" not in config.getoption("--image"): - appprotect = pytest.mark.skip( - reason="Skip AppProtect test in non-AP image") + appprotect = pytest.mark.skip(reason="Skip AppProtect test in non-AP image") for item in items: if "appprotect" in item.keywords: item.add_marker(appprotect) @@ -134,9 +138,7 @@ def pytest_runtest_makereport(item) -> None: # we only look at actual failing test calls, not setup/teardown if rep.when == "call" and rep.failed and item.config.getoption("--show-ic-logs") == "yes": pod_namespace = item.funcargs["ingress_controller_prerequisites"].namespace - pod_name = get_first_pod_name( - item.funcargs["kube_apis"].v1, pod_namespace) + pod_name = get_first_pod_name(item.funcargs["kube_apis"].v1, pod_namespace) print("\n===================== IC Logs Start =====================") - print(item.funcargs["kube_apis"].v1.read_namespaced_pod_log( - pod_name, pod_namespace)) + print(item.funcargs["kube_apis"].v1.read_namespaced_pod_log(pod_name, pod_namespace)) print("\n===================== IC Logs End =====================") diff --git a/perf-tests/suite/ap_request_perf.py b/perf-tests/suite/ap_request_perf.py index 8667752943..1f421bcfb3 100644 --- a/perf-tests/suite/ap_request_perf.py +++ b/perf-tests/suite/ap_request_perf.py @@ -1,37 +1,33 @@ -import yaml, os -from locust import TaskSet, HttpUser, task +import os + +import yaml +from locust import HttpUser, TaskSet, task host = "" + + class TestAPResponse(HttpUser): - # locust class to be invoked + # locust class to be invoked def on_start(self): - # get host from appprotect-ingress yaml before each test + # get host from appprotect-ingress yaml before each test ap_yaml = os.path.join(os.path.dirname(__file__), "../data/appprotect-ingress.yaml") with open(ap_yaml) as f: docs = yaml.safe_load_all(f) for dep in docs: - self.host = dep['spec']['rules'][0]['host'] + self.host = dep["spec"]["rules"][0]["host"] print("Setup finished") @task def send_block_request(self): - # Send invalid request while dataguard alarm policy is active - response = self.client.get( - url="/", headers={"host": virtual_server_setup.vs_host}, ) print(response1.text) - print( - "----------------------- Send request with blocked keyword in UDS----------------------" - ) + print("----------------------- Send request with blocked keyword in UDS----------------------") response2 = requests.get( virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, @@ -246,7 +228,10 @@ def test_ap_waf_policy_block( @pytest.mark.parametrize( "vs_src, waf", - [(waf_spec_vs_src, waf_pol_dataguard_src), (waf_route_vs_src, waf_pol_dataguard_src),], + [ + (waf_spec_vs_src, waf_pol_dataguard_src), + (waf_route_vs_src, waf_pol_dataguard_src), + ], ) def test_ap_waf_policy_allow( self, @@ -282,24 +267,18 @@ def test_ap_waf_policy_allow( virtual_server_setup.namespace, ) wait_before_test() - ap_crd_info = read_ap_custom_resource( - kube_apis.custom_objects, test_namespace, "appolicies", ap_policy_uds - ) + ap_crd_info = read_ap_custom_resource(kube_apis.custom_objects, test_namespace, "appolicies", ap_policy_uds) assert_ap_crd_info(ap_crd_info, ap_policy_uds) wait_before_test(120) - print( - "----------------------- Send request with embedded malicious script----------------------" - ) + print("----------------------- Send request with embedded malicious script----------------------") response1 = requests.get( virtual_server_setup.backend_1_url + "", headers={"host": virtual_server_setup.vs_host}, ) print(response1.text) - print( - "----------------------- Send request with blocked keyword in UDS----------------------" - ) + print("----------------------- Send request with blocked keyword in UDS----------------------") response2 = requests.get( virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, @@ -350,15 +329,11 @@ def test_ap_waf_policy_logs( virtual_server_setup.namespace, ) wait_before_test() - ap_crd_info = read_ap_custom_resource( - kube_apis.custom_objects, test_namespace, "appolicies", ap_policy_uds - ) + ap_crd_info = read_ap_custom_resource(kube_apis.custom_objects, test_namespace, "appolicies", ap_policy_uds) assert_ap_crd_info(ap_crd_info, ap_policy_uds) wait_before_test(120) - print( - "----------------------- Send request with embedded malicious script----------------------" - ) + print("----------------------- Send request with embedded malicious script----------------------") response = requests.get( virtual_server_setup.backend_1_url + "", headers={"host": virtual_server_setup.vs_host}, @@ -367,9 +342,7 @@ def test_ap_waf_policy_logs( log_contents = "" retry = 0 while "ASM:attack_type" not in log_contents and retry <= 30: - log_contents = get_file_contents( - kube_apis.v1, log_loc, syslog_pod, test_namespace - ) + log_contents = get_file_contents(kube_apis.v1, log_loc, syslog_pod, test_namespace) retry += 1 wait_before_test(1) print(f"Security log not updated, retrying... #{retry}") @@ -378,10 +351,7 @@ def test_ap_waf_policy_logs( self.restore_default_vs(kube_apis, virtual_server_setup) delete_items_from_yaml(kube_apis, src_syslog_yaml, test_namespace) assert_invalid_responses(response) - assert ( - f'ASM:attack_type="Non-browser Client,Abuse of Functionality,Cross Site Scripting (XSS)"' - in log_contents - ) + assert f'ASM:attack_type="Non-browser Client,Abuse of Functionality,Cross Site Scripting (XSS)"' in log_contents assert f'severity="Critical"' in log_contents assert f'request_status="blocked"' in log_contents assert f'outcome="REJECTED"' in log_contents @@ -418,7 +388,7 @@ def test_ap_waf_policy_multi_logs( True, ap_pol_name, [log_name, log_esc_name], - [f"syslog:server={syslog_dst1}:514",f"syslog:server={syslog_dst2}:514"] + [f"syslog:server={syslog_dst1}:514", f"syslog:server={syslog_dst2}:514"], ) wait_before_test() print(f"Patch vs with policy: {waf_spec_vs_src}") @@ -429,15 +399,11 @@ def test_ap_waf_policy_multi_logs( virtual_server_setup.namespace, ) wait_before_test() - ap_crd_info = read_ap_custom_resource( - kube_apis.custom_objects, test_namespace, "appolicies", ap_policy_uds - ) + ap_crd_info = read_ap_custom_resource(kube_apis.custom_objects, test_namespace, "appolicies", ap_policy_uds) assert_ap_crd_info(ap_crd_info, ap_policy_uds) wait_before_test(120) - print( - "----------------------- Send request with embedded malicious script----------------------" - ) + print("----------------------- Send request with embedded malicious script----------------------") response = requests.get( virtual_server_setup.backend_1_url + "", headers={"host": virtual_server_setup.vs_host}, @@ -446,9 +412,7 @@ def test_ap_waf_policy_multi_logs( log_contents = "" retry = 0 while "ASM:attack_type" not in log_contents and retry <= 30: - log_contents = get_file_contents( - kube_apis.v1, log_loc, syslog_pod[0].metadata.name, test_namespace - ) + log_contents = get_file_contents(kube_apis.v1, log_loc, syslog_pod[0].metadata.name, test_namespace) retry += 1 wait_before_test(1) print(log_contents) @@ -457,13 +421,11 @@ def test_ap_waf_policy_multi_logs( log_esc_contents = "" retry = 0 while "attack_type" not in log_esc_contents and retry <= 30: - log_esc_contents = get_file_contents( - kube_apis.v1, log_loc, syslog_esc_pod[0].metadata.name, test_namespace - ) + log_esc_contents = get_file_contents(kube_apis.v1, log_loc, syslog_esc_pod[0].metadata.name, test_namespace) retry += 1 wait_before_test(1) print(log_esc_contents) - print(f"Security log not updated, retrying... #{retry}") + print(f"Security log not updated, retrying... #{retry}") delete_policy(kube_apis.custom_objects, "waf-policy", test_namespace) self.restore_default_vs(kube_apis, virtual_server_setup) @@ -476,6 +438,7 @@ def test_ap_waf_policy_multi_logs( assert f'outcome="REJECTED"' in log_contents assert f'"my_attack_type": "[Non-browser Client' in log_esc_contents + @pytest.mark.skip_for_nginx_oss @pytest.mark.appprotect @pytest.mark.parametrize( @@ -512,7 +475,7 @@ def restore_default_vsr(self, kube_apis, v_s_route_setup) -> None: @pytest.mark.parametrize( "ap_enable", [ - True, + True, # False ], ) @@ -551,9 +514,7 @@ def test_ap_waf_policy_block( v_s_route_setup.route_m.namespace, ) wait_before_test() - ap_crd_info = read_ap_custom_resource( - kube_apis.custom_objects, test_namespace, "appolicies", ap_policy_uds - ) + ap_crd_info = read_ap_custom_resource(kube_apis.custom_objects, test_namespace, "appolicies", ap_policy_uds) assert_ap_crd_info(ap_crd_info, ap_policy_uds) wait_before_test(120) response = requests.get( diff --git a/tests/suite/test_app_protect_waf_policies_grpc.py b/tests/suite/test_app_protect_waf_policies_grpc.py index 0620f76b10..995a0b6dc7 100644 --- a/tests/suite/test_app_protect_waf_policies_grpc.py +++ b/tests/suite/test_app_protect_waf_policies_grpc.py @@ -1,49 +1,38 @@ import grpc import pytest -from settings import TEST_DATA, DEPLOYMENTS -from suite.custom_resource_fixtures import ( - VirtualServerRoute, - VirtualServerSetup, - VirtualServerRouteSetup +from settings import DEPLOYMENTS, TEST_DATA +from suite.ap_resources_utils import ( + create_ap_logconf_from_yaml, + create_ap_policy_from_yaml, + create_ap_waf_policy_from_yaml, + delete_ap_logconf, + delete_ap_policy, ) +from suite.custom_resource_fixtures import VirtualServerRoute, VirtualServerRouteSetup, VirtualServerSetup from suite.grpc.helloworld_pb2 import HelloRequest from suite.grpc.helloworld_pb2_grpc import GreeterStub +from suite.policy_resources_utils import delete_policy from suite.resources_utils import ( - wait_before_test, - wait_before_test, - get_file_contents, - replace_configmap_from_yaml, - create_secret_from_yaml, create_example_app, - wait_until_all_pods_are_ready, - delete_items_from_yaml, - delete_common_app, create_items_from_yaml, - get_service_endpoint, create_namespace_with_name_from_yaml, + create_secret_from_yaml, + delete_common_app, + delete_items_from_yaml, delete_namespace, -) -from suite.vs_vsr_resources_utils import( - delete_virtual_server, - create_virtual_server_from_yaml, - create_v_s_route_from_yaml, -) -from suite.policy_resources_utils import( - delete_policy, -) -from suite.ap_resources_utils import ( - create_ap_logconf_from_yaml, - create_ap_policy_from_yaml, - delete_ap_policy, - delete_ap_logconf, - create_ap_waf_policy_from_yaml + get_file_contents, + get_service_endpoint, + replace_configmap_from_yaml, + wait_before_test, + wait_until_all_pods_are_ready, ) from suite.ssl_utils import get_certificate -from suite.yaml_utils import ( - get_first_host_from_yaml, - get_paths_from_vs_yaml, - get_paths_from_vsr_yaml +from suite.vs_vsr_resources_utils import ( + create_v_s_route_from_yaml, + create_virtual_server_from_yaml, + delete_virtual_server, ) +from suite.yaml_utils import get_first_host_from_yaml, get_paths_from_vs_yaml, get_paths_from_vsr_yaml log_loc = f"/var/log/messages" valid_resp_txt = "Hello" @@ -61,14 +50,16 @@ @pytest.fixture(scope="class") -def appprotect_setup(request, kube_apis, ingress_controller_endpoint, ingress_controller_prerequisites, test_namespace) -> None: +def appprotect_setup( + request, kube_apis, ingress_controller_endpoint, ingress_controller_prerequisites, test_namespace +) -> None: """ - Replace the config map, create the TLS secret, deploy grpc application, and deploy + Replace the config map, create the TLS secret, deploy grpc application, and deploy all the AppProtect(dataguard-alarm) resources under test in one namespace. :param request: pytest fixture :param kube_apis: client apis - :param ingress_controller_prerequisites: + :param ingress_controller_prerequisites: :param test_namespace: """ policy_method = request.param["policy"] @@ -76,60 +67,52 @@ def appprotect_setup(request, kube_apis, ingress_controller_endpoint, ingress_co vsr = None try: print("------------------------- Replace ConfigMap with HTTP2 -------------------------") - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - cm_source) + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + cm_source, + ) if vs_or_vsr == "vs": - (src_pol_name, vs_name, vs_host, vs_paths) = ap_vs_setup( - kube_apis, test_namespace, policy_method) + (src_pol_name, vs_name, vs_host, vs_paths) = ap_vs_setup(kube_apis, test_namespace, policy_method) elif vs_or_vsr == "vsr": - (src_pol_name, vsr_ns, vs_host, vs_name, vsr) = ap_vsr_setup( - kube_apis, test_namespace, policy_method) + (src_pol_name, vsr_ns, vs_host, vs_name, vsr) = ap_vsr_setup(kube_apis, test_namespace, policy_method) wait_before_test(120) except Exception as ex: - cleanup( - kube_apis, ingress_controller_prerequisites, src_pol_name, test_namespace, vs_or_vsr, vs_name, vsr) + cleanup(kube_apis, ingress_controller_prerequisites, src_pol_name, test_namespace, vs_or_vsr, vs_name, vsr) + def fin(): print("Clean up:") - cleanup( - kube_apis, ingress_controller_prerequisites, src_pol_name, test_namespace, vs_or_vsr, vs_name, vsr) + cleanup(kube_apis, ingress_controller_prerequisites, src_pol_name, test_namespace, vs_or_vsr, vs_name, vsr) request.addfinalizer(fin) if vs_or_vsr == "vs": - return VirtualServerSetup( - ingress_controller_endpoint, test_namespace, vs_host, vs_name, vs_paths - ) + return VirtualServerSetup(ingress_controller_endpoint, test_namespace, vs_host, vs_name, vs_paths) elif vs_or_vsr == "vsr": - return VirtualServerRouteSetup( - ingress_controller_endpoint, vsr_ns, vs_host, vs_name, vsr, None - ) + return VirtualServerRouteSetup(ingress_controller_endpoint, vsr_ns, vs_host, vs_name, vsr, None) + def ap_vs_setup(kube_apis, test_namespace, policy_method) -> tuple: - src_pol_name, vs_name = ap_generic_setup( - kube_apis, test_namespace, test_namespace, - policy_method, waf_spec_vs_src) + src_pol_name, vs_name = ap_generic_setup(kube_apis, test_namespace, test_namespace, policy_method, waf_spec_vs_src) vs_host = get_first_host_from_yaml(waf_spec_vs_src) vs_paths = get_paths_from_vs_yaml(waf_spec_vs_src) return (src_pol_name, vs_name, vs_host, vs_paths) + def ap_vsr_setup(kube_apis, test_namespace, policy_method) -> tuple: print(f"------------------------- Deploy namespace ---------------------------") vs_routes_ns = "grpcs" - vsr_ns = create_namespace_with_name_from_yaml( - kube_apis.v1, vs_routes_ns, f"{TEST_DATA}/common/ns.yaml") - src_pol_name, vs_name = ap_generic_setup( - kube_apis, vsr_ns, test_namespace, policy_method, - vsr_vs_yaml) + vsr_ns = create_namespace_with_name_from_yaml(kube_apis.v1, vs_routes_ns, f"{TEST_DATA}/common/ns.yaml") + src_pol_name, vs_name = ap_generic_setup(kube_apis, vsr_ns, test_namespace, policy_method, vsr_vs_yaml) vs_host = get_first_host_from_yaml(vsr_vs_yaml) print("------------------------- Deploy Virtual Server Route ----------------------------") - vsr_name = create_v_s_route_from_yaml( - kube_apis.custom_objects, waf_subroute_vsr_src, vsr_ns) + vsr_name = create_v_s_route_from_yaml(kube_apis.custom_objects, waf_subroute_vsr_src, vsr_ns) vsr_paths = get_paths_from_vsr_yaml(waf_subroute_vsr_src) vsr = VirtualServerRoute(vsr_ns, vsr_name, vsr_paths) return (src_pol_name, vsr_ns, vs_host, vs_name, vsr) + def ap_generic_setup(kube_apis, vs_namespace, test_namespace, policy_method, vs_yaml): src_pol_yaml = f"{TEST_DATA}/ap-waf-grpc/policies/waf-block-{policy_method}.yaml" print("------------------------- Deploy logconf -----------------------------") @@ -150,21 +133,29 @@ def ap_generic_setup(kube_apis, vs_namespace, test_namespace, policy_method, vs_ create_secret_from_yaml(kube_apis.v1, vs_namespace, src_vs_sec_yaml) print(f"------------------------- Deploy policy ---------------------------") src_pol_name = create_ap_waf_policy_from_yaml( - kube_apis.custom_objects, src_pol_yaml, vs_namespace, test_namespace, - True, True, ap_pol_name, log_name, f"syslog:server={syslog_ep}:514") + kube_apis.custom_objects, + src_pol_yaml, + vs_namespace, + test_namespace, + True, + True, + ap_pol_name, + log_name, + f"syslog:server={syslog_ep}:514", + ) print("------------------------- Deploy Virtual Server -----------------------------------") - vs_name = create_virtual_server_from_yaml( - kube_apis.custom_objects, vs_yaml, vs_namespace) + vs_name = create_virtual_server_from_yaml(kube_apis.custom_objects, vs_yaml, vs_namespace) return (src_pol_name, vs_name) -def cleanup(kube_apis, ingress_controller_prerequisites, src_pol_name, - test_namespace, vs_or_vsr, vs_name, vsr) -> None: + +def cleanup(kube_apis, ingress_controller_prerequisites, src_pol_name, test_namespace, vs_or_vsr, vs_name, vsr) -> None: vsr_namespace = test_namespace if vs_or_vsr == "vs" else vsr.namespace replace_configmap_from_yaml( kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], + ingress_controller_prerequisites.config_map["metadata"]["name"], ingress_controller_prerequisites.namespace, - f"{DEPLOYMENTS}/common/nginx-config.yaml") + f"{DEPLOYMENTS}/common/nginx-config.yaml", + ) delete_ap_logconf(kube_apis.custom_objects, log_name, test_namespace) delete_ap_policy(kube_apis.custom_objects, ap_pol_name, test_namespace) delete_policy(kube_apis.custom_objects, src_pol_name, vsr_namespace) @@ -177,11 +168,12 @@ def cleanup(kube_apis, ingress_controller_prerequisites, src_pol_name, print("Delete test namespaces") delete_namespace(kube_apis.v1, vsr.namespace) + def grpc_waf_block(kube_apis, test_namespace, public_ip, vs_host, port_ssl): cert = get_certificate(public_ip, vs_host, port_ssl) - target = f'{public_ip}:{port_ssl}' + target = f"{public_ip}:{port_ssl}" credentials = grpc.ssl_channel_credentials(root_certificates=cert.encode()) - options = (('grpc.ssl_target_name_override', vs_host),) + options = (("grpc.ssl_target_name_override", vs_host),) with grpc.secure_channel(target, credentials, options) as channel: stub = GreeterStub(channel) @@ -194,11 +186,12 @@ def grpc_waf_block(kube_apis, test_namespace, public_ip, vs_host, port_ssl): print(ex) assert invalid_resp_text in ex + def grpc_waf_allow(kube_apis, test_namespace, public_ip, vs_host, port_ssl): cert = get_certificate(public_ip, vs_host, port_ssl) - target = f'{public_ip}:{port_ssl}' + target = f"{public_ip}:{port_ssl}" credentials = grpc.ssl_channel_credentials(root_certificates=cert.encode()) - options = (('grpc.ssl_target_name_override', vs_host),) + options = (("grpc.ssl_target_name_override", vs_host),) with grpc.secure_channel(target, credentials, options) as channel: stub = GreeterStub(channel) @@ -229,49 +222,80 @@ def grpc_waf_allow(kube_apis, test_namespace, public_ip, vs_host, port_ssl): indirect=True, ) class TestAppProtectVSGrpc: - @pytest.mark.parametrize("appprotect_setup", [{"policy": "sayhello", "vs_or_vsr": "vs",}], indirect=True) + @pytest.mark.parametrize( + "appprotect_setup", + [ + { + "policy": "sayhello", + "vs_or_vsr": "vs", + } + ], + indirect=True, + ) def test_responses_grpc_block( - self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller_with_ap, - appprotect_setup, test_namespace): + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller_with_ap, + appprotect_setup, + test_namespace, + ): """ Test grpc-block-hello AppProtect policy: Blocks /sayhello gRPC method only Client sends request to /sayhello """ - grpc_waf_block(kube_apis, - test_namespace, - appprotect_setup.public_endpoint.public_ip, - appprotect_setup.vs_host, - appprotect_setup.public_endpoint.port_ssl) + grpc_waf_block( + kube_apis, + test_namespace, + appprotect_setup.public_endpoint.public_ip, + appprotect_setup.vs_host, + appprotect_setup.public_endpoint.port_ssl, + ) syslog_pod = kube_apis.v1.list_namespaced_pod(test_namespace).items[-1].metadata.name log_contents = get_file_contents(kube_apis.v1, log_loc, syslog_pod, test_namespace) assert ( - 'ASM:attack_type="Directory Indexing"' in log_contents and - 'violations="Illegal gRPC method"' in log_contents and - 'severity="Error"' in log_contents and - 'outcome="REJECTED"' in log_contents + 'ASM:attack_type="Directory Indexing"' in log_contents + and 'violations="Illegal gRPC method"' in log_contents + and 'severity="Error"' in log_contents + and 'outcome="REJECTED"' in log_contents ) - @pytest.mark.parametrize("appprotect_setup", [{"policy": "saygoodbye", "vs_or_vsr": "vs",}], indirect=True) + @pytest.mark.parametrize( + "appprotect_setup", + [ + { + "policy": "saygoodbye", + "vs_or_vsr": "vs", + } + ], + indirect=True, + ) def test_responses_grpc_allow( - self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller_with_ap, - appprotect_setup, test_namespace - ): + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller_with_ap, + appprotect_setup, + test_namespace, + ): """ Test grpc-block-goodbye AppProtect policy: Blocks /saygoodbye gRPC method only Client sends request to /sayhello thus should pass """ - grpc_waf_allow(kube_apis, - test_namespace, - appprotect_setup.public_endpoint.public_ip, - appprotect_setup.vs_host, - appprotect_setup.public_endpoint.port_ssl) + grpc_waf_allow( + kube_apis, + test_namespace, + appprotect_setup.public_endpoint.public_ip, + appprotect_setup.vs_host, + appprotect_setup.public_endpoint.port_ssl, + ) syslog_pod = kube_apis.v1.list_namespaced_pod(test_namespace).items[-1].metadata.name log_contents = get_file_contents(kube_apis.v1, log_loc, syslog_pod, test_namespace) assert ( - 'ASM:attack_type="N/A"' in log_contents and - 'violations="N/A"' in log_contents and - 'severity="Informational"' in log_contents and - 'outcome="PASSED"' in log_contents + 'ASM:attack_type="N/A"' in log_contents + and 'violations="N/A"' in log_contents + and 'severity="Informational"' in log_contents + and 'outcome="PASSED"' in log_contents ) @@ -292,32 +316,53 @@ def test_responses_grpc_allow( indirect=True, ) class TestAppProtectVSRGrpc: - @pytest.mark.parametrize("appprotect_setup", [{"policy": "sayhello", "vs_or_vsr": "vsr",}], indirect=True) + @pytest.mark.parametrize( + "appprotect_setup", + [ + { + "policy": "sayhello", + "vs_or_vsr": "vsr", + } + ], + indirect=True, + ) def test_responses_grpc_block( - self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller_with_ap, - appprotect_setup, test_namespace - ): + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller_with_ap, + appprotect_setup, + test_namespace, + ): """ Test grpc-block-hello AppProtect policy: Blocks /sayhello gRPC method only Client sends request to /sayhello """ - grpc_waf_block(kube_apis, - appprotect_setup.namespace, - appprotect_setup.public_endpoint.public_ip, - appprotect_setup.vs_host, - appprotect_setup.public_endpoint.port_ssl) + grpc_waf_block( + kube_apis, + appprotect_setup.namespace, + appprotect_setup.public_endpoint.public_ip, + appprotect_setup.vs_host, + appprotect_setup.public_endpoint.port_ssl, + ) @pytest.mark.parametrize("appprotect_setup", [{"policy": "saygoodbye", "vs_or_vsr": "vsr"}], indirect=True) def test_responses_grpc_allow( - self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller_with_ap, - appprotect_setup, test_namespace - ): + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller_with_ap, + appprotect_setup, + test_namespace, + ): """ Test grpc-block-goodbye AppProtect policy: Blocks /saygoodbye gRPC method only Client sends request to /sayhello thus should pass """ - grpc_waf_allow(kube_apis, - appprotect_setup.namespace, - appprotect_setup.public_endpoint.public_ip, - appprotect_setup.vs_host, - appprotect_setup.public_endpoint.port_ssl) + grpc_waf_allow( + kube_apis, + appprotect_setup.namespace, + appprotect_setup.public_endpoint.public_ip, + appprotect_setup.vs_host, + appprotect_setup.public_endpoint.port_ssl, + ) diff --git a/tests/suite/test_app_protect_watch_namespace.py b/tests/suite/test_app_protect_watch_namespace.py index 3971e6d665..3310192769 100644 --- a/tests/suite/test_app_protect_watch_namespace.py +++ b/tests/suite/test_app_protect_watch_namespace.py @@ -1,27 +1,26 @@ -import requests -import pytest import time -from settings import TEST_DATA, DEPLOYMENTS +import pytest +import requests +from settings import DEPLOYMENTS, TEST_DATA from suite.ap_resources_utils import ( create_ap_logconf_from_yaml, create_ap_policy_from_yaml, - delete_ap_policy, delete_ap_logconf, + delete_ap_policy, ) from suite.resources_utils import ( - wait_before_test, create_example_app, - wait_until_all_pods_are_ready, + create_ingress_with_ap_annotations, create_items_from_yaml, - delete_items_from_yaml, + create_namespace_with_name_from_yaml, delete_common_app, + delete_items_from_yaml, delete_namespace, ensure_connection_to_public_endpoint, - create_ingress_with_ap_annotations, - create_namespace_with_name_from_yaml, ensure_response_from_backend, wait_before_test, + wait_until_all_pods_are_ready, ) from suite.yaml_utils import get_first_ingress_host_from_yaml @@ -63,10 +62,10 @@ def backend_setup(request, kube_apis, ingress_controller_endpoint) -> BackendSet :return: BackendSetup """ policy = "file-block" - + create_namespace_with_name_from_yaml(kube_apis.v1, test_namespace, f"{TEST_DATA}/common/ns.yaml") print("------------------------- Deploy backend application -------------------------") - + create_example_app(kube_apis, "simple", test_namespace) req_url = f"https://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.port_ssl}/backend1" req_url_2 = f"https://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.port_ssl}/backend2" @@ -118,87 +117,75 @@ def fin(): return BackendSetup(req_url, req_url_2, metrics_url, ingress_host) -# the first case does not set "-watch-namespace" so the policy is configured on the ingress. + +# the first case does not set "-watch-namespace" so the policy is configured on the ingress. # This causes the traffic to be blocked + @pytest.mark.skip_for_nginx_oss @pytest.mark.appprotect @pytest.mark.parametrize( "crd_ingress_controller_with_ap", - [ - { - "extra_args": [ - f"-enable-custom-resources", - f"-enable-app-protect", - f"-enable-prometheus-metrics" - ] - } - ], + [{"extra_args": [f"-enable-custom-resources", f"-enable-app-protect", f"-enable-prometheus-metrics"]}], indirect=True, ) class TestAppProtectWatchNamespaceDisabled: - def test_responses( - self, request, kube_apis, crd_ingress_controller_with_ap, backend_setup - ): + def test_responses(self, request, kube_apis, crd_ingress_controller_with_ap, backend_setup): """ Test file_block AppProtect policy without -watch-namespace """ print("------------- Run test for AP policy: file-block --------------") print(f"Request URL: {backend_setup.req_url} and Host: {backend_setup.ingress_host}") - ensure_response_from_backend( - backend_setup.req_url, backend_setup.ingress_host, check404=True - ) + ensure_response_from_backend(backend_setup.req_url, backend_setup.ingress_host, check404=True) print("----------------------- Send request ----------------------") resp = requests.get( f"{backend_setup.req_url}/test.bat", headers={"host": backend_setup.ingress_host}, verify=False ) - + print(resp.text) assert invalid_resp_body in resp.text assert resp.status_code == 200 -# In this test case the "-watch-namespace" param is set so the policy in policy_namespace + +# In this test case the "-watch-namespace" param is set so the policy in policy_namespace # Is not configured on the ingress -> NAP uses the default policy which will not block the same request. + @pytest.mark.skip_for_nginx_oss @pytest.mark.appprotect @pytest.mark.parametrize( "crd_ingress_controller_with_ap", [ - { + { "extra_args": [ f"-enable-custom-resources", f"-enable-app-protect", f"-enable-prometheus-metrics", - f"-watch-namespace={test_namespace}" + f"-watch-namespace={test_namespace}", ] } ], indirect=True, ) class TestAppProtectWatchNamespaceEnabled: - def test_responses( - self, request, kube_apis, crd_ingress_controller_with_ap, backend_setup, test_namespace - ): + def test_responses(self, request, kube_apis, crd_ingress_controller_with_ap, backend_setup, test_namespace): """ Test file-block AppProtect policy with -watch-namespace """ print("------------- Run test for AP policy: file-block --------------") print(f"Request URL: {backend_setup.req_url} and Host: {backend_setup.ingress_host}") - ensure_response_from_backend( - backend_setup.req_url, backend_setup.ingress_host, check404=True - ) + ensure_response_from_backend(backend_setup.req_url, backend_setup.ingress_host, check404=True) print("----------------------- Send request ----------------------") resp = requests.get( f"{backend_setup.req_url}/test.bat", headers={"host": backend_setup.ingress_host}, verify=False ) - + print(resp.text) assert valid_resp_body in resp.text - assert resp.status_code == 200 \ No newline at end of file + assert resp.status_code == 200 diff --git a/tests/suite/test_auth_basic_auth_mergeable.py b/tests/suite/test_auth_basic_auth_mergeable.py index 9c81bcc34d..07fcee1046 100644 --- a/tests/suite/test_auth_basic_auth_mergeable.py +++ b/tests/suite/test_auth_basic_auth_mergeable.py @@ -1,19 +1,27 @@ -import requests -import pytest - from base64 import b64encode + +import pytest +import requests +from settings import TEST_DATA from suite.fixtures import PublicEndpoint -from suite.resources_utils import create_secret_from_yaml, delete_secret, replace_secret,\ - ensure_connection_to_public_endpoint, wait_before_test -from suite.resources_utils import create_items_from_yaml, delete_items_from_yaml, create_example_app, delete_common_app -from suite.resources_utils import wait_until_all_pods_are_ready, is_secret_present +from suite.resources_utils import ( + create_example_app, + create_items_from_yaml, + create_secret_from_yaml, + delete_common_app, + delete_items_from_yaml, + delete_secret, + ensure_connection_to_public_endpoint, + is_secret_present, + replace_secret, + wait_before_test, + wait_until_all_pods_are_ready, +) from suite.yaml_utils import get_first_ingress_host_from_yaml -from settings import TEST_DATA + def to_base64(b64_string): - return b64encode( - b64_string.encode('ascii') - ).decode('ascii') + return b64encode(b64_string.encode("ascii")).decode("ascii") class AuthBasicAuthMergeableSetup: @@ -25,9 +33,12 @@ class AuthBasicAuthMergeableSetup: ingress_host (str): a hostname from Ingress resource master_secret_name (str): minion_secret_name (str): - credentials_dict ([]): a dictionnary of credentials for testing + credentials_dict ([]): a dictionary of credentials for testing """ - def __init__(self, public_endpoint: PublicEndpoint, ingress_host, master_secret_name, minion_secret_name, credentials_dict): + + def __init__( + self, public_endpoint: PublicEndpoint, ingress_host, master_secret_name, minion_secret_name, credentials_dict + ): self.public_endpoint = public_endpoint self.ingress_host = ingress_host self.master_secret_name = master_secret_name @@ -36,20 +47,30 @@ def __init__(self, public_endpoint: PublicEndpoint, ingress_host, master_secret_ @pytest.fixture(scope="class") -def auth_basic_auth_setup(request, kube_apis, ingress_controller_endpoint, ingress_controller, test_namespace) -> AuthBasicAuthMergeableSetup: +def auth_basic_auth_setup( + request, kube_apis, ingress_controller_endpoint, ingress_controller, test_namespace +) -> AuthBasicAuthMergeableSetup: credentials_dict = {"master": get_credentials_from_file("master"), "minion": get_credentials_from_file("minion")} - master_secret_name = create_secret_from_yaml(kube_apis.v1, test_namespace, - f"{TEST_DATA}/auth-basic-auth-mergeable/auth-basic-master-secret.yaml") - minion_secret_name = create_secret_from_yaml(kube_apis.v1, test_namespace, - f"{TEST_DATA}/auth-basic-auth-mergeable/auth-basic-minion-secret.yaml") - print("------------------------- Deploy Auth Basic Auth Mergeable Minions Example -----------------------------------") - create_items_from_yaml(kube_apis, f"{TEST_DATA}/auth-basic-auth-mergeable/mergeable/auth-basic-auth-ingress.yaml", test_namespace) - ingress_host = get_first_ingress_host_from_yaml(f"{TEST_DATA}/auth-basic-auth-mergeable/mergeable/auth-basic-auth-ingress.yaml") + master_secret_name = create_secret_from_yaml( + kube_apis.v1, test_namespace, f"{TEST_DATA}/auth-basic-auth-mergeable/auth-basic-master-secret.yaml" + ) + minion_secret_name = create_secret_from_yaml( + kube_apis.v1, test_namespace, f"{TEST_DATA}/auth-basic-auth-mergeable/auth-basic-minion-secret.yaml" + ) + print( + "------------------------- Deploy Auth Basic Auth Mergeable Minions Example -----------------------------------" + ) + create_items_from_yaml( + kube_apis, f"{TEST_DATA}/auth-basic-auth-mergeable/mergeable/auth-basic-auth-ingress.yaml", test_namespace + ) + ingress_host = get_first_ingress_host_from_yaml( + f"{TEST_DATA}/auth-basic-auth-mergeable/mergeable/auth-basic-auth-ingress.yaml" + ) create_example_app(kube_apis, "simple", test_namespace) wait_until_all_pods_are_ready(kube_apis.v1, test_namespace) - ensure_connection_to_public_endpoint(ingress_controller_endpoint.public_ip, - ingress_controller_endpoint.port, - ingress_controller_endpoint.port_ssl) + ensure_connection_to_public_endpoint( + ingress_controller_endpoint.public_ip, ingress_controller_endpoint.port, ingress_controller_endpoint.port_ssl + ) wait_before_test(2) def fin(): @@ -63,12 +84,15 @@ def fin(): print("Clean up the Auth Basic Auth Mergeable Minions Application:") delete_common_app(kube_apis, "simple", test_namespace) - delete_items_from_yaml(kube_apis, f"{TEST_DATA}/auth-basic-auth-mergeable/mergeable/auth-basic-auth-ingress.yaml", - test_namespace) + delete_items_from_yaml( + kube_apis, f"{TEST_DATA}/auth-basic-auth-mergeable/mergeable/auth-basic-auth-ingress.yaml", test_namespace + ) request.addfinalizer(fin) - return AuthBasicAuthMergeableSetup(ingress_controller_endpoint, ingress_host, master_secret_name, minion_secret_name, credentials_dict) + return AuthBasicAuthMergeableSetup( + ingress_controller_endpoint, ingress_host, master_secret_name, minion_secret_name, credentials_dict + ) def get_credentials_from_file(creds_type) -> str: @@ -78,44 +102,56 @@ def get_credentials_from_file(creds_type) -> str: :param creds_type: 'master' or 'minion' :return: str """ - with open(f"{TEST_DATA}/auth-basic-auth-mergeable/credentials/auth-basic-auth-{creds_type}-credentials.txt", "r") as credentials_file: - return credentials_file.read().replace('\n', '') - - -step_1_expected_results = [{"creds_type": "master", "path": "", "response_code": 404}, - {"creds_type": "master", "path": "backend1", "response_code": 401}, - {"creds_type": "master", "path": "backend2", "response_code": 200}, - {"creds_type": "minion", "path": "", "response_code": 401}, - {"creds_type": "minion", "path": "backend1", "response_code": 200}, - {"creds_type": "minion", "path": "backend2", "response_code": 401}] - -step_2_expected_results = [{"creds_type": "master", "path": "", "response_code": 401}, - {"creds_type": "master", "path": "backend1", "response_code": 401}, - {"creds_type": "master", "path": "backend2", "response_code": 401}, - {"creds_type": "minion", "path": "", "response_code": 404}, - {"creds_type": "minion", "path": "backend1", "response_code": 200}, - {"creds_type": "minion", "path": "backend2", "response_code": 200}] - -step_3_expected_results = [{"creds_type": "master", "path": "", "response_code": 401}, - {"creds_type": "master", "path": "backend1", "response_code": 200}, - {"creds_type": "master", "path": "backend2", "response_code": 401}, - {"creds_type": "minion", "path": "", "response_code": 404}, - {"creds_type": "minion", "path": "backend1", "response_code": 401}, - {"creds_type": "minion", "path": "backend2", "response_code": 200}] - -step_4_expected_results = [{"creds_type": "master", "path": "", "response_code": 401}, - {"creds_type": "master", "path": "backend1", "response_code": 403}, - {"creds_type": "master", "path": "backend2", "response_code": 401}, - {"creds_type": "minion", "path": "", "response_code": 404}, - {"creds_type": "minion", "path": "backend1", "response_code": 403}, - {"creds_type": "minion", "path": "backend2", "response_code": 200}] - -step_5_expected_results = [{"creds_type": "master", "path": "", "response_code": 403}, - {"creds_type": "master", "path": "backend1", "response_code": 403}, - {"creds_type": "master", "path": "backend2", "response_code": 403}, - {"creds_type": "minion", "path": "", "response_code": 403}, - {"creds_type": "minion", "path": "backend1", "response_code": 403}, - {"creds_type": "minion", "path": "backend2", "response_code": 403}] + with open( + f"{TEST_DATA}/auth-basic-auth-mergeable/credentials/auth-basic-auth-{creds_type}-credentials.txt", "r" + ) as credentials_file: + return credentials_file.read().replace("\n", "") + + +step_1_expected_results = [ + {"creds_type": "master", "path": "", "response_code": 404}, + {"creds_type": "master", "path": "backend1", "response_code": 401}, + {"creds_type": "master", "path": "backend2", "response_code": 200}, + {"creds_type": "minion", "path": "", "response_code": 401}, + {"creds_type": "minion", "path": "backend1", "response_code": 200}, + {"creds_type": "minion", "path": "backend2", "response_code": 401}, +] + +step_2_expected_results = [ + {"creds_type": "master", "path": "", "response_code": 401}, + {"creds_type": "master", "path": "backend1", "response_code": 401}, + {"creds_type": "master", "path": "backend2", "response_code": 401}, + {"creds_type": "minion", "path": "", "response_code": 404}, + {"creds_type": "minion", "path": "backend1", "response_code": 200}, + {"creds_type": "minion", "path": "backend2", "response_code": 200}, +] + +step_3_expected_results = [ + {"creds_type": "master", "path": "", "response_code": 401}, + {"creds_type": "master", "path": "backend1", "response_code": 200}, + {"creds_type": "master", "path": "backend2", "response_code": 401}, + {"creds_type": "minion", "path": "", "response_code": 404}, + {"creds_type": "minion", "path": "backend1", "response_code": 401}, + {"creds_type": "minion", "path": "backend2", "response_code": 200}, +] + +step_4_expected_results = [ + {"creds_type": "master", "path": "", "response_code": 401}, + {"creds_type": "master", "path": "backend1", "response_code": 403}, + {"creds_type": "master", "path": "backend2", "response_code": 401}, + {"creds_type": "minion", "path": "", "response_code": 404}, + {"creds_type": "minion", "path": "backend1", "response_code": 403}, + {"creds_type": "minion", "path": "backend2", "response_code": 200}, +] + +step_5_expected_results = [ + {"creds_type": "master", "path": "", "response_code": 403}, + {"creds_type": "master", "path": "backend1", "response_code": 403}, + {"creds_type": "master", "path": "backend2", "response_code": 403}, + {"creds_type": "minion", "path": "", "response_code": 403}, + {"creds_type": "minion", "path": "backend1", "response_code": 403}, + {"creds_type": "minion", "path": "backend2", "response_code": 403}, +] @pytest.mark.ingresses @@ -125,14 +161,22 @@ def test_auth_basic_auth_response_codes(self, kube_apis, auth_basic_auth_setup, execute_checks(auth_basic_auth_setup, step_1_expected_results) print("Step 2: replace master secret") - replace_secret(kube_apis.v1, auth_basic_auth_setup.master_secret_name, test_namespace, - f"{TEST_DATA}/auth-basic-auth-mergeable/auth-basic-master-secret-updated.yaml") + replace_secret( + kube_apis.v1, + auth_basic_auth_setup.master_secret_name, + test_namespace, + f"{TEST_DATA}/auth-basic-auth-mergeable/auth-basic-master-secret-updated.yaml", + ) wait_before_test(1) execute_checks(auth_basic_auth_setup, step_2_expected_results) print("Step 3: now replace minion secret as well") - replace_secret(kube_apis.v1, auth_basic_auth_setup.minion_secret_name, test_namespace, - f"{TEST_DATA}/auth-basic-auth-mergeable/auth-basic-minion-secret-updated.yaml") + replace_secret( + kube_apis.v1, + auth_basic_auth_setup.minion_secret_name, + test_namespace, + f"{TEST_DATA}/auth-basic-auth-mergeable/auth-basic-minion-secret-updated.yaml", + ) wait_before_test(1) execute_checks(auth_basic_auth_setup, step_3_expected_results) @@ -157,9 +201,12 @@ def execute_checks(auth_basic_auth_setup, expected_results) -> None: """ for expected in expected_results: req_url = f"http://{auth_basic_auth_setup.public_endpoint.public_ip}:{auth_basic_auth_setup.public_endpoint.port}/{expected['path']}" - resp = requests.get(req_url, headers={ - "host": auth_basic_auth_setup.ingress_host, - "authorization": f"Basic {to_base64(auth_basic_auth_setup.credentials_dict[expected['creds_type']])}", - }, - allow_redirects=False) - assert resp.status_code == expected['response_code'] + resp = requests.get( + req_url, + headers={ + "host": auth_basic_auth_setup.ingress_host, + "authorization": f"Basic {to_base64(auth_basic_auth_setup.credentials_dict[expected['creds_type']])}", + }, + allow_redirects=False, + ) + assert resp.status_code == expected["response_code"] diff --git a/tests/suite/test_auth_basic_policies.py b/tests/suite/test_auth_basic_policies.py index dd6da6a518..95845e3e33 100644 --- a/tests/suite/test_auth_basic_policies.py +++ b/tests/suite/test_auth_basic_policies.py @@ -1,27 +1,23 @@ -import pytest, requests from base64 import b64encode + +import pytest +import requests from kubernetes.client.rest import ApiException +from settings import DEPLOYMENTS, TEST_DATA +from suite.custom_resources_utils import read_custom_resource +from suite.policy_resources_utils import create_policy_from_yaml, delete_policy, read_policy from suite.resources_utils import ( - wait_before_test, - replace_configmap_from_yaml, create_secret_from_yaml, delete_secret, + replace_configmap_from_yaml, replace_secret, -) -from suite.custom_resources_utils import ( - read_custom_resource, + wait_before_test, ) from suite.vs_vsr_resources_utils import ( - delete_virtual_server, create_virtual_server_from_yaml, delete_and_create_vs_from_yaml, + delete_virtual_server, ) -from suite.policy_resources_utils import ( - create_policy_from_yaml, - delete_policy, - read_policy, -) -from settings import TEST_DATA, DEPLOYMENTS std_vs_src = f"{TEST_DATA}/virtual-server/standard/virtual-server.yaml" htpasswd_sec_valid_src = f"{TEST_DATA}/auth-basic-policy/secret/htpasswd-secret-valid.yaml" @@ -60,10 +56,10 @@ ] valid_credentials = valid_credentials_list[0] + def to_base64(b64_string): - return b64encode( - b64_string.encode('ascii') - ).decode('ascii') + return b64encode(b64_string.encode("ascii")).decode("ascii") + @pytest.mark.policies @pytest.mark.parametrize( @@ -78,7 +74,10 @@ def to_base64(b64_string): f"-enable-leader-election=false", ], }, - {"example": "virtual-server", "app_type": "simple",}, + { + "example": "virtual-server", + "app_type": "simple", + }, ) ], indirect=True, @@ -93,7 +92,7 @@ def setup_single_policy(self, kube_apis, test_namespace, credentials, secret, po wait_before_test() # generate header without auth - if credentials == None : + if credentials == None: return secret_name, pol_name, {"host": vs_host} with open(credentials, "r") as file: @@ -102,16 +101,12 @@ def setup_single_policy(self, kube_apis, test_namespace, credentials, secret, po return secret_name, pol_name, headers - def setup_multiple_policies( - self, kube_apis, test_namespace, credentials, secret_list, policy_1, policy_2, vs_host - ): + def setup_multiple_policies(self, kube_apis, test_namespace, credentials, secret_list, policy_1, policy_2, vs_host): print(f"Create {len(secret_list)} htpasswd secrets") # secret_name = create_secret_from_yaml(kube_apis.v1, test_namespace, secret) secret_name_list = [] for secret in secret_list: - secret_name_list.append( - create_secret_from_yaml(kube_apis.v1, test_namespace, secret) - ) + secret_name_list.append(create_secret_from_yaml(kube_apis.v1, test_namespace, secret)) print(f"Create auth basic policy #1") pol_name_1 = create_policy_from_yaml(kube_apis.custom_objects, policy_1, test_namespace) @@ -125,12 +120,17 @@ def setup_multiple_policies( return secret_name_list, pol_name_1, pol_name_2, headers - @pytest.mark.parametrize("credentials", valid_credentials_list + invalid_credentials_list + [None] ) + @pytest.mark.parametrize("credentials", valid_credentials_list + invalid_credentials_list + [None]) def test_auth_basic_policy_credentials( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, credentials, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + credentials, ): """ - Test auth-basic-policy with no credentials, valid credentials and invalid credentials + Test auth-basic-policy with no credentials, valid credentials and invalid credentials """ secret, pol_name, headers = self.setup_single_policy( kube_apis, @@ -172,10 +172,15 @@ def test_auth_basic_policy_credentials( @pytest.mark.parametrize("htpasswd_secret", [htpasswd_sec_valid_src, htpasswd_sec_invalid_src]) def test_auth_basic_policy_secret( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, htpasswd_secret, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + htpasswd_secret, ): """ - Test auth-basic-policy with a valid and an invalid secret + Test auth-basic-policy with a valid and an invalid secret """ if htpasswd_secret == htpasswd_sec_valid_src: pol = auth_basic_pol_valid_src @@ -186,7 +191,12 @@ def test_auth_basic_policy_secret( else: pytest.fail("Invalid configuration") secret, pol_name, headers = self.setup_single_policy( - kube_apis, test_namespace, valid_credentials, htpasswd_secret, pol, virtual_server_setup.vs_host, + kube_apis, + test_namespace, + valid_credentials, + htpasswd_secret, + pol, + virtual_server_setup.vs_host, ) print(f"Patch vs with policy: {pol}") @@ -231,10 +241,15 @@ def test_auth_basic_policy_secret( @pytest.mark.smoke @pytest.mark.parametrize("policy", [auth_basic_pol_valid_src, auth_basic_pol_invalid_src]) def test_auth_basic_policy( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, policy, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + policy, ): """ - Test auth-basic-policy with a valid and an invalid policy + Test auth-basic-policy with a valid and an invalid policy """ secret, pol_name, headers = self.setup_single_policy( kube_apis, @@ -301,10 +316,14 @@ def test_auth_basic_policy( pytest.fail(f"Not a valid case or parameter") def test_auth_basic_policy_delete_secret( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, ): """ - Test if requests result in 500 when secret is deleted + Test if requests result in 500 when secret is deleted """ secret, pol_name, headers = self.setup_single_policy( kube_apis, @@ -344,10 +363,14 @@ def test_auth_basic_policy_delete_secret( assert resp2.status_code == 500 def test_auth_basic_policy_delete_policy( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, ): """ - Test if requests result in 500 when policy is deleted + Test if requests result in 500 when policy is deleted """ secret, pol_name, headers = self.setup_single_policy( kube_apis, @@ -388,16 +411,20 @@ def test_auth_basic_policy_delete_policy( assert resp2.status_code == 500 def test_auth_basic_policy_override( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, ): """ - Test if first reference to a policy in the same context takes precedence + Test if first reference to a policy in the same context takes precedence """ secret_list, pol_name_1, pol_name_2, headers = self.setup_multiple_policies( kube_apis, test_namespace, valid_credentials, - [ htpasswd_sec_valid_src, htpasswd_sec_valid_empty_src ], + [htpasswd_sec_valid_src, htpasswd_sec_valid_empty_src], auth_basic_pol_valid_src, auth_basic_pol_multi_src, virtual_server_setup.vs_host, @@ -450,25 +477,27 @@ def test_auth_basic_policy_override( virtual_server_setup.namespace, ) - assert ( - resp1.status_code == 401 - ) # 401 unauthorized, since no credentials are attached to policy in spec context + assert resp1.status_code == 401 # 401 unauthorized, since no credentials are attached to policy in spec context assert resp2.status_code == 200 assert ( resp3.status_code == 401 ) # 401 unauthorized, since no credentials are attached to policy in route context def test_auth_basic_policy_override_spec( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, ): """ - Test if policy reference in route takes precedence over policy in spec + Test if policy reference in route takes precedence over policy in spec """ secret_list, pol_name_1, pol_name_2, headers = self.setup_multiple_policies( kube_apis, test_namespace, valid_credentials, - [ htpasswd_sec_valid_src, htpasswd_sec_valid_empty_src ], + [htpasswd_sec_valid_src, htpasswd_sec_valid_empty_src], auth_basic_pol_valid_src, auth_basic_pol_multi_src, virtual_server_setup.vs_host, diff --git a/tests/suite/test_auth_basic_policies_vsr.py b/tests/suite/test_auth_basic_policies_vsr.py index 52f78e6b9e..4f9c0d8e51 100644 --- a/tests/suite/test_auth_basic_policies_vsr.py +++ b/tests/suite/test_auth_basic_policies_vsr.py @@ -1,27 +1,23 @@ -import pytest, requests from base64 import b64encode + +import pytest +import requests from kubernetes.client.rest import ApiException +from settings import DEPLOYMENTS, TEST_DATA +from suite.custom_resources_utils import read_custom_resource +from suite.policy_resources_utils import create_policy_from_yaml, delete_policy, read_policy from suite.resources_utils import ( - wait_before_test, - replace_configmap_from_yaml, create_secret_from_yaml, delete_secret, + replace_configmap_from_yaml, replace_secret, -) -from suite.custom_resources_utils import ( - read_custom_resource, -) -from suite.policy_resources_utils import ( - create_policy_from_yaml, - delete_policy, - read_policy, + wait_before_test, ) from suite.vs_vsr_resources_utils import ( delete_virtual_server, - patch_virtual_server_from_yaml, patch_v_s_route_from_yaml, + patch_virtual_server_from_yaml, ) -from settings import TEST_DATA, DEPLOYMENTS std_vs_src = f"{TEST_DATA}/virtual-server-route/standard/virtual-server.yaml" std_vsr_src = f"{TEST_DATA}/virtual-server-route/route-multiple.yaml" @@ -32,34 +28,28 @@ auth_basic_pol_multi_src = f"{TEST_DATA}/auth-basic-policy/policies/auth-basic-policy-valid-multi.yaml" auth_basic_pol_invalid_src = f"{TEST_DATA}/auth-basic-policy/policies/auth-basic-policy-invalid.yaml" auth_basic_pol_invalid_sec_src = f"{TEST_DATA}/auth-basic-policy/policies/auth-basic-policy-invalid-secret.yaml" -auth_basic_vsr_invalid_src = ( - f"{TEST_DATA}/auth-basic-policy/route-subroute/virtual-server-route-invalid-subroute.yaml" -) +auth_basic_vsr_invalid_src = f"{TEST_DATA}/auth-basic-policy/route-subroute/virtual-server-route-invalid-subroute.yaml" auth_basic_vsr_invalid_sec_src = ( f"{TEST_DATA}/auth-basic-policy/route-subroute/virtual-server-route-invalid-subroute-secret.yaml" ) auth_basic_vsr_override_src = ( f"{TEST_DATA}/auth-basic-policy/route-subroute/virtual-server-route-override-subroute.yaml" ) -auth_basic_vsr_valid_src = ( - f"{TEST_DATA}/auth-basic-policy/route-subroute/virtual-server-route-valid-subroute.yaml" -) +auth_basic_vsr_valid_src = f"{TEST_DATA}/auth-basic-policy/route-subroute/virtual-server-route-valid-subroute.yaml" auth_basic_vsr_valid_multi_src = ( f"{TEST_DATA}/auth-basic-policy/route-subroute/virtual-server-route-valid-subroute-multi.yaml" ) -auth_basic_vs_override_spec_src = ( - f"{TEST_DATA}/auth-basic-policy/route-subroute/virtual-server-vsr-spec-override.yaml" -) +auth_basic_vs_override_spec_src = f"{TEST_DATA}/auth-basic-policy/route-subroute/virtual-server-vsr-spec-override.yaml" auth_basic_vs_override_route_src = ( f"{TEST_DATA}/auth-basic-policy/route-subroute/virtual-server-vsr-route-override.yaml" ) valid_credentials = f"{TEST_DATA}/auth-basic-policy/credentials.txt" invalid_credentials = f"{TEST_DATA}/auth-basic-policy/invalid-credentials.txt" + def to_base64(b64_string): - return b64encode( - b64_string.encode('ascii') - ).decode('ascii') + return b64encode(b64_string.encode("ascii")).decode("ascii") + @pytest.mark.policies @pytest.mark.parametrize( @@ -90,7 +80,7 @@ def setup_single_policy(self, kube_apis, namespace, credentials, secret, policy, wait_before_test() # generate header without auth - if credentials == None : + if credentials == None: return secret_name, pol_name, {"host": vs_host} with open(credentials, "r") as file: @@ -99,16 +89,12 @@ def setup_single_policy(self, kube_apis, namespace, credentials, secret, policy, return secret_name, pol_name, headers - def setup_multiple_policies( - self, kube_apis, namespace, credentials, secret_list, policy_1, policy_2, vs_host - ): + def setup_multiple_policies(self, kube_apis, namespace, credentials, secret_list, policy_1, policy_2, vs_host): print(f"Create {len(secret_list)} htpasswd secrets") # secret_name = create_secret_from_yaml(kube_apis.v1, namespace, secret) secret_name_list = [] for secret in secret_list: - secret_name_list.append( - create_secret_from_yaml(kube_apis.v1, namespace, secret) - ) + secret_name_list.append(create_secret_from_yaml(kube_apis.v1, namespace, secret)) print(f"Create auth basic policy #1") pol_name_1 = create_policy_from_yaml(kube_apis.custom_objects, policy_1, namespace) @@ -133,7 +119,7 @@ def test_auth_basic_policy_credentials( credentials, ): """ - Test auth-basic-policy with no credentials, valid credentials and invalid credentials + Test auth-basic-policy with no credentials, valid credentials and invalid credentials """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" secret, pol_name, headers = self.setup_single_policy( @@ -185,7 +171,7 @@ def test_auth_basic_policy_secret( htpasswd_secret, ): """ - Test auth-basic-policy with a valid and an invalid secret + Test auth-basic-policy with a valid and an invalid secret """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" if htpasswd_secret == htpasswd_sec_valid_src: @@ -215,7 +201,10 @@ def test_auth_basic_policy_secret( ) wait_before_test() - resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) + resp = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers=headers, + ) print(resp.status_code) crd_info = read_custom_resource( @@ -257,7 +246,7 @@ def test_auth_basic_policy( policy, ): """ - Test auth-basic-policy with a valid and an invalid policy + Test auth-basic-policy with a valid and an invalid policy """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" if policy == auth_basic_pol_valid_src: @@ -336,7 +325,7 @@ def test_auth_basic_policy_delete_secret( test_namespace, ): """ - Test if requests result in 500 when secret is deleted + Test if requests result in 500 when secret is deleted """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" secret, pol_name, headers = self.setup_single_policy( @@ -357,11 +346,17 @@ def test_auth_basic_policy_delete_secret( ) wait_before_test() - resp1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) + resp1 = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers=headers, + ) print(resp1.status_code) delete_secret(kube_apis.v1, secret, v_s_route_setup.route_m.namespace) - resp2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) + resp2 = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers=headers, + ) print(resp2.status_code) crd_info = read_custom_resource( kube_apis.custom_objects, @@ -396,7 +391,7 @@ def test_auth_basic_policy_delete_policy( test_namespace, ): """ - Test if requests result in 500 when policy is deleted + Test if requests result in 500 when policy is deleted """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" secret, pol_name, headers = self.setup_single_policy( @@ -417,11 +412,17 @@ def test_auth_basic_policy_delete_policy( ) wait_before_test() - resp1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) + resp1 = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers=headers, + ) print(resp1.status_code) delete_policy(kube_apis.custom_objects, pol_name, v_s_route_setup.route_m.namespace) - resp2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) + resp2 = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers=headers, + ) print(resp2.status_code) crd_info = read_custom_resource( kube_apis.custom_objects, @@ -440,10 +441,7 @@ def test_auth_basic_policy_delete_policy( assert resp1.status_code == 200 assert f"Request ID:" in resp1.text assert crd_info["status"]["state"] == "Warning" - assert ( - f"{v_s_route_setup.route_m.namespace}/{pol_name} is missing" - in crd_info["status"]["message"] - ) + assert f"{v_s_route_setup.route_m.namespace}/{pol_name} is missing" in crd_info["status"]["message"] assert resp2.status_code == 500 assert f"Internal Server Error" in resp2.text @@ -456,15 +454,15 @@ def test_auth_basic_policy_override( test_namespace, ): """ - Test if first reference to a policy in the same context(subroute) takes precedence, - i.e. in this case, policy with empty htpasswd over policy with htpasswd. + Test if first reference to a policy in the same context(subroute) takes precedence, + i.e. in this case, policy with empty htpasswd over policy with htpasswd. """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" secret_list, pol_name_1, pol_name_2, headers = self.setup_multiple_policies( kube_apis, v_s_route_setup.route_m.namespace, valid_credentials, - [ htpasswd_sec_valid_src, htpasswd_sec_valid_empty_src ], + [htpasswd_sec_valid_src, htpasswd_sec_valid_empty_src], auth_basic_pol_valid_src, auth_basic_pol_multi_src, v_s_route_setup.vs_host, @@ -501,10 +499,7 @@ def test_auth_basic_policy_override( ) assert resp.status_code == 401 assert f"Authorization Required" in resp.text - assert ( - f"Multiple basic auth policies in the same context is not valid." - in crd_info["status"]["message"] - ) + assert f"Multiple basic auth policies in the same context is not valid." in crd_info["status"]["message"] @pytest.mark.parametrize("vs_src", [auth_basic_vs_override_route_src, auth_basic_vs_override_spec_src]) def test_auth_basic_policy_override_vs_vsr( @@ -517,16 +512,16 @@ def test_auth_basic_policy_override_vs_vsr( vs_src, ): """ - Test if policy specified in vsr:subroute (policy without $httptoken) takes preference over policy specified in: - 1. vs:spec (policy with $httptoken) - 2. vs:route (policy with $httptoken) + Test if policy specified in vsr:subroute (policy without $httptoken) takes preference over policy specified in: + 1. vs:spec (policy with $httptoken) + 2. vs:route (policy with $httptoken) """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" secret_list, pol_name_1, pol_name_2, headers = self.setup_multiple_policies( kube_apis, v_s_route_setup.route_m.namespace, valid_credentials, - [ htpasswd_sec_valid_src, htpasswd_sec_valid_empty_src ], + [htpasswd_sec_valid_src, htpasswd_sec_valid_empty_src], auth_basic_pol_valid_src, auth_basic_pol_multi_src, v_s_route_setup.vs_host, @@ -540,11 +535,17 @@ def test_auth_basic_policy_override_vs_vsr( v_s_route_setup.route_m.namespace, ) patch_virtual_server_from_yaml( - kube_apis.custom_objects, v_s_route_setup.vs_name, vs_src, v_s_route_setup.namespace, + kube_apis.custom_objects, + v_s_route_setup.vs_name, + vs_src, + v_s_route_setup.namespace, ) wait_before_test() - resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) + resp = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers=headers, + ) print(resp.status_code) delete_policy(kube_apis.custom_objects, pol_name_1, v_s_route_setup.route_m.namespace) diff --git a/tests/suite/test_auth_basic_secrets.py b/tests/suite/test_auth_basic_secrets.py index 42bd683cb1..8edb3b8c88 100644 --- a/tests/suite/test_auth_basic_secrets.py +++ b/tests/suite/test_auth_basic_secrets.py @@ -1,18 +1,27 @@ -import requests -import pytest - from base64 import b64encode + +import pytest +import requests +from settings import TEST_DATA from suite.fixtures import PublicEndpoint -from suite.resources_utils import create_secret_from_yaml, delete_secret, replace_secret, ensure_connection_to_public_endpoint, wait_before_test -from suite.resources_utils import create_items_from_yaml, delete_items_from_yaml, create_example_app, delete_common_app -from suite.resources_utils import wait_until_all_pods_are_ready, is_secret_present +from suite.resources_utils import ( + create_example_app, + create_items_from_yaml, + create_secret_from_yaml, + delete_common_app, + delete_items_from_yaml, + delete_secret, + ensure_connection_to_public_endpoint, + is_secret_present, + replace_secret, + wait_before_test, + wait_until_all_pods_are_ready, +) from suite.yaml_utils import get_first_ingress_host_from_yaml -from settings import TEST_DATA + def to_base64(b64_string): - return b64encode( - b64_string.encode('ascii') - ).decode('ascii') + return b64encode(b64_string.encode("ascii")).decode("ascii") class AuthBasicSecretsSetup: @@ -24,6 +33,7 @@ class AuthBasicSecretsSetup: ingress_host (str): credentials (str): """ + def __init__(self, public_endpoint: PublicEndpoint, ingress_host, credentials): self.public_endpoint = public_endpoint self.ingress_host = ingress_host @@ -37,28 +47,36 @@ class AuthBasicSecret: Attributes: secret_name (str): """ + def __init__(self, secret_name): self.secret_name = secret_name @pytest.fixture(scope="class", params=["standard", "mergeable"]) -def auth_basic_secrets_setup(request, kube_apis, ingress_controller_endpoint, ingress_controller, test_namespace) -> AuthBasicSecretsSetup: +def auth_basic_secrets_setup( + request, kube_apis, ingress_controller_endpoint, ingress_controller, test_namespace +) -> AuthBasicSecretsSetup: with open(f"{TEST_DATA}/auth-basic-secrets/credentials/credentials.txt", "r") as credentials_file: - credentials = credentials_file.read().replace('\n', '') + credentials = credentials_file.read().replace("\n", "") print("------------------------- Deploy Auth Basic Secrets Example -----------------------------------") - create_items_from_yaml(kube_apis, f"{TEST_DATA}/auth-basic-secrets/{request.param}/auth-basic-secrets-ingress.yaml", test_namespace) - ingress_host = get_first_ingress_host_from_yaml(f"{TEST_DATA}/auth-basic-secrets/{request.param}/auth-basic-secrets-ingress.yaml") + create_items_from_yaml( + kube_apis, f"{TEST_DATA}/auth-basic-secrets/{request.param}/auth-basic-secrets-ingress.yaml", test_namespace + ) + ingress_host = get_first_ingress_host_from_yaml( + f"{TEST_DATA}/auth-basic-secrets/{request.param}/auth-basic-secrets-ingress.yaml" + ) create_example_app(kube_apis, "simple", test_namespace) wait_until_all_pods_are_ready(kube_apis.v1, test_namespace) - ensure_connection_to_public_endpoint(ingress_controller_endpoint.public_ip, - ingress_controller_endpoint.port, - ingress_controller_endpoint.port_ssl) + ensure_connection_to_public_endpoint( + ingress_controller_endpoint.public_ip, ingress_controller_endpoint.port, ingress_controller_endpoint.port_ssl + ) def fin(): print("Clean up the Auth Basic Secrets Application:") delete_common_app(kube_apis, "simple", test_namespace) - delete_items_from_yaml(kube_apis, f"{TEST_DATA}/auth-basic-secrets/{request.param}/auth-basic-secrets-ingress.yaml", - test_namespace) + delete_items_from_yaml( + kube_apis, f"{TEST_DATA}/auth-basic-secrets/{request.param}/auth-basic-secrets-ingress.yaml", test_namespace + ) request.addfinalizer(fin) @@ -66,8 +84,12 @@ def fin(): @pytest.fixture -def auth_basic_secret(request, kube_apis, ingress_controller_endpoint, auth_basic_secrets_setup, test_namespace) -> AuthBasicSecret: - secret_name = create_secret_from_yaml(kube_apis.v1, test_namespace, f"{TEST_DATA}/auth-basic-secrets/auth-basic-secret.yaml") +def auth_basic_secret( + request, kube_apis, ingress_controller_endpoint, auth_basic_secrets_setup, test_namespace +) -> AuthBasicSecret: + secret_name = create_secret_from_yaml( + kube_apis.v1, test_namespace, f"{TEST_DATA}/auth-basic-secrets/auth-basic-secret.yaml" + ) wait_before_test(1) def fin(): @@ -84,32 +106,81 @@ def fin(): class TestAuthBasicSecrets: def test_response_code_200_and_server_name(self, auth_basic_secrets_setup, auth_basic_secret): req_url = f"http://{auth_basic_secrets_setup.public_endpoint.public_ip}:{auth_basic_secrets_setup.public_endpoint.port}/backend2" - resp = requests.get(req_url, headers={"host": auth_basic_secrets_setup.ingress_host, "authorization": f"Basic {to_base64(auth_basic_secrets_setup.credentials)}"}) + resp = requests.get( + req_url, + headers={ + "host": auth_basic_secrets_setup.ingress_host, + "authorization": f"Basic {to_base64(auth_basic_secrets_setup.credentials)}", + }, + ) assert resp.status_code == 200 assert f"Server name: backend2" in resp.text - def test_response_codes_after_secret_remove_and_restore(self, kube_apis, auth_basic_secrets_setup, test_namespace, auth_basic_secret): + def test_response_codes_after_secret_remove_and_restore( + self, kube_apis, auth_basic_secrets_setup, test_namespace, auth_basic_secret + ): req_url = f"http://{auth_basic_secrets_setup.public_endpoint.public_ip}:{auth_basic_secrets_setup.public_endpoint.port}/backend2" delete_secret(kube_apis.v1, auth_basic_secret.secret_name, test_namespace) wait_before_test(1) - resp = requests.get(req_url, headers={"host": auth_basic_secrets_setup.ingress_host, "authorization": f"Basic {to_base64(auth_basic_secrets_setup.credentials)}"}) + resp = requests.get( + req_url, + headers={ + "host": auth_basic_secrets_setup.ingress_host, + "authorization": f"Basic {to_base64(auth_basic_secrets_setup.credentials)}", + }, + ) assert resp.status_code == 403 - - auth_basic_secret.secret_name = create_secret_from_yaml(kube_apis.v1, test_namespace, f"{TEST_DATA}/auth-basic-secrets/auth-basic-secret.yaml") + + auth_basic_secret.secret_name = create_secret_from_yaml( + kube_apis.v1, test_namespace, f"{TEST_DATA}/auth-basic-secrets/auth-basic-secret.yaml" + ) wait_before_test(1) - resp = requests.get(req_url, headers={"host": auth_basic_secrets_setup.ingress_host, "authorization": f"Basic {to_base64(auth_basic_secrets_setup.credentials)}"}) + resp = requests.get( + req_url, + headers={ + "host": auth_basic_secrets_setup.ingress_host, + "authorization": f"Basic {to_base64(auth_basic_secrets_setup.credentials)}", + }, + ) assert resp.status_code == 200 - def test_response_code_403_with_invalid_secret(self, kube_apis, auth_basic_secrets_setup, test_namespace, auth_basic_secret): + def test_response_code_403_with_invalid_secret( + self, kube_apis, auth_basic_secrets_setup, test_namespace, auth_basic_secret + ): req_url = f"http://{auth_basic_secrets_setup.public_endpoint.public_ip}:{auth_basic_secrets_setup.public_endpoint.port}/backend2" - replace_secret(kube_apis.v1, auth_basic_secret.secret_name, test_namespace, f"{TEST_DATA}/auth-basic-secrets/auth-basic-secret-invalid.yaml") + replace_secret( + kube_apis.v1, + auth_basic_secret.secret_name, + test_namespace, + f"{TEST_DATA}/auth-basic-secrets/auth-basic-secret-invalid.yaml", + ) wait_before_test(1) - resp = requests.get(req_url, headers={"host": auth_basic_secrets_setup.ingress_host, "authorization": f"Basic {to_base64(auth_basic_secrets_setup.credentials)}"}) + resp = requests.get( + req_url, + headers={ + "host": auth_basic_secrets_setup.ingress_host, + "authorization": f"Basic {to_base64(auth_basic_secrets_setup.credentials)}", + }, + ) assert resp.status_code == 403 - def test_response_code_401_with_updated_secret(self, kube_apis, auth_basic_secrets_setup, test_namespace, auth_basic_secret): + def test_response_code_401_with_updated_secret( + self, kube_apis, auth_basic_secrets_setup, test_namespace, auth_basic_secret + ): req_url = f"http://{auth_basic_secrets_setup.public_endpoint.public_ip}:{auth_basic_secrets_setup.public_endpoint.port}/backend2" - replace_secret(kube_apis.v1, auth_basic_secret.secret_name, test_namespace, f"{TEST_DATA}/auth-basic-secrets/auth-basic-secret-updated.yaml") + replace_secret( + kube_apis.v1, + auth_basic_secret.secret_name, + test_namespace, + f"{TEST_DATA}/auth-basic-secrets/auth-basic-secret-updated.yaml", + ) wait_before_test(1) - resp = requests.get(req_url, headers={"host": auth_basic_secrets_setup.ingress_host, "authorization": f"Basic {to_base64(auth_basic_secrets_setup.credentials)}"}, allow_redirects=False) + resp = requests.get( + req_url, + headers={ + "host": auth_basic_secrets_setup.ingress_host, + "authorization": f"Basic {to_base64(auth_basic_secrets_setup.credentials)}", + }, + allow_redirects=False, + ) assert resp.status_code == 401 diff --git a/tests/suite/test_batch_startup_times.py b/tests/suite/test_batch_startup_times.py index 2bb6fa30cc..0cb107bea1 100644 --- a/tests/suite/test_batch_startup_times.py +++ b/tests/suite/test_batch_startup_times.py @@ -1,51 +1,48 @@ import time -import requests import pytest +import requests import yaml - +from settings import TEST_DATA from suite.ap_resources_utils import ( - create_ap_usersig_from_yaml, - delete_ap_usersig, create_ap_logconf_from_yaml, create_ap_policy_from_yaml, - delete_ap_policy, - delete_ap_logconf, + create_ap_usersig_from_yaml, create_ap_waf_policy_from_yaml, + delete_ap_logconf, + delete_ap_policy, + delete_ap_usersig, ) +from suite.policy_resources_utils import create_policy_from_yaml, delete_policy from suite.resources_utils import ( - ensure_connection_to_public_endpoint, - create_items_from_yaml, create_example_app, + create_ingress, + create_ingress_with_ap_annotations, + create_items_from_yaml, + create_secret_from_yaml, delete_common_app, + delete_ingress, delete_items_from_yaml, - wait_until_all_pods_are_ready, - create_secret_from_yaml, delete_secret, + ensure_connection_to_public_endpoint, ensure_response_from_backend, - create_ingress, - create_ingress_with_ap_annotations, - delete_ingress, - wait_before_test, - scale_deployment, + get_last_reload_status, + get_pods_amount, get_total_ingresses, get_total_vs, - get_last_reload_status, - get_pods_amount, get_total_vsr, + get_total_vsr, + scale_deployment, + wait_before_test, + wait_until_all_pods_are_ready, ) from suite.vs_vsr_resources_utils import ( + create_v_s_route, + create_virtual_server, create_virtual_server_from_yaml, delete_virtual_server, patch_virtual_server_from_yaml, - create_virtual_server, - create_v_s_route, -) -from suite.policy_resources_utils import ( - create_policy_from_yaml, - delete_policy, ) from suite.yaml_utils import get_first_ingress_host_from_yaml -from settings import TEST_DATA class IngressSetup: @@ -83,17 +80,11 @@ def simple_ingress_setup( req_url = f"https://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.port_ssl}/backend1" metrics_url = f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.metrics_port}/metrics" - secret_name = create_secret_from_yaml( - kube_apis.v1, test_namespace, f"{TEST_DATA}/smoke/smoke-secret.yaml" - ) + secret_name = create_secret_from_yaml(kube_apis.v1, test_namespace, f"{TEST_DATA}/smoke/smoke-secret.yaml") create_example_app(kube_apis, "simple", test_namespace) - create_items_from_yaml( - kube_apis, f"{TEST_DATA}/smoke/standard/smoke-ingress.yaml", test_namespace - ) + create_items_from_yaml(kube_apis, f"{TEST_DATA}/smoke/standard/smoke-ingress.yaml", test_namespace) - ingress_host = get_first_ingress_host_from_yaml( - f"{TEST_DATA}/smoke/standard/smoke-ingress.yaml" - ) + ingress_host = get_first_ingress_host_from_yaml(f"{TEST_DATA}/smoke/standard/smoke-ingress.yaml") wait_until_all_pods_are_ready(kube_apis.v1, test_namespace) ensure_connection_to_public_endpoint( ingress_controller_endpoint.public_ip, @@ -105,9 +96,7 @@ def fin(): print("Clean up the Application:") delete_common_app(kube_apis, "simple", test_namespace) delete_secret(kube_apis.v1, secret_name, test_namespace) - delete_items_from_yaml( - kube_apis, f"{TEST_DATA}/smoke/standard/smoke-ingress.yaml", test_namespace - ) + delete_items_from_yaml(kube_apis, f"{TEST_DATA}/smoke/standard/smoke-ingress.yaml", test_namespace) request.addfinalizer(fin) @@ -137,9 +126,7 @@ def test_simple_ingress_batch_start( """ Pod startup time with simple Ingress """ - ensure_response_from_backend( - simple_ingress_setup.req_url, simple_ingress_setup.ingress_host, check404=True - ) + ensure_response_from_backend(simple_ingress_setup.req_url, simple_ingress_setup.ingress_host, check404=True) total_ing = int(request.config.getoption("--batch-resources")) manifest = f"{TEST_DATA}/smoke/standard/smoke-ingress.yaml" @@ -153,7 +140,7 @@ def test_simple_ingress_batch_start( wait_before_test() ic_ns = ingress_controller_prerequisites.namespace scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "nginx-ingress", ic_ns, 0) - while get_pods_amount(kube_apis.v1, ic_ns) is not 0: + while get_pods_amount(kube_apis.v1, ic_ns) != 0: print(f"Number of replicas not 0, retrying...") wait_before_test() num = scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "nginx-ingress", ic_ns, 1) @@ -172,9 +159,7 @@ def test_simple_ingress_batch_start( @pytest.fixture(scope="class") -def ap_ingress_setup( - request, kube_apis, ingress_controller_endpoint, test_namespace -) -> IngressSetup: +def ap_ingress_setup(request, kube_apis, ingress_controller_endpoint, test_namespace) -> IngressSetup: """ Deploy a simple application and AppProtect manifests. @@ -263,9 +248,7 @@ def test_ap_ingress_batch_start( print("------------- Run test for AP policy: dataguard-alarm --------------") print(f"Request URL: {ap_ingress_setup.req_url} and Host: {ap_ingress_setup.ingress_host}") - ensure_response_from_backend( - ap_ingress_setup.req_url, ap_ingress_setup.ingress_host, check404=True - ) + ensure_response_from_backend(ap_ingress_setup.req_url, ap_ingress_setup.ingress_host, check404=True) total_ing = int(request.config.getoption("--batch-resources")) @@ -280,7 +263,7 @@ def test_ap_ingress_batch_start( wait_before_test() ic_ns = ingress_controller_prerequisites.namespace scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "nginx-ingress", ic_ns, 0) - while get_pods_amount(kube_apis.v1, ic_ns) is not 0: + while get_pods_amount(kube_apis.v1, ic_ns) != 0: print(f"Number of replicas not 0, retrying...") wait_before_test() num = scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "nginx-ingress", ic_ns, 1) @@ -326,10 +309,8 @@ def test_vs_batch_start( """ Pod startup time with simple VS """ - resp = requests.get( - virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host} - ) - assert resp.status_code is 200 + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) + assert resp.status_code == 200 total_vs = int(request.config.getoption("--batch-resources")) manifest = f"{TEST_DATA}/virtual-server/standard/virtual-server.yaml" for i in range(1, total_vs + 1): @@ -345,7 +326,7 @@ def test_vs_batch_start( wait_before_test() ic_ns = ingress_controller_prerequisites.namespace scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "nginx-ingress", ic_ns, 0) - while get_pods_amount(kube_apis.v1, ic_ns) is not 0: + while get_pods_amount(kube_apis.v1, ic_ns) != 0: print(f"Number of replicas not 0, retrying...") wait_before_test() num = scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "nginx-ingress", ic_ns, 1) @@ -381,9 +362,7 @@ def appprotect_waf_setup(request, kube_apis, test_namespace) -> None: log_name = create_ap_logconf_from_yaml(kube_apis.custom_objects, src_log_yaml, test_namespace) print("------------------------- Create UserSig CRD resource-----------------------------") - usersig_name = create_ap_usersig_from_yaml( - kube_apis.custom_objects, uds_crd_resource, test_namespace - ) + usersig_name = create_ap_usersig_from_yaml(kube_apis.custom_objects, uds_crd_resource, test_namespace) print(f"------------------------- Deploy dataguard-alarm appolicy ---------------------------") src_pol_yaml = f"{TEST_DATA}/ap-waf/{ap_policy_uds}.yaml" @@ -460,18 +439,14 @@ def test_ap_waf_policy_vs_batch_start( virtual_server_setup.namespace, ) wait_before_test(120) - print( - "----------------------- Send request with embedded malicious script----------------------" - ) + print("----------------------- Send request with embedded malicious script----------------------") response1 = requests.get( virtual_server_setup.backend_1_url + "", headers={"host": virtual_server_setup.vs_host}, ) print(response1.status_code) - print( - "----------------------- Send request with blocked keyword in UDS----------------------" - ) + print("----------------------- Send request with blocked keyword in UDS----------------------") response2 = requests.get( virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, @@ -494,7 +469,7 @@ def test_ap_waf_policy_vs_batch_start( wait_before_test() ic_ns = ingress_controller_prerequisites.namespace scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "nginx-ingress", ic_ns, 0) - while get_pods_amount(kube_apis.v1, ic_ns) is not 0: + while get_pods_amount(kube_apis.v1, ic_ns) != 0: print(f"Number of replicas not 0, retrying...") wait_before_test() num = scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "nginx-ingress", ic_ns, 1) @@ -512,6 +487,7 @@ def test_ap_waf_policy_vs_batch_start( ############################################################################################################## + @pytest.fixture(scope="class") def vs_vsr_setup( request, @@ -561,7 +537,11 @@ def vs_vsr_setup( pytest.param( { "type": "complete", - "extra_args": ["-enable-custom-resources","-enable-prometheus-metrics", "-enable-leader-election=false"] + "extra_args": [ + "-enable-custom-resources", + "-enable-prometheus-metrics", + "-enable-leader-election=false", + ], }, ) ], @@ -575,7 +555,8 @@ def test_startup_time( ingress_controller_prerequisites, crd_ingress_controller, ingress_controller_endpoint, - vs_vsr_setup): + vs_vsr_setup, + ): """ Pod startup time with 1 VS and multiple VSRs. """ @@ -583,12 +564,14 @@ def test_startup_time( ic_ns = ingress_controller_prerequisites.namespace scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "nginx-ingress", ic_ns, 0) - while get_pods_amount(kube_apis.v1, ic_ns) is not 0: + while get_pods_amount(kube_apis.v1, ic_ns) != 0: print(f"Number of replicas not 0, retrying...") wait_before_test() num = scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "nginx-ingress", ic_ns, 1) - metrics_url = f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.metrics_port}/metrics" + metrics_url = ( + f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.metrics_port}/metrics" + ) assert ( get_total_vs(metrics_url, "nginx") == "1" @@ -596,4 +579,4 @@ def test_startup_time( and get_last_reload_status(metrics_url, "nginx") == "1" ) - assert num is None \ No newline at end of file + assert num is None diff --git a/tests/suite/test_build_info.py b/tests/suite/test_build_info.py index 5f8fc44574..a264cb0cfe 100644 --- a/tests/suite/test_build_info.py +++ b/tests/suite/test_build_info.py @@ -1,20 +1,21 @@ -import pytest, logging, io, time +import io +import logging +import time + +import pytest from kubernetes.client.rest import ApiException from suite.resources_utils import get_first_pod_name, wait_until_all_pods_are_ready + @pytest.mark.ingresses @pytest.mark.smoke class TestBuildVersion: - def test_build_version( - self, ingress_controller, kube_apis, ingress_controller_prerequisites - ): + def test_build_version(self, ingress_controller, kube_apis, ingress_controller_prerequisites): """ Test Version tag of build i.e. 'Version=' """ _info = self.send_build_info(kube_apis, ingress_controller_prerequisites) - _version = _info[ - _info.find("Version=") + len("Version=") : _info.rfind("GitCommit=") - ] + _version = _info[_info.find("Version=") + len("Version=") : _info.rfind("GitCommit=")] logging.info(_version) assert _version != " " @@ -24,11 +25,9 @@ def send_build_info(self, kube_apis, ingress_controller_prerequisites) -> str: """ retry = 0 ready = False - pod_name = get_first_pod_name( - kube_apis.v1, ingress_controller_prerequisites.namespace - ) + pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) wait_until_all_pods_are_ready(kube_apis.v1, ingress_controller_prerequisites.namespace) - while(not ready): + while not ready: time.sleep(1) try: api_response = kube_apis.v1.read_namespaced_pod_log( @@ -42,12 +41,11 @@ def send_build_info(self, kube_apis, ingress_controller_prerequisites) -> str: except Exception as ex: if retry < 10: retry += 1 - print(f"Retry# {retry}") + print(f"Retry# {retry}") else: logging.exception(ex) raise ex - br = io.StringIO(api_response) _log = br.readline() try: diff --git a/tests/suite/test_custom_annotations.py b/tests/suite/test_custom_annotations.py index 848d2c174f..8a130f2d55 100644 --- a/tests/suite/test_custom_annotations.py +++ b/tests/suite/test_custom_annotations.py @@ -1,8 +1,14 @@ import pytest -from settings import TEST_DATA, DEPLOYMENTS +from settings import DEPLOYMENTS, TEST_DATA from suite.fixtures import PublicEndpoint -from suite.resources_utils import create_items_from_yaml, delete_items_from_yaml, replace_configmap_from_yaml, \ - get_ingress_nginx_template_conf, get_first_pod_name, wait_before_test +from suite.resources_utils import ( + create_items_from_yaml, + delete_items_from_yaml, + get_first_pod_name, + get_ingress_nginx_template_conf, + replace_configmap_from_yaml, + wait_before_test, +) from suite.yaml_utils import get_first_ingress_host_from_yaml, get_name_from_yaml @@ -15,6 +21,7 @@ class CustomAnnotationsSetup: namespace (str): ingress_host (str): """ + def __init__(self, public_endpoint: PublicEndpoint, ingress_name, namespace, ingress_host, ic_pod_name): self.public_endpoint = public_endpoint self.namespace = namespace @@ -26,14 +33,17 @@ def __init__(self, public_endpoint: PublicEndpoint, ingress_name, namespace, ing @pytest.fixture(scope="class") -def custom_annotations_setup(request, kube_apis, ingress_controller_prerequisites, - ingress_controller_endpoint, test_namespace) -> CustomAnnotationsSetup: +def custom_annotations_setup( + request, kube_apis, ingress_controller_prerequisites, ingress_controller_endpoint, test_namespace +) -> CustomAnnotationsSetup: ing_type = request.param print("------------------------- Deploy ConfigMap with custom template -----------------------------------") - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - f"{TEST_DATA}/custom-annotations/{ing_type}/nginx-config.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + f"{TEST_DATA}/custom-annotations/{ing_type}/nginx-config.yaml", + ) print("------------------------- Deploy Custom Annotations Ingress -----------------------------------") ing_src = f"{TEST_DATA}/custom-annotations/{ing_type}/annotations-ingress.yaml" create_items_from_yaml(kube_apis, ing_src, test_namespace) @@ -45,10 +55,12 @@ def custom_annotations_setup(request, kube_apis, ingress_controller_prerequisite def fin(): print("Clean up Custom Annotations Example:") - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - f"{DEPLOYMENTS}/common/nginx-config.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + f"{DEPLOYMENTS}/common/nginx-config.yaml", + ) delete_items_from_yaml(kube_apis, ing_src, test_namespace) request.addfinalizer(fin) @@ -57,31 +69,46 @@ def fin(): @pytest.mark.ingresses -@pytest.mark.parametrize('custom_annotations_setup, expected_texts', - [ - pytest.param("standard", - ["# This is TEST configuration for custom-annotations-ingress/", - "# Insert config for test-split-feature: 192.168.1.1;", - "# Insert config for test-split-feature: some-ip;", - "# Insert config for feature A if the annotation is set", - "# Print the value assigned to the annotation: 512"], id="standard-ingress"), - pytest.param("mergeable", - ["# This is TEST configuration for custom-annotations-ingress-master/", - "# Insert config for test-split-feature: master.ip;", - "# Insert config for test-split-feature: master;", - "# Insert config for test-split-feature minion: minion1;", - "# Insert config for test-split-feature minion: minion2;", - "# Insert config for feature A if the annotation is set", - "# Print the value assigned to the annotation: 512"], id="mergeable-ingress") - ], - indirect=["custom_annotations_setup"]) +@pytest.mark.parametrize( + "custom_annotations_setup, expected_texts", + [ + pytest.param( + "standard", + [ + "# This is TEST configuration for custom-annotations-ingress/", + "# Insert config for test-split-feature: 192.168.1.1;", + "# Insert config for test-split-feature: some-ip;", + "# Insert config for feature A if the annotation is set", + "# Print the value assigned to the annotation: 512", + ], + id="standard-ingress", + ), + pytest.param( + "mergeable", + [ + "# This is TEST configuration for custom-annotations-ingress-master/", + "# Insert config for test-split-feature: master.ip;", + "# Insert config for test-split-feature: master;", + "# Insert config for test-split-feature minion: minion1;", + "# Insert config for test-split-feature minion: minion2;", + "# Insert config for feature A if the annotation is set", + "# Print the value assigned to the annotation: 512", + ], + id="mergeable-ingress", + ), + ], + indirect=["custom_annotations_setup"], +) class TestCustomAnnotations: - def test_nginx_config(self, kube_apis, ingress_controller_prerequisites, - ingress_controller, custom_annotations_setup, expected_texts): - result_conf = get_ingress_nginx_template_conf(kube_apis.v1, - custom_annotations_setup.namespace, - custom_annotations_setup.ingress_name, - custom_annotations_setup.ic_pod_name, - ingress_controller_prerequisites.namespace) + def test_nginx_config( + self, kube_apis, ingress_controller_prerequisites, ingress_controller, custom_annotations_setup, expected_texts + ): + result_conf = get_ingress_nginx_template_conf( + kube_apis.v1, + custom_annotations_setup.namespace, + custom_annotations_setup.ingress_name, + custom_annotations_setup.ic_pod_name, + ingress_controller_prerequisites.namespace, + ) for line in expected_texts: assert line in result_conf diff --git a/tests/suite/test_default_server.py b/tests/suite/test_default_server.py index 5eec73184e..ca0b379dd7 100644 --- a/tests/suite/test_default_server.py +++ b/tests/suite/test_default_server.py @@ -1,17 +1,22 @@ from ssl import SSLError import pytest - -from suite.resources_utils import create_secret_from_yaml, is_secret_present, delete_secret, wait_before_test, \ - ensure_connection, replace_secret +from settings import DEPLOYMENTS, TEST_DATA +from suite.resources_utils import ( + create_secret_from_yaml, + delete_secret, + ensure_connection, + is_secret_present, + replace_secret, + wait_before_test, +) from suite.ssl_utils import get_server_certificate_subject -from settings import TEST_DATA, DEPLOYMENTS def assert_cn(endpoint, cn): - host = "random" # any host would work + host = "random" # any host would work subject_dict = get_server_certificate_subject(endpoint.public_ip, host, endpoint.port_ssl) - assert subject_dict[b'CN'] == cn.encode('ascii') + assert subject_dict[b"CN"] == cn.encode("ascii") def assert_unrecognized_name_error(endpoint): @@ -24,12 +29,12 @@ def assert_unrecognized_name_error(endpoint): assert "TLSV1_UNRECOGNIZED_NAME" in e.reason -secret_path=f"{DEPLOYMENTS}/common/default-server-secret.yaml" -test_data_path=f"{TEST_DATA}/default-server" -invalid_secret_path=f"{test_data_path}/invalid-tls-secret.yaml" -new_secret_path=f"{test_data_path}/new-tls-secret.yaml" -secret_name="default-server-secret" -secret_namespace="nginx-ingress" +secret_path = f"{DEPLOYMENTS}/common/default-server-secret.yaml" +test_data_path = f"{TEST_DATA}/default-server" +invalid_secret_path = f"{test_data_path}/invalid-tls-secret.yaml" +new_secret_path = f"{test_data_path}/new-tls-secret.yaml" +secret_name = "default-server-secret" +secret_namespace = "nginx-ingress" @pytest.fixture(scope="class") diff --git a/tests/suite/test_dos.py b/tests/suite/test_dos.py index 196bf537d3..9d8610fcff 100644 --- a/tests/suite/test_dos.py +++ b/tests/suite/test_dos.py @@ -4,7 +4,6 @@ import pytest import requests - from settings import TEST_DATA from suite.custom_resources_utils import ( create_dos_logconf_from_yaml, diff --git a/tests/suite/test_externalname_service.py b/tests/suite/test_externalname_service.py index c5662107de..8c1d8f6f44 100644 --- a/tests/suite/test_externalname_service.py +++ b/tests/suite/test_externalname_service.py @@ -1,13 +1,24 @@ -import requests import pytest - +import requests from settings import TEST_DATA from suite.fixtures import PublicEndpoint -from suite.resources_utils import create_ingress_from_yaml, create_service_with_name, \ - create_namespace_with_name_from_yaml, create_deployment_with_name, delete_namespace, ensure_response_from_backend -from suite.resources_utils import replace_configmap_from_yaml, create_service_from_yaml -from suite.resources_utils import replace_configmap, delete_ingress, delete_service, get_ingress_nginx_template_conf -from suite.resources_utils import get_first_pod_name, ensure_connection_to_public_endpoint, wait_before_test +from suite.resources_utils import ( + create_deployment_with_name, + create_ingress_from_yaml, + create_namespace_with_name_from_yaml, + create_service_from_yaml, + create_service_with_name, + delete_ingress, + delete_namespace, + delete_service, + ensure_connection_to_public_endpoint, + ensure_response_from_backend, + get_first_pod_name, + get_ingress_nginx_template_conf, + replace_configmap, + replace_configmap_from_yaml, + wait_before_test, +) from suite.yaml_utils import get_first_ingress_host_from_yaml @@ -23,8 +34,17 @@ class ExternalNameSetup: external_host: external-name example external host namespace: external-name example namespace """ - def __init__(self, public_endpoint: PublicEndpoint, - ingress_name, ingress_host, ingress_pod_name, service, external_host, namespace): + + def __init__( + self, + public_endpoint: PublicEndpoint, + ingress_name, + ingress_host, + ingress_pod_name, + service, + external_host, + namespace, + ): self.public_endpoint = public_endpoint self.ingress_name = ingress_name self.ingress_pod_name = ingress_pod_name @@ -35,43 +55,56 @@ def __init__(self, public_endpoint: PublicEndpoint, @pytest.fixture(scope="class") -def external_name_setup(request, - kube_apis, - ingress_controller_prerequisites, - ingress_controller_endpoint, ingress_controller, test_namespace) -> ExternalNameSetup: +def external_name_setup( + request, + kube_apis, + ingress_controller_prerequisites, + ingress_controller_endpoint, + ingress_controller, + test_namespace, +) -> ExternalNameSetup: print("------------------------- Deploy External-Backend -----------------------------------") external_ns = create_namespace_with_name_from_yaml(kube_apis.v1, "external-ns", f"{TEST_DATA}/common/ns.yaml") external_svc_name = create_service_with_name(kube_apis.v1, external_ns, "external-backend-svc") create_deployment_with_name(kube_apis.apps_v1_api, external_ns, "external-backend") print("------------------------- Deploy External-Name-Example -----------------------------------") - ingress_name = create_ingress_from_yaml(kube_apis.networking_v1, test_namespace, - f"{TEST_DATA}/externalname-services/externalname-ingress.yaml") + ingress_name = create_ingress_from_yaml( + kube_apis.networking_v1, test_namespace, f"{TEST_DATA}/externalname-services/externalname-ingress.yaml" + ) ingress_host = get_first_ingress_host_from_yaml(f"{TEST_DATA}/externalname-services/externalname-ingress.yaml") external_host = f"{external_svc_name}.{external_ns}.svc.cluster.local" config_map_name = ingress_controller_prerequisites.config_map["metadata"]["name"] - replace_configmap_from_yaml(kube_apis.v1, config_map_name, - ingress_controller_prerequisites.namespace, - f"{TEST_DATA}/externalname-services/nginx-config.yaml") - svc_name = create_service_from_yaml(kube_apis.v1, - test_namespace, f"{TEST_DATA}/externalname-services/externalname-svc.yaml") - ensure_connection_to_public_endpoint(ingress_controller_endpoint.public_ip, - ingress_controller_endpoint.port, - ingress_controller_endpoint.port_ssl) + replace_configmap_from_yaml( + kube_apis.v1, + config_map_name, + ingress_controller_prerequisites.namespace, + f"{TEST_DATA}/externalname-services/nginx-config.yaml", + ) + svc_name = create_service_from_yaml( + kube_apis.v1, test_namespace, f"{TEST_DATA}/externalname-services/externalname-svc.yaml" + ) + ensure_connection_to_public_endpoint( + ingress_controller_endpoint.public_ip, ingress_controller_endpoint.port, ingress_controller_endpoint.port_ssl + ) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) def fin(): print("Clean up External-Name-Example:") delete_namespace(kube_apis.v1, external_ns) - replace_configmap(kube_apis.v1, config_map_name, - ingress_controller_prerequisites.namespace, - ingress_controller_prerequisites.config_map) + replace_configmap( + kube_apis.v1, + config_map_name, + ingress_controller_prerequisites.namespace, + ingress_controller_prerequisites.config_map, + ) delete_ingress(kube_apis.networking_v1, ingress_name, test_namespace) delete_service(kube_apis.v1, svc_name, test_namespace) request.addfinalizer(fin) - return ExternalNameSetup(ingress_controller_endpoint, - ingress_name, ingress_host, ic_pod_name, svc_name, external_host, test_namespace) + return ExternalNameSetup( + ingress_controller_endpoint, ingress_name, ingress_host, ic_pod_name, svc_name, external_host, test_namespace + ) @pytest.mark.ingresses @@ -84,33 +117,51 @@ def test_resolver(self, external_name_setup): resp = requests.get(req_url, headers={"host": external_name_setup.ingress_host}, verify=False) assert resp.status_code == 200 - def test_ic_template_config_upstream_zone(self, kube_apis, ingress_controller_prerequisites, - ingress_controller, external_name_setup): - result_conf = get_ingress_nginx_template_conf(kube_apis.v1, - external_name_setup.namespace, - external_name_setup.ingress_name, - external_name_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace) - line = f"zone {external_name_setup.namespace}-" \ - f"{external_name_setup.ingress_name}-" \ - f"{external_name_setup.ingress_host}-{external_name_setup.service}-80 512k;" + def test_ic_template_config_upstream_zone( + self, kube_apis, ingress_controller_prerequisites, ingress_controller, external_name_setup + ): + result_conf = get_ingress_nginx_template_conf( + kube_apis.v1, + external_name_setup.namespace, + external_name_setup.ingress_name, + external_name_setup.ingress_pod_name, + ingress_controller_prerequisites.namespace, + ) + line = ( + f"zone {external_name_setup.namespace}-" + f"{external_name_setup.ingress_name}-" + f"{external_name_setup.ingress_host}-{external_name_setup.service}-80 512k;" + ) assert line in result_conf - def test_ic_template_config_upstream_rule(self, kube_apis, ingress_controller_prerequisites, - ingress_controller, external_name_setup): - result_conf = get_ingress_nginx_template_conf(kube_apis.v1, - external_name_setup.namespace, - external_name_setup.ingress_name, - external_name_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace) + def test_ic_template_config_upstream_rule( + self, kube_apis, ingress_controller_prerequisites, ingress_controller, external_name_setup + ): + result_conf = get_ingress_nginx_template_conf( + kube_apis.v1, + external_name_setup.namespace, + external_name_setup.ingress_name, + external_name_setup.ingress_pod_name, + ingress_controller_prerequisites.namespace, + ) assert "random two least_conn;" in result_conf - def test_ic_template_config_upstream_server(self, kube_apis, ingress_controller_prerequisites, - ingress_controller, ingress_controller_endpoint, external_name_setup): - result_conf = get_ingress_nginx_template_conf(kube_apis.v1, - external_name_setup.namespace, - external_name_setup.ingress_name, - external_name_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace) - assert f"server {external_name_setup.external_host}:80 max_fails=1 fail_timeout=10s max_conns=0 resolve;"\ - in result_conf + def test_ic_template_config_upstream_server( + self, + kube_apis, + ingress_controller_prerequisites, + ingress_controller, + ingress_controller_endpoint, + external_name_setup, + ): + result_conf = get_ingress_nginx_template_conf( + kube_apis.v1, + external_name_setup.namespace, + external_name_setup.ingress_name, + external_name_setup.ingress_pod_name, + ingress_controller_prerequisites.namespace, + ) + assert ( + f"server {external_name_setup.external_host}:80 max_fails=1 fail_timeout=10s max_conns=0 resolve;" + in result_conf + ) diff --git a/tests/suite/test_healthcheck_uri.py b/tests/suite/test_healthcheck_uri.py index daac75190b..dec4ccfade 100644 --- a/tests/suite/test_healthcheck_uri.py +++ b/tests/suite/test_healthcheck_uri.py @@ -1,29 +1,36 @@ import pytest import requests - from suite.resources_utils import ensure_connection @pytest.mark.ingresses -@pytest.mark.parametrize('ingress_controller, expected_responses', - [ - pytest.param({"extra_args": ["-health-status=true", - "-health-status-uri=/something-va(l)id/blabla"]}, - {"/something-va(l)id/blabla": 200, "/nginx-health": 404}, - id="custom-health-status-uri"), - pytest.param({"extra_args": ["-health-status=true"]}, - {"/something-va(l)id/blabla": 404, "/nginx-health": 200}, - id="default-health-status-uri"), - pytest.param({"extra_args": ["-health-status=false"]}, - {"/something-va(l)id/blabla": 404, "/nginx-health": 404}, - id="disable-health-status") - ], - indirect=["ingress_controller"]) +@pytest.mark.parametrize( + "ingress_controller, expected_responses", + [ + pytest.param( + {"extra_args": ["-health-status=true", "-health-status-uri=/something-va(l)id/blabla"]}, + {"/something-va(l)id/blabla": 200, "/nginx-health": 404}, + id="custom-health-status-uri", + ), + pytest.param( + {"extra_args": ["-health-status=true"]}, + {"/something-va(l)id/blabla": 404, "/nginx-health": 200}, + id="default-health-status-uri", + ), + pytest.param( + {"extra_args": ["-health-status=false"]}, + {"/something-va(l)id/blabla": 404, "/nginx-health": 404}, + id="disable-health-status", + ), + ], + indirect=["ingress_controller"], +) class TestHealthStatusURI: def test_response_code(self, ingress_controller_endpoint, ingress_controller, expected_responses): for uri in expected_responses: req_url = f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.port}{uri}" ensure_connection(req_url, expected_responses[uri]) resp = requests.get(req_url) - assert resp.status_code == expected_responses[uri],\ - f"Expected {expected_responses[uri]} code for {uri} but got {resp.status_code}" + assert ( + resp.status_code == expected_responses[uri] + ), f"Expected {expected_responses[uri]} code for {uri} but got {resp.status_code}" diff --git a/tests/suite/test_hsts.py b/tests/suite/test_hsts.py index bb8c71a9c1..2cd3d1b8c6 100644 --- a/tests/suite/test_hsts.py +++ b/tests/suite/test_hsts.py @@ -1,14 +1,20 @@ import pytest import requests - +from settings import TEST_DATA from suite.fixtures import PublicEndpoint -from suite.resources_utils import ensure_connection_to_public_endpoint, \ - create_example_app, wait_until_all_pods_are_ready, \ - delete_common_app, create_items_from_yaml, delete_items_from_yaml, \ - wait_before_test, ensure_response_from_backend, \ - generate_ingresses_with_annotation, replace_ingress +from suite.resources_utils import ( + create_example_app, + create_items_from_yaml, + delete_common_app, + delete_items_from_yaml, + ensure_connection_to_public_endpoint, + ensure_response_from_backend, + generate_ingresses_with_annotation, + replace_ingress, + wait_before_test, + wait_until_all_pods_are_ready, +) from suite.yaml_utils import get_first_ingress_host_from_yaml, get_name_from_yaml -from settings import TEST_DATA class HSTSSetup: @@ -20,6 +26,7 @@ class HSTSSetup: ingress_host: namespace: example namespace """ + def __init__(self, public_endpoint: PublicEndpoint, ingress_src_file, ingress_name, ingress_host, namespace): self.public_endpoint = public_endpoint self.ingress_name = ingress_name @@ -31,50 +38,54 @@ def __init__(self, public_endpoint: PublicEndpoint, ingress_src_file, ingress_na @pytest.fixture(scope="class") -def hsts_setup(request, - kube_apis, - ingress_controller_prerequisites, - ingress_controller_endpoint, ingress_controller, test_namespace) -> HSTSSetup: +def hsts_setup( + request, + kube_apis, + ingress_controller_prerequisites, + ingress_controller_endpoint, + ingress_controller, + test_namespace, +) -> HSTSSetup: print("------------------------- Deploy HSTS-Example -----------------------------------") - create_items_from_yaml(kube_apis, - f"{TEST_DATA}/hsts/{request.param}/hsts-ingress.yaml", - test_namespace) + create_items_from_yaml(kube_apis, f"{TEST_DATA}/hsts/{request.param}/hsts-ingress.yaml", test_namespace) ingress_name = get_name_from_yaml(f"{TEST_DATA}/hsts/{request.param}/hsts-ingress.yaml") ingress_host = get_first_ingress_host_from_yaml(f"{TEST_DATA}/hsts/{request.param}/hsts-ingress.yaml") create_example_app(kube_apis, "simple", test_namespace) wait_until_all_pods_are_ready(kube_apis.v1, test_namespace) - ensure_connection_to_public_endpoint(ingress_controller_endpoint.public_ip, - ingress_controller_endpoint.port, - ingress_controller_endpoint.port_ssl) - req_https_url = f"https://{ingress_controller_endpoint.public_ip}:" \ - f"{ingress_controller_endpoint.port_ssl}/backend1" + ensure_connection_to_public_endpoint( + ingress_controller_endpoint.public_ip, ingress_controller_endpoint.port, ingress_controller_endpoint.port_ssl + ) + req_https_url = ( + f"https://{ingress_controller_endpoint.public_ip}:" f"{ingress_controller_endpoint.port_ssl}/backend1" + ) ensure_response_from_backend(req_https_url, ingress_host) def fin(): print("Clean up HSTS Example:") delete_common_app(kube_apis, "simple", test_namespace) - delete_items_from_yaml(kube_apis, - f"{TEST_DATA}/hsts/{request.param}/hsts-ingress.yaml", - test_namespace) + delete_items_from_yaml(kube_apis, f"{TEST_DATA}/hsts/{request.param}/hsts-ingress.yaml", test_namespace) request.addfinalizer(fin) - return HSTSSetup(ingress_controller_endpoint, - f"{TEST_DATA}/hsts/{request.param}/hsts-ingress.yaml", - ingress_name, ingress_host, test_namespace) + return HSTSSetup( + ingress_controller_endpoint, + f"{TEST_DATA}/hsts/{request.param}/hsts-ingress.yaml", + ingress_name, + ingress_host, + test_namespace, + ) @pytest.mark.ingresses -@pytest.mark.parametrize('hsts_setup', ["standard-tls", "mergeable-tls"], indirect=True) +@pytest.mark.parametrize("hsts_setup", ["standard-tls", "mergeable-tls"], indirect=True) class TestTLSHSTSFlows: def test_headers(self, kube_apis, hsts_setup, ingress_controller_prerequisites): print("\nCase 1: TLS enabled, secret is in place, hsts is True, hsts-behind-proxy is False") annotations = {"nginx.org/hsts-behind-proxy": "False"} new_ing = generate_ingresses_with_annotation(hsts_setup.ingress_src_file, annotations) for ing in new_ing: - if ing['metadata']['name'] == hsts_setup.ingress_name: - replace_ingress(kube_apis.networking_v1, - hsts_setup.ingress_name, hsts_setup.namespace, ing) + if ing["metadata"]["name"] == hsts_setup.ingress_name: + replace_ingress(kube_apis.networking_v1, hsts_setup.ingress_name, hsts_setup.namespace, ing) wait_before_test(1) https_headers = {"host": hsts_setup.ingress_host} @@ -89,9 +100,8 @@ def test_headers(self, kube_apis, hsts_setup, ingress_controller_prerequisites): annotations = {"nginx.org/hsts-behind-proxy": "True"} new_ing = generate_ingresses_with_annotation(hsts_setup.ingress_src_file, annotations) for ing in new_ing: - if ing['metadata']['name'] == hsts_setup.ingress_name: - replace_ingress(kube_apis.networking_v1, - hsts_setup.ingress_name, hsts_setup.namespace, ing) + if ing["metadata"]["name"] == hsts_setup.ingress_name: + replace_ingress(kube_apis.networking_v1, hsts_setup.ingress_name, hsts_setup.namespace, ing) wait_before_test(1) xfp_https_headers = {"host": hsts_setup.ingress_host, "X-Forwarded-Proto": "https"} @@ -104,7 +114,7 @@ def test_headers(self, kube_apis, hsts_setup, ingress_controller_prerequisites): @pytest.mark.ingresses -@pytest.mark.parametrize('hsts_setup', ["tls-no-secret"], indirect=True) +@pytest.mark.parametrize("hsts_setup", ["tls-no-secret"], indirect=True) class TestBrokenTLSHSTSFlows: def test_headers_without_secret(self, kube_apis, hsts_setup, ingress_controller_prerequisites): print("\nCase 2: TLS enabled, secret is NOT in place, hsts is True, hsts-behind-proxy is default (False)") @@ -118,24 +128,23 @@ def test_headers_without_secret(self, kube_apis, hsts_setup, ingress_controller_ @pytest.mark.ingresses -@pytest.mark.parametrize('hsts_setup', ["standard", "mergeable"], indirect=True) +@pytest.mark.parametrize("hsts_setup", ["standard", "mergeable"], indirect=True) class TestNoTLSHSTS: def test_headers(self, kube_apis, hsts_setup, ingress_controller_prerequisites): print("Case 4: no TLS, hsts is True, hsts-behind-proxy is True") annotations = {"nginx.org/hsts-behind-proxy": "True"} new_ing = generate_ingresses_with_annotation(hsts_setup.ingress_src_file, annotations) for ing in new_ing: - if ing['metadata']['name'] == hsts_setup.ingress_name: - replace_ingress(kube_apis.networking_v1, - hsts_setup.ingress_name, hsts_setup.namespace, ing) + if ing["metadata"]["name"] == hsts_setup.ingress_name: + replace_ingress(kube_apis.networking_v1, hsts_setup.ingress_name, hsts_setup.namespace, ing) wait_before_test(1) xfp_https_headers = {"host": hsts_setup.ingress_host, "X-Forwarded-Proto": "https"} xfp_http_headers = {"host": hsts_setup.ingress_host, "X-Forwarded-Proto": "http"} - xfp_https_resp = requests.get(f"{hsts_setup.http_url}/backend1", headers=xfp_https_headers, - allow_redirects=False) - xfp_http_resp = requests.get(f"{hsts_setup.http_url}/backend1", headers=xfp_http_headers, - allow_redirects=False) + xfp_https_resp = requests.get( + f"{hsts_setup.http_url}/backend1", headers=xfp_https_headers, allow_redirects=False + ) + xfp_http_resp = requests.get(f"{hsts_setup.http_url}/backend1", headers=xfp_http_headers, allow_redirects=False) assert "'Strict-Transport-Security': 'max-age=2592000; preload'" in str(xfp_https_resp.headers) assert "'Strict-Transport-Security'" not in str(xfp_http_resp.headers) diff --git a/tests/suite/test_ingress_class.py b/tests/suite/test_ingress_class.py index 560c026244..9eb03db29c 100644 --- a/tests/suite/test_ingress_class.py +++ b/tests/suite/test_ingress_class.py @@ -1,18 +1,17 @@ -import requests import pytest - +import requests +from settings import TEST_DATA from suite.resources_utils import ( - ensure_connection_to_public_endpoint, - create_items_from_yaml, create_example_app, + create_items_from_yaml, delete_common_app, delete_items_from_yaml, - wait_until_all_pods_are_ready, + ensure_connection_to_public_endpoint, ensure_response_from_backend, wait_before_test, + wait_until_all_pods_are_ready, ) from suite.yaml_utils import get_first_ingress_host_from_yaml -from settings import TEST_DATA class BackendSetup: @@ -52,9 +51,7 @@ def backend_setup(request, kube_apis, ingress_controller_endpoint, test_namespac ingress_controller_endpoint.port, ingress_controller_endpoint.port_ssl, ) - print( - "------------------------- Deploy ingresses under test -----------------------------------" - ) + print("------------------------- Deploy ingresses under test -----------------------------------") ingress_hosts = {} for item in ingresses_under_test: src_ing_yaml = f"{TEST_DATA}/ingress-class/{item}-ingress.yaml" @@ -76,7 +73,6 @@ def fin(): @pytest.mark.ingresses class TestIngressClassArgs: - @pytest.mark.parametrize( "ingress_controller, expected_responses", [ @@ -111,12 +107,8 @@ def test_response_codes_117_plus( ) for item in ingresses_under_test: - ensure_response_from_backend( - backend_setup.req_url, backend_setup.ingress_hosts[item] - ) - resp = requests.get( - backend_setup.req_url, headers={"host": backend_setup.ingress_hosts[item]} - ) + ensure_response_from_backend(backend_setup.req_url, backend_setup.ingress_hosts[item]) + resp = requests.get(backend_setup.req_url, headers={"host": backend_setup.ingress_hosts[item]}) assert ( resp.status_code == expected_responses[item] ), f"Expected: {expected_responses[item]} response code for {backend_setup.ingress_hosts[item]}" diff --git a/tests/suite/test_ingress_mtls.py b/tests/suite/test_ingress_mtls.py index 64fa56e1cc..5148bf571b 100644 --- a/tests/suite/test_ingress_mtls.py +++ b/tests/suite/test_ingress_mtls.py @@ -1,23 +1,11 @@ import mock import pytest import requests -from suite.resources_utils import ( - wait_before_test, - create_secret_from_yaml, - delete_secret, -) -from suite.ssl_utils import create_sni_session -from suite.vs_vsr_resources_utils import ( - read_vs, - read_vsr, - patch_virtual_server_from_yaml, - patch_v_s_route_from_yaml, -) -from suite.policy_resources_utils import ( - create_policy_from_yaml, - delete_policy, -) from settings import TEST_DATA +from suite.policy_resources_utils import create_policy_from_yaml, delete_policy +from suite.resources_utils import create_secret_from_yaml, delete_secret, wait_before_test +from suite.ssl_utils import create_sni_session +from suite.vs_vsr_resources_utils import patch_v_s_route_from_yaml, patch_virtual_server_from_yaml, read_vs, read_vsr std_vs_src = f"{TEST_DATA}/virtual-server/standard/virtual-server.yaml" std_vsr_src = f"{TEST_DATA}/virtual-server-route/route-multiple.yaml" @@ -230,11 +218,8 @@ def test_ingress_mtls_policy_cert( std_vs_src, virtual_server_setup.namespace, ) - assert ( - resp.status_code == expected_code - and expected_text in resp.text - and exception in ssl_exception - ) + assert resp.status_code == expected_code and expected_text in resp.text and exception in ssl_exception + @pytest.mark.policies @pytest.mark.parametrize( @@ -271,9 +256,7 @@ def test_ingress_mtls_policy_vsr( tls_sec_valid_src, mtls_pol_valid_src, ) - print( - f"Patch vsr with policy: {mtls_vsr_subroute_src} and vs with tls secret: {tls_secret}" - ) + print(f"Patch vsr with policy: {mtls_vsr_subroute_src} and vs with tls secret: {tls_secret}") patch_virtual_server_from_yaml( kube_apis.custom_objects, v_s_route_setup.vs_name, @@ -292,9 +275,7 @@ def test_ingress_mtls_policy_vsr( v_s_route_setup.route_m.namespace, v_s_route_setup.route_m.name, ) - teardown_policy( - kube_apis, v_s_route_setup.route_m.namespace, tls_secret, pol_name, mtls_secret - ) + teardown_policy(kube_apis, v_s_route_setup.route_m.namespace, tls_secret, pol_name, mtls_secret) patch_v_s_route_from_yaml( kube_apis.custom_objects, v_s_route_setup.route_m.name, diff --git a/tests/suite/test_jwt_auth_mergeable.py b/tests/suite/test_jwt_auth_mergeable.py index 12f8cae038..9da944e62b 100644 --- a/tests/suite/test_jwt_auth_mergeable.py +++ b/tests/suite/test_jwt_auth_mergeable.py @@ -1,13 +1,21 @@ -import requests import pytest - +import requests +from settings import TEST_DATA from suite.fixtures import PublicEndpoint -from suite.resources_utils import create_secret_from_yaml, delete_secret, replace_secret,\ - ensure_connection_to_public_endpoint, wait_before_test -from suite.resources_utils import create_items_from_yaml, delete_items_from_yaml, create_example_app, delete_common_app -from suite.resources_utils import wait_until_all_pods_are_ready, is_secret_present +from suite.resources_utils import ( + create_example_app, + create_items_from_yaml, + create_secret_from_yaml, + delete_common_app, + delete_items_from_yaml, + delete_secret, + ensure_connection_to_public_endpoint, + is_secret_present, + replace_secret, + wait_before_test, + wait_until_all_pods_are_ready, +) from suite.yaml_utils import get_first_ingress_host_from_yaml -from settings import TEST_DATA class JWTAuthMergeableSetup: @@ -21,6 +29,7 @@ class JWTAuthMergeableSetup: minion_secret_name (str): tokens ([]): a list of tokens for testing """ + def __init__(self, public_endpoint: PublicEndpoint, ingress_host, master_secret_name, minion_secret_name, tokens): self.public_endpoint = public_endpoint self.ingress_host = ingress_host @@ -30,20 +39,24 @@ def __init__(self, public_endpoint: PublicEndpoint, ingress_host, master_secret_ @pytest.fixture(scope="class") -def jwt_auth_setup(request, kube_apis, ingress_controller_endpoint, ingress_controller, test_namespace) -> JWTAuthMergeableSetup: +def jwt_auth_setup( + request, kube_apis, ingress_controller_endpoint, ingress_controller, test_namespace +) -> JWTAuthMergeableSetup: tokens = {"master": get_token_from_file("master"), "minion": get_token_from_file("minion")} - master_secret_name = create_secret_from_yaml(kube_apis.v1, test_namespace, - f"{TEST_DATA}/jwt-auth-mergeable/jwt-master-secret.yaml") - minion_secret_name = create_secret_from_yaml(kube_apis.v1, test_namespace, - f"{TEST_DATA}/jwt-auth-mergeable/jwt-minion-secret.yaml") + master_secret_name = create_secret_from_yaml( + kube_apis.v1, test_namespace, f"{TEST_DATA}/jwt-auth-mergeable/jwt-master-secret.yaml" + ) + minion_secret_name = create_secret_from_yaml( + kube_apis.v1, test_namespace, f"{TEST_DATA}/jwt-auth-mergeable/jwt-minion-secret.yaml" + ) print("------------------------- Deploy JWT Auth Mergeable Minions Example -----------------------------------") create_items_from_yaml(kube_apis, f"{TEST_DATA}/jwt-auth-mergeable/mergeable/jwt-auth-ingress.yaml", test_namespace) ingress_host = get_first_ingress_host_from_yaml(f"{TEST_DATA}/jwt-auth-mergeable/mergeable/jwt-auth-ingress.yaml") create_example_app(kube_apis, "simple", test_namespace) wait_until_all_pods_are_ready(kube_apis.v1, test_namespace) - ensure_connection_to_public_endpoint(ingress_controller_endpoint.public_ip, - ingress_controller_endpoint.port, - ingress_controller_endpoint.port_ssl) + ensure_connection_to_public_endpoint( + ingress_controller_endpoint.public_ip, ingress_controller_endpoint.port, ingress_controller_endpoint.port_ssl + ) wait_before_test(2) def fin(): @@ -57,12 +70,15 @@ def fin(): print("Clean up the JWT Auth Mergeable Minions Application:") delete_common_app(kube_apis, "simple", test_namespace) - delete_items_from_yaml(kube_apis, f"{TEST_DATA}/jwt-auth-mergeable/mergeable/jwt-auth-ingress.yaml", - test_namespace) + delete_items_from_yaml( + kube_apis, f"{TEST_DATA}/jwt-auth-mergeable/mergeable/jwt-auth-ingress.yaml", test_namespace + ) request.addfinalizer(fin) - return JWTAuthMergeableSetup(ingress_controller_endpoint, ingress_host, master_secret_name, minion_secret_name, tokens) + return JWTAuthMergeableSetup( + ingress_controller_endpoint, ingress_host, master_secret_name, minion_secret_name, tokens + ) def get_token_from_file(token_type) -> str: @@ -73,43 +89,108 @@ def get_token_from_file(token_type) -> str: :return: str """ with open(f"{TEST_DATA}/jwt-auth-mergeable/tokens/jwt-auth-{token_type}-token.jwt", "r") as token_file: - return token_file.read().replace('\n', '') - - -step_1_expected_results = [{"token_type": "master", "path": "", "response_code": 404}, - {"token_type": "master", "path": "backend1", "response_code": 302, "location": "https://login-backend1.jwt-auth-mergeable.example.com"}, - {"token_type": "master", "path": "backend2", "response_code": 200}, - {"token_type": "minion", "path": "", "response_code": 302, "location": "https://login.jwt-auth-mergeable.example.com"}, - {"token_type": "minion", "path": "backend1", "response_code": 200}, - {"token_type": "minion", "path": "backend2", "response_code": 302, "location": "https://login.jwt-auth-mergeable.example.com"}] - -step_2_expected_results = [{"token_type": "master", "path": "", "response_code": 302, "location": "https://login.jwt-auth-mergeable.example.com"}, - {"token_type": "master", "path": "backend1", "response_code": 302, "location": "https://login-backend1.jwt-auth-mergeable.example.com"}, - {"token_type": "master", "path": "backend2", "response_code": 302, "location": "https://login.jwt-auth-mergeable.example.com"}, - {"token_type": "minion", "path": "", "response_code": 404}, - {"token_type": "minion", "path": "backend1", "response_code": 200}, - {"token_type": "minion", "path": "backend2", "response_code": 200}] - -step_3_expected_results = [{"token_type": "master", "path": "", "response_code": 302, "location": "https://login.jwt-auth-mergeable.example.com"}, - {"token_type": "master", "path": "backend1", "response_code": 200}, - {"token_type": "master", "path": "backend2", "response_code": 302, "location": "https://login.jwt-auth-mergeable.example.com"}, - {"token_type": "minion", "path": "", "response_code": 404}, - {"token_type": "minion", "path": "backend1", "response_code": 302, "location": "https://login-backend1.jwt-auth-mergeable.example.com"}, - {"token_type": "minion", "path": "backend2", "response_code": 200}] - -step_4_expected_results = [{"token_type": "master", "path": "", "response_code": 302, "location": "https://login.jwt-auth-mergeable.example.com"}, - {"token_type": "master", "path": "backend1", "response_code": 500}, - {"token_type": "master", "path": "backend2", "response_code": 302, "location": "https://login.jwt-auth-mergeable.example.com"}, - {"token_type": "minion", "path": "", "response_code": 404}, - {"token_type": "minion", "path": "backend1", "response_code": 500}, - {"token_type": "minion", "path": "backend2", "response_code": 200}] - -step_5_expected_results = [{"token_type": "master", "path": "", "response_code": 500}, - {"token_type": "master", "path": "backend1", "response_code": 500}, - {"token_type": "master", "path": "backend2", "response_code": 500}, - {"token_type": "minion", "path": "", "response_code": 500}, - {"token_type": "minion", "path": "backend1", "response_code": 500}, - {"token_type": "minion", "path": "backend2", "response_code": 500}] + return token_file.read().replace("\n", "") + + +step_1_expected_results = [ + {"token_type": "master", "path": "", "response_code": 404}, + { + "token_type": "master", + "path": "backend1", + "response_code": 302, + "location": "https://login-backend1.jwt-auth-mergeable.example.com", + }, + {"token_type": "master", "path": "backend2", "response_code": 200}, + { + "token_type": "minion", + "path": "", + "response_code": 302, + "location": "https://login.jwt-auth-mergeable.example.com", + }, + {"token_type": "minion", "path": "backend1", "response_code": 200}, + { + "token_type": "minion", + "path": "backend2", + "response_code": 302, + "location": "https://login.jwt-auth-mergeable.example.com", + }, +] + +step_2_expected_results = [ + { + "token_type": "master", + "path": "", + "response_code": 302, + "location": "https://login.jwt-auth-mergeable.example.com", + }, + { + "token_type": "master", + "path": "backend1", + "response_code": 302, + "location": "https://login-backend1.jwt-auth-mergeable.example.com", + }, + { + "token_type": "master", + "path": "backend2", + "response_code": 302, + "location": "https://login.jwt-auth-mergeable.example.com", + }, + {"token_type": "minion", "path": "", "response_code": 404}, + {"token_type": "minion", "path": "backend1", "response_code": 200}, + {"token_type": "minion", "path": "backend2", "response_code": 200}, +] + +step_3_expected_results = [ + { + "token_type": "master", + "path": "", + "response_code": 302, + "location": "https://login.jwt-auth-mergeable.example.com", + }, + {"token_type": "master", "path": "backend1", "response_code": 200}, + { + "token_type": "master", + "path": "backend2", + "response_code": 302, + "location": "https://login.jwt-auth-mergeable.example.com", + }, + {"token_type": "minion", "path": "", "response_code": 404}, + { + "token_type": "minion", + "path": "backend1", + "response_code": 302, + "location": "https://login-backend1.jwt-auth-mergeable.example.com", + }, + {"token_type": "minion", "path": "backend2", "response_code": 200}, +] + +step_4_expected_results = [ + { + "token_type": "master", + "path": "", + "response_code": 302, + "location": "https://login.jwt-auth-mergeable.example.com", + }, + {"token_type": "master", "path": "backend1", "response_code": 500}, + { + "token_type": "master", + "path": "backend2", + "response_code": 302, + "location": "https://login.jwt-auth-mergeable.example.com", + }, + {"token_type": "minion", "path": "", "response_code": 404}, + {"token_type": "minion", "path": "backend1", "response_code": 500}, + {"token_type": "minion", "path": "backend2", "response_code": 200}, +] + +step_5_expected_results = [ + {"token_type": "master", "path": "", "response_code": 500}, + {"token_type": "master", "path": "backend1", "response_code": 500}, + {"token_type": "master", "path": "backend2", "response_code": 500}, + {"token_type": "minion", "path": "", "response_code": 500}, + {"token_type": "minion", "path": "backend1", "response_code": 500}, + {"token_type": "minion", "path": "backend2", "response_code": 500}, +] @pytest.mark.ingresses @@ -120,14 +201,22 @@ def test_jwt_auth_response_codes_and_location(self, kube_apis, jwt_auth_setup, t execute_checks(jwt_auth_setup, step_1_expected_results) print("Step 2: replace master secret") - replace_secret(kube_apis.v1, jwt_auth_setup.master_secret_name, test_namespace, - f"{TEST_DATA}/jwt-auth-mergeable/jwt-master-secret-updated.yaml") + replace_secret( + kube_apis.v1, + jwt_auth_setup.master_secret_name, + test_namespace, + f"{TEST_DATA}/jwt-auth-mergeable/jwt-master-secret-updated.yaml", + ) wait_before_test(1) execute_checks(jwt_auth_setup, step_2_expected_results) print("Step 3: now replace minion secret as well") - replace_secret(kube_apis.v1, jwt_auth_setup.minion_secret_name, test_namespace, - f"{TEST_DATA}/jwt-auth-mergeable/jwt-minion-secret-updated.yaml") + replace_secret( + kube_apis.v1, + jwt_auth_setup.minion_secret_name, + test_namespace, + f"{TEST_DATA}/jwt-auth-mergeable/jwt-minion-secret-updated.yaml", + ) wait_before_test(1) execute_checks(jwt_auth_setup, step_3_expected_results) @@ -152,9 +241,12 @@ def execute_checks(jwt_auth_setup, expected_results) -> None: """ for expected in expected_results: req_url = f"http://{jwt_auth_setup.public_endpoint.public_ip}:{jwt_auth_setup.public_endpoint.port}/{expected['path']}" - resp = requests.get(req_url, headers={"host": jwt_auth_setup.ingress_host}, - cookies={"auth_token": jwt_auth_setup.tokens[expected['token_type']]}, - allow_redirects=False) - assert resp.status_code == expected['response_code'] - if expected.get('location', None): - assert resp.headers['Location'] == expected['location'] + resp = requests.get( + req_url, + headers={"host": jwt_auth_setup.ingress_host}, + cookies={"auth_token": jwt_auth_setup.tokens[expected["token_type"]]}, + allow_redirects=False, + ) + assert resp.status_code == expected["response_code"] + if expected.get("location", None): + assert resp.headers["Location"] == expected["location"] diff --git a/tests/suite/test_jwt_policies.py b/tests/suite/test_jwt_policies.py index 91d43bd00d..571aac86d9 100644 --- a/tests/suite/test_jwt_policies.py +++ b/tests/suite/test_jwt_policies.py @@ -1,26 +1,23 @@ -import pytest, requests, time +import time + +import pytest +import requests from kubernetes.client.rest import ApiException +from settings import DEPLOYMENTS, TEST_DATA +from suite.custom_resources_utils import read_custom_resource +from suite.policy_resources_utils import create_policy_from_yaml, delete_policy, read_policy from suite.resources_utils import ( - wait_before_test, - replace_configmap_from_yaml, create_secret_from_yaml, delete_secret, + replace_configmap_from_yaml, replace_secret, -) -from suite.custom_resources_utils import ( - read_custom_resource, + wait_before_test, ) from suite.vs_vsr_resources_utils import ( - delete_virtual_server, create_virtual_server_from_yaml, delete_and_create_vs_from_yaml, + delete_virtual_server, ) -from suite.policy_resources_utils import ( - create_policy_from_yaml, - delete_policy, - read_policy, -) -from settings import TEST_DATA, DEPLOYMENTS std_vs_src = f"{TEST_DATA}/virtual-server/standard/virtual-server.yaml" jwk_sec_valid_src = f"{TEST_DATA}/jwt-policy/secret/jwk-secret-valid.yaml" @@ -28,23 +25,15 @@ jwt_pol_valid_src = f"{TEST_DATA}/jwt-policy/policies/jwt-policy-valid.yaml" jwt_pol_multi_src = f"{TEST_DATA}/jwt-policy/policies/jwt-policy-valid-multi.yaml" jwt_vs_single_src = f"{TEST_DATA}/jwt-policy/spec/virtual-server-policy-single.yaml" -jwt_vs_single_invalid_pol_src = ( - f"{TEST_DATA}/jwt-policy/spec/virtual-server-policy-single-invalid-pol.yaml" -) +jwt_vs_single_invalid_pol_src = f"{TEST_DATA}/jwt-policy/spec/virtual-server-policy-single-invalid-pol.yaml" jwt_vs_multi_1_src = f"{TEST_DATA}/jwt-policy/spec/virtual-server-policy-multi-1.yaml" jwt_vs_multi_2_src = f"{TEST_DATA}/jwt-policy/spec/virtual-server-policy-multi-2.yaml" jwt_pol_invalid_src = f"{TEST_DATA}/jwt-policy/policies/jwt-policy-invalid.yaml" jwt_pol_invalid_sec_src = f"{TEST_DATA}/jwt-policy/policies/jwt-policy-invalid-secret.yaml" -jwt_vs_single_invalid_sec_src = ( - f"{TEST_DATA}/jwt-policy/spec/virtual-server-policy-single-invalid-secret.yaml" -) +jwt_vs_single_invalid_sec_src = f"{TEST_DATA}/jwt-policy/spec/virtual-server-policy-single-invalid-secret.yaml" jwt_vs_override_route = f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-override-route.yaml" -jwt_vs_override_spec_route_1 = ( - f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-override-spec-route-1.yaml" -) -jwt_vs_override_spec_route_2 = ( - f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-override-spec-route-2.yaml" -) +jwt_vs_override_spec_route_1 = f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-override-spec-route-1.yaml" +jwt_vs_override_spec_route_2 = f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-override-spec-route-2.yaml" valid_token = f"{TEST_DATA}/jwt-policy/token.jwt" invalid_token = f"{TEST_DATA}/jwt-policy/invalid-token.jwt" @@ -62,7 +51,10 @@ f"-enable-leader-election=false", ], }, - {"example": "virtual-server", "app_type": "simple",}, + { + "example": "virtual-server", + "app_type": "simple", + }, ) ], indirect=True, @@ -82,9 +74,7 @@ def setup_single_policy(self, kube_apis, test_namespace, token, secret, policy, return secret_name, pol_name, headers - def setup_multiple_policies( - self, kube_apis, test_namespace, token, secret, policy_1, policy_2, vs_host - ): + def setup_multiple_policies(self, kube_apis, test_namespace, token, secret, policy_1, policy_2, vs_host): print(f"Create jwk secret") secret_name = create_secret_from_yaml(kube_apis.v1, test_namespace, secret) @@ -102,10 +92,15 @@ def setup_multiple_policies( @pytest.mark.parametrize("token", [valid_token, invalid_token]) def test_jwt_policy_token( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, token, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + token, ): """ - Test jwt-policy with no token, valid token and invalid token + Test jwt-policy with no token, valid token and invalid token """ secret, pol_name, headers = self.setup_single_policy( kube_apis, @@ -126,7 +121,8 @@ def test_jwt_policy_token( wait_before_test() resp1 = requests.get( - virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host}, ) print(resp1.status_code) @@ -155,10 +151,15 @@ def test_jwt_policy_token( @pytest.mark.parametrize("jwk_secret", [jwk_sec_valid_src, jwk_sec_invalid_src]) def test_jwt_policy_secret( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, jwk_secret, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + jwk_secret, ): """ - Test jwt-policy with a valid and an invalid secret + Test jwt-policy with a valid and an invalid secret """ if jwk_secret == jwk_sec_valid_src: pol = jwt_pol_valid_src @@ -169,7 +170,12 @@ def test_jwt_policy_secret( else: pytest.fail("Invalid configuration") secret, pol_name, headers = self.setup_single_policy( - kube_apis, test_namespace, valid_token, jwk_secret, pol, virtual_server_setup.vs_host, + kube_apis, + test_namespace, + valid_token, + jwk_secret, + pol, + virtual_server_setup.vs_host, ) print(f"Patch vs with policy: {jwt_vs_single_src}") @@ -214,10 +220,15 @@ def test_jwt_policy_secret( @pytest.mark.smoke @pytest.mark.parametrize("policy", [jwt_pol_valid_src, jwt_pol_invalid_src]) def test_jwt_policy( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, policy, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + policy, ): """ - Test jwt-policy with a valid and an invalid policy + Test jwt-policy with a valid and an invalid policy """ secret, pol_name, headers = self.setup_single_policy( kube_apis, @@ -284,10 +295,14 @@ def test_jwt_policy( pytest.fail(f"Not a valid case or parameter") def test_jwt_policy_delete_secret( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, ): """ - Test if requests result in 500 when secret is deleted + Test if requests result in 500 when secret is deleted """ secret, pol_name, headers = self.setup_single_policy( kube_apis, @@ -327,10 +342,14 @@ def test_jwt_policy_delete_secret( assert resp2.status_code == 500 def test_jwt_policy_delete_policy( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, ): """ - Test if requests result in 500 when policy is deleted + Test if requests result in 500 when policy is deleted """ secret, pol_name, headers = self.setup_single_policy( kube_apis, @@ -371,10 +390,14 @@ def test_jwt_policy_delete_policy( assert resp2.status_code == 500 def test_jwt_policy_override( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, ): """ - Test if first reference to a policy in the same context takes precedence + Test if first reference to a policy in the same context takes precedence """ secret, pol_name_1, pol_name_2, headers = self.setup_multiple_policies( kube_apis, @@ -432,19 +455,19 @@ def test_jwt_policy_override( virtual_server_setup.namespace, ) - assert ( - resp1.status_code == 401 - ) # 401 unauthorized, since no token is attached to policy in spec context + assert resp1.status_code == 401 # 401 unauthorized, since no token is attached to policy in spec context assert resp2.status_code == 200 - assert ( - resp3.status_code == 401 - ) # 401 unauthorized, since no token is attached to policy in route context + assert resp3.status_code == 401 # 401 unauthorized, since no token is attached to policy in route context def test_jwt_policy_override_spec( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, ): """ - Test if policy reference in route takes precedence over policy in spec + Test if policy reference in route takes precedence over policy in spec """ secret, pol_name_1, pol_name_2, headers = self.setup_multiple_policies( kube_apis, diff --git a/tests/suite/test_jwt_policies_vsr.py b/tests/suite/test_jwt_policies_vsr.py index 50d147b690..cf970c4993 100644 --- a/tests/suite/test_jwt_policies_vsr.py +++ b/tests/suite/test_jwt_policies_vsr.py @@ -1,26 +1,23 @@ -import pytest, requests, time +import time + +import pytest +import requests from kubernetes.client.rest import ApiException +from settings import DEPLOYMENTS, TEST_DATA +from suite.custom_resources_utils import read_custom_resource +from suite.policy_resources_utils import create_policy_from_yaml, delete_policy, read_policy from suite.resources_utils import ( - wait_before_test, - replace_configmap_from_yaml, create_secret_from_yaml, delete_secret, + replace_configmap_from_yaml, replace_secret, -) -from suite.custom_resources_utils import ( - read_custom_resource, -) -from suite.policy_resources_utils import ( - create_policy_from_yaml, - delete_policy, - read_policy, + wait_before_test, ) from suite.vs_vsr_resources_utils import ( delete_virtual_server, - patch_virtual_server_from_yaml, patch_v_s_route_from_yaml, + patch_virtual_server_from_yaml, ) -from settings import TEST_DATA, DEPLOYMENTS std_vs_src = f"{TEST_DATA}/virtual-server-route/standard/virtual-server.yaml" std_vsr_src = f"{TEST_DATA}/virtual-server-route/route-multiple.yaml" @@ -30,27 +27,13 @@ jwt_pol_multi_src = f"{TEST_DATA}/jwt-policy/policies/jwt-policy-valid-multi.yaml" jwt_pol_invalid_src = f"{TEST_DATA}/jwt-policy/policies/jwt-policy-invalid.yaml" jwt_pol_invalid_sec_src = f"{TEST_DATA}/jwt-policy/policies/jwt-policy-invalid-secret.yaml" -jwt_vsr_invalid_src = ( - f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-route-invalid-subroute.yaml" -) -jwt_vsr_invalid_sec_src = ( - f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-route-invalid-subroute-secret.yaml" -) -jwt_vsr_override_src = ( - f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-route-override-subroute.yaml" -) -jwt_vsr_valid_src = ( - f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-route-valid-subroute.yaml" -) -jwt_vsr_valid_multi_src = ( - f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-route-valid-subroute-multi.yaml" -) -jwt_vs_override_spec_src = ( - f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-vsr-spec-override.yaml" -) -jwt_vs_override_route_src = ( - f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-vsr-route-override.yaml" -) +jwt_vsr_invalid_src = f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-route-invalid-subroute.yaml" +jwt_vsr_invalid_sec_src = f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-route-invalid-subroute-secret.yaml" +jwt_vsr_override_src = f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-route-override-subroute.yaml" +jwt_vsr_valid_src = f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-route-valid-subroute.yaml" +jwt_vsr_valid_multi_src = f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-route-valid-subroute-multi.yaml" +jwt_vs_override_spec_src = f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-vsr-spec-override.yaml" +jwt_vs_override_route_src = f"{TEST_DATA}/jwt-policy/route-subroute/virtual-server-vsr-route-override.yaml" valid_token = f"{TEST_DATA}/jwt-policy/token.jwt" invalid_token = f"{TEST_DATA}/jwt-policy/invalid-token.jwt" @@ -88,9 +71,7 @@ def setup_single_policy(self, kube_apis, namespace, token, secret, policy, vs_ho return secret_name, pol_name, headers - def setup_multiple_policies( - self, kube_apis, namespace, token, secret, policy_1, policy_2, vs_host - ): + def setup_multiple_policies(self, kube_apis, namespace, token, secret, policy_1, policy_2, vs_host): print(f"Create jwk secret") secret_name = create_secret_from_yaml(kube_apis.v1, namespace, secret) @@ -117,7 +98,7 @@ def test_jwt_policy_token( token, ): """ - Test jwt-policy with no token, valid token and invalid token + Test jwt-policy with no token, valid token and invalid token """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" secret, pol_name, headers = self.setup_single_policy( @@ -178,7 +159,7 @@ def test_jwt_policy_secret( jwk_secret, ): """ - Test jwt-policy with a valid and an invalid secret + Test jwt-policy with a valid and an invalid secret """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" if jwk_secret == jwk_sec_valid_src: @@ -208,7 +189,10 @@ def test_jwt_policy_secret( ) wait_before_test() - resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) + resp = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers=headers, + ) print(resp.status_code) crd_info = read_custom_resource( @@ -250,7 +234,7 @@ def test_jwt_policy( policy, ): """ - Test jwt-policy with a valid and an invalid policy + Test jwt-policy with a valid and an invalid policy """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" if policy == jwt_pol_valid_src: @@ -278,7 +262,10 @@ def test_jwt_policy( ) wait_before_test() - resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) + resp = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers=headers, + ) print(resp.status_code) policy_info = read_custom_resource( kube_apis.custom_objects, v_s_route_setup.route_m.namespace, "policies", pol_name @@ -329,7 +316,7 @@ def test_jwt_policy_delete_secret( test_namespace, ): """ - Test if requests result in 500 when secret is deleted + Test if requests result in 500 when secret is deleted """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" secret, pol_name, headers = self.setup_single_policy( @@ -350,11 +337,17 @@ def test_jwt_policy_delete_secret( ) wait_before_test() - resp1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) + resp1 = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers=headers, + ) print(resp1.status_code) delete_secret(kube_apis.v1, secret, v_s_route_setup.route_m.namespace) - resp2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) + resp2 = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers=headers, + ) print(resp2.status_code) crd_info = read_custom_resource( kube_apis.custom_objects, @@ -389,7 +382,7 @@ def test_jwt_policy_delete_policy( test_namespace, ): """ - Test if requests result in 500 when policy is deleted + Test if requests result in 500 when policy is deleted """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" secret, pol_name, headers = self.setup_single_policy( @@ -410,11 +403,17 @@ def test_jwt_policy_delete_policy( ) wait_before_test() - resp1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) + resp1 = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers=headers, + ) print(resp1.status_code) delete_policy(kube_apis.custom_objects, pol_name, v_s_route_setup.route_m.namespace) - resp2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) + resp2 = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers=headers, + ) print(resp2.status_code) crd_info = read_custom_resource( kube_apis.custom_objects, @@ -433,10 +432,7 @@ def test_jwt_policy_delete_policy( assert resp1.status_code == 200 assert f"Request ID:" in resp1.text assert crd_info["status"]["state"] == "Warning" - assert ( - f"{v_s_route_setup.route_m.namespace}/{pol_name} is missing" - in crd_info["status"]["message"] - ) + assert f"{v_s_route_setup.route_m.namespace}/{pol_name} is missing" in crd_info["status"]["message"] assert resp2.status_code == 500 assert f"Internal Server Error" in resp2.text @@ -449,8 +445,8 @@ def test_jwt_policy_override( test_namespace, ): """ - Test if first reference to a policy in the same context(subroute) takes precedence, - i.e. in this case, policy without $httptoken over policy with $httptoken. + Test if first reference to a policy in the same context(subroute) takes precedence, + i.e. in this case, policy without $httptoken over policy with $httptoken. """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" secret, pol_name_1, pol_name_2, headers = self.setup_multiple_policies( @@ -472,7 +468,10 @@ def test_jwt_policy_override( ) wait_before_test() - resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) + resp = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers=headers, + ) print(resp.status_code) crd_info = read_custom_resource( @@ -493,10 +492,7 @@ def test_jwt_policy_override( ) assert resp.status_code == 401 assert f"Authorization Required" in resp.text - assert ( - f"Multiple jwt policies in the same context is not valid." - in crd_info["status"]["message"] - ) + assert f"Multiple jwt policies in the same context is not valid." in crd_info["status"]["message"] @pytest.mark.parametrize("vs_src", [jwt_vs_override_route_src, jwt_vs_override_spec_src]) def test_jwt_policy_override_vs_vsr( @@ -509,9 +505,9 @@ def test_jwt_policy_override_vs_vsr( vs_src, ): """ - Test if policy specified in vsr:subroute (policy without $httptoken) takes preference over policy specified in: - 1. vs:spec (policy with $httptoken) - 2. vs:route (policy with $httptoken) + Test if policy specified in vsr:subroute (policy without $httptoken) takes preference over policy specified in: + 1. vs:spec (policy with $httptoken) + 2. vs:route (policy with $httptoken) """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" secret, pol_name_1, pol_name_2, headers = self.setup_multiple_policies( @@ -532,11 +528,17 @@ def test_jwt_policy_override_vs_vsr( v_s_route_setup.route_m.namespace, ) patch_virtual_server_from_yaml( - kube_apis.custom_objects, v_s_route_setup.vs_name, vs_src, v_s_route_setup.namespace, + kube_apis.custom_objects, + v_s_route_setup.vs_name, + vs_src, + v_s_route_setup.namespace, ) wait_before_test() - resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers=headers,) + resp = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers=headers, + ) print(resp.status_code) delete_policy(kube_apis.custom_objects, pol_name_1, v_s_route_setup.route_m.namespace) diff --git a/tests/suite/test_jwt_secrets.py b/tests/suite/test_jwt_secrets.py index 7b402c692c..154f063587 100644 --- a/tests/suite/test_jwt_secrets.py +++ b/tests/suite/test_jwt_secrets.py @@ -1,12 +1,21 @@ -import requests import pytest - +import requests +from settings import TEST_DATA from suite.fixtures import PublicEndpoint -from suite.resources_utils import create_secret_from_yaml, delete_secret, replace_secret, ensure_connection_to_public_endpoint, wait_before_test -from suite.resources_utils import create_items_from_yaml, delete_items_from_yaml, create_example_app, delete_common_app -from suite.resources_utils import wait_until_all_pods_are_ready, is_secret_present +from suite.resources_utils import ( + create_example_app, + create_items_from_yaml, + create_secret_from_yaml, + delete_common_app, + delete_items_from_yaml, + delete_secret, + ensure_connection_to_public_endpoint, + is_secret_present, + replace_secret, + wait_before_test, + wait_until_all_pods_are_ready, +) from suite.yaml_utils import get_first_ingress_host_from_yaml -from settings import TEST_DATA class JWTSecretsSetup: @@ -18,6 +27,7 @@ class JWTSecretsSetup: ingress_host (str): jwt_token (str): """ + def __init__(self, public_endpoint: PublicEndpoint, ingress_host, jwt_token): self.public_endpoint = public_endpoint self.ingress_host = ingress_host @@ -31,28 +41,34 @@ class JWTSecret: Attributes: secret_name (str): """ + def __init__(self, secret_name): self.secret_name = secret_name @pytest.fixture(scope="class", params=["standard", "mergeable"]) -def jwt_secrets_setup(request, kube_apis, ingress_controller_endpoint, ingress_controller, test_namespace) -> JWTSecretsSetup: +def jwt_secrets_setup( + request, kube_apis, ingress_controller_endpoint, ingress_controller, test_namespace +) -> JWTSecretsSetup: with open(f"{TEST_DATA}/jwt-secrets/tokens/jwt-secrets-token.jwt", "r") as token_file: - token = token_file.read().replace('\n', '') + token = token_file.read().replace("\n", "") print("------------------------- Deploy JWT Secrets Example -----------------------------------") - create_items_from_yaml(kube_apis, f"{TEST_DATA}/jwt-secrets/{request.param}/jwt-secrets-ingress.yaml", test_namespace) + create_items_from_yaml( + kube_apis, f"{TEST_DATA}/jwt-secrets/{request.param}/jwt-secrets-ingress.yaml", test_namespace + ) ingress_host = get_first_ingress_host_from_yaml(f"{TEST_DATA}/jwt-secrets/{request.param}/jwt-secrets-ingress.yaml") create_example_app(kube_apis, "simple", test_namespace) wait_until_all_pods_are_ready(kube_apis.v1, test_namespace) - ensure_connection_to_public_endpoint(ingress_controller_endpoint.public_ip, - ingress_controller_endpoint.port, - ingress_controller_endpoint.port_ssl) + ensure_connection_to_public_endpoint( + ingress_controller_endpoint.public_ip, ingress_controller_endpoint.port, ingress_controller_endpoint.port_ssl + ) def fin(): print("Clean up the JWT Secrets Application:") delete_common_app(kube_apis, "simple", test_namespace) - delete_items_from_yaml(kube_apis, f"{TEST_DATA}/jwt-secrets/{request.param}/jwt-secrets-ingress.yaml", - test_namespace) + delete_items_from_yaml( + kube_apis, f"{TEST_DATA}/jwt-secrets/{request.param}/jwt-secrets-ingress.yaml", test_namespace + ) request.addfinalizer(fin) @@ -78,33 +94,70 @@ def fin(): @pytest.mark.skip_for_nginx_oss class TestJWTSecrets: def test_response_code_200_and_server_name(self, jwt_secrets_setup, jwt_secret): - req_url = f"http://{jwt_secrets_setup.public_endpoint.public_ip}:{jwt_secrets_setup.public_endpoint.port}/backend2" - resp = requests.get(req_url, headers={"host": jwt_secrets_setup.ingress_host}, cookies={"auth_token": jwt_secrets_setup.jwt_token}) + req_url = ( + f"http://{jwt_secrets_setup.public_endpoint.public_ip}:{jwt_secrets_setup.public_endpoint.port}/backend2" + ) + resp = requests.get( + req_url, + headers={"host": jwt_secrets_setup.ingress_host}, + cookies={"auth_token": jwt_secrets_setup.jwt_token}, + ) assert resp.status_code == 200 assert f"Server name: backend2" in resp.text - def test_response_codes_after_secret_remove_and_restore(self, kube_apis, jwt_secrets_setup, test_namespace, jwt_secret): - req_url = f"http://{jwt_secrets_setup.public_endpoint.public_ip}:{jwt_secrets_setup.public_endpoint.port}/backend2" + def test_response_codes_after_secret_remove_and_restore( + self, kube_apis, jwt_secrets_setup, test_namespace, jwt_secret + ): + req_url = ( + f"http://{jwt_secrets_setup.public_endpoint.public_ip}:{jwt_secrets_setup.public_endpoint.port}/backend2" + ) delete_secret(kube_apis.v1, jwt_secret.secret_name, test_namespace) wait_before_test(1) - resp = requests.get(req_url, headers={"host": jwt_secrets_setup.ingress_host}, cookies={"auth_token": jwt_secrets_setup.jwt_token}) + resp = requests.get( + req_url, + headers={"host": jwt_secrets_setup.ingress_host}, + cookies={"auth_token": jwt_secrets_setup.jwt_token}, + ) assert resp.status_code == 500 - jwt_secret.secret_name = create_secret_from_yaml(kube_apis.v1, test_namespace, f"{TEST_DATA}/jwt-secrets/jwt-secret.yaml") + jwt_secret.secret_name = create_secret_from_yaml( + kube_apis.v1, test_namespace, f"{TEST_DATA}/jwt-secrets/jwt-secret.yaml" + ) wait_before_test(1) - resp = requests.get(req_url, headers={"host": jwt_secrets_setup.ingress_host}, cookies={"auth_token": jwt_secrets_setup.jwt_token}) + resp = requests.get( + req_url, + headers={"host": jwt_secrets_setup.ingress_host}, + cookies={"auth_token": jwt_secrets_setup.jwt_token}, + ) assert resp.status_code == 200 def test_response_code_500_with_invalid_secret(self, kube_apis, jwt_secrets_setup, test_namespace, jwt_secret): - req_url = f"http://{jwt_secrets_setup.public_endpoint.public_ip}:{jwt_secrets_setup.public_endpoint.port}/backend2" - replace_secret(kube_apis.v1, jwt_secret.secret_name, test_namespace, f"{TEST_DATA}/jwt-secrets/jwt-secret-invalid.yaml") + req_url = ( + f"http://{jwt_secrets_setup.public_endpoint.public_ip}:{jwt_secrets_setup.public_endpoint.port}/backend2" + ) + replace_secret( + kube_apis.v1, jwt_secret.secret_name, test_namespace, f"{TEST_DATA}/jwt-secrets/jwt-secret-invalid.yaml" + ) wait_before_test(1) - resp = requests.get(req_url, headers={"host": jwt_secrets_setup.ingress_host}, cookies={"auth_token": jwt_secrets_setup.jwt_token}) + resp = requests.get( + req_url, + headers={"host": jwt_secrets_setup.ingress_host}, + cookies={"auth_token": jwt_secrets_setup.jwt_token}, + ) assert resp.status_code == 500 def test_response_code_302_with_updated_secret(self, kube_apis, jwt_secrets_setup, test_namespace, jwt_secret): - req_url = f"http://{jwt_secrets_setup.public_endpoint.public_ip}:{jwt_secrets_setup.public_endpoint.port}/backend2" - replace_secret(kube_apis.v1, jwt_secret.secret_name, test_namespace, f"{TEST_DATA}/jwt-secrets/jwt-secret-updated.yaml") + req_url = ( + f"http://{jwt_secrets_setup.public_endpoint.public_ip}:{jwt_secrets_setup.public_endpoint.port}/backend2" + ) + replace_secret( + kube_apis.v1, jwt_secret.secret_name, test_namespace, f"{TEST_DATA}/jwt-secrets/jwt-secret-updated.yaml" + ) wait_before_test(1) - resp = requests.get(req_url, headers={"host": jwt_secrets_setup.ingress_host}, cookies={"auth_token": jwt_secrets_setup.jwt_token}, allow_redirects=False) + resp = requests.get( + req_url, + headers={"host": jwt_secrets_setup.ingress_host}, + cookies={"auth_token": jwt_secrets_setup.jwt_token}, + allow_redirects=False, + ) assert resp.status_code == 302 diff --git a/tests/suite/test_policy_ingress_class.py b/tests/suite/test_policy_ingress_class.py index 3d4715c153..45f68f677a 100644 --- a/tests/suite/test_policy_ingress_class.py +++ b/tests/suite/test_policy_ingress_class.py @@ -1,23 +1,16 @@ +import time + import pytest import requests -import time -from suite.resources_utils import ( - wait_before_test, -) -from suite.custom_resources_utils import ( - read_custom_resource, -) +from settings import TEST_DATA +from suite.custom_resources_utils import read_custom_resource +from suite.policy_resources_utils import create_policy_from_yaml, delete_policy, read_policy +from suite.resources_utils import wait_before_test from suite.vs_vsr_resources_utils import ( - delete_virtual_server, create_virtual_server_from_yaml, + delete_virtual_server, patch_virtual_server_from_yaml, ) -from suite.policy_resources_utils import ( - create_policy_from_yaml, - delete_policy, - read_policy, -) -from settings import TEST_DATA vs_src = f"{TEST_DATA}/policy-ingress-class/virtual-server.yaml" vs_policy_src = f"{TEST_DATA}/policy-ingress-class/virtual-server-policy.yaml" @@ -39,7 +32,10 @@ f"-enable-leader-election=false", ], }, - {"example": "rate-limit", "app_type": "simple",}, + { + "example": "rate-limit", + "app_type": "simple", + }, ) ], indirect=True, @@ -49,17 +45,18 @@ def restore_default_vs(self, kube_apis, virtual_server_setup) -> None: """ Restore VirtualServer without policy spec """ - delete_virtual_server( - kube_apis.custom_objects, virtual_server_setup.vs_name, virtual_server_setup.namespace - ) - create_virtual_server_from_yaml( - kube_apis.custom_objects, vs_src, virtual_server_setup.namespace - ) + delete_virtual_server(kube_apis.custom_objects, virtual_server_setup.vs_name, virtual_server_setup.namespace) + create_virtual_server_from_yaml(kube_apis.custom_objects, vs_src, virtual_server_setup.namespace) wait_before_test() @pytest.mark.parametrize("src", [vs_policy_src]) def test_policy_empty_ingress_class( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, src, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + src, ): """ Test if policy with no ingress class is applied to vs @@ -70,9 +67,9 @@ def test_policy_empty_ingress_class( wait_before_test() policy_info = read_custom_resource(kube_apis.custom_objects, test_namespace, "policies", pol_name) assert ( - policy_info["status"] - and policy_info["status"]["reason"] == "AddedOrUpdated" - and policy_info["status"]["state"] == "Valid" + policy_info["status"] + and policy_info["status"]["reason"] == "AddedOrUpdated" + and policy_info["status"]["state"] == "Valid" ) print(f"Patch vs with policy: {src}") @@ -84,11 +81,13 @@ def test_policy_empty_ingress_class( ) wait_before_test() - vs_info = read_custom_resource(kube_apis.custom_objects, virtual_server_setup.namespace, "virtualservers", virtual_server_setup.vs_name) + vs_info = read_custom_resource( + kube_apis.custom_objects, virtual_server_setup.namespace, "virtualservers", virtual_server_setup.vs_name + ) assert ( - vs_info["status"] - and vs_info["status"]["reason"] == "AddedOrUpdated" - and vs_info["status"]["state"] == "Valid" + vs_info["status"] + and vs_info["status"]["reason"] == "AddedOrUpdated" + and vs_info["status"]["state"] == "Valid" ) delete_policy(kube_apis.custom_objects, pol_name, test_namespace) @@ -96,7 +95,12 @@ def test_policy_empty_ingress_class( @pytest.mark.parametrize("src", [vs_policy_src]) def test_policy_matching_ingress_class( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, src, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + src, ): """ Test if policy with matching ingress class is applied to vs @@ -107,9 +111,9 @@ def test_policy_matching_ingress_class( wait_before_test() policy_info = read_custom_resource(kube_apis.custom_objects, test_namespace, "policies", pol_name) assert ( - policy_info["status"] - and policy_info["status"]["reason"] == "AddedOrUpdated" - and policy_info["status"]["state"] == "Valid" + policy_info["status"] + and policy_info["status"]["reason"] == "AddedOrUpdated" + and policy_info["status"]["state"] == "Valid" ) print(f"Patch vs with policy: {src}") @@ -121,11 +125,13 @@ def test_policy_matching_ingress_class( ) wait_before_test() - vs_info = read_custom_resource(kube_apis.custom_objects, virtual_server_setup.namespace, "virtualservers", virtual_server_setup.vs_name) + vs_info = read_custom_resource( + kube_apis.custom_objects, virtual_server_setup.namespace, "virtualservers", virtual_server_setup.vs_name + ) assert ( - vs_info["status"] - and vs_info["status"]["reason"] == "AddedOrUpdated" - and vs_info["status"]["state"] == "Valid" + vs_info["status"] + and vs_info["status"]["reason"] == "AddedOrUpdated" + and vs_info["status"]["state"] == "Valid" ) delete_policy(kube_apis.custom_objects, pol_name, test_namespace) @@ -133,7 +139,12 @@ def test_policy_matching_ingress_class( @pytest.mark.parametrize("src", [vs_policy_src]) def test_policy_non_matching_ingress_class( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, src, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + src, ): """ Test if non matching policy gets caught by vc validation @@ -155,14 +166,15 @@ def test_policy_non_matching_ingress_class( ) wait_before_test() - vs_info = read_custom_resource(kube_apis.custom_objects, virtual_server_setup.namespace, "virtualservers", virtual_server_setup.vs_name) + vs_info = read_custom_resource( + kube_apis.custom_objects, virtual_server_setup.namespace, "virtualservers", virtual_server_setup.vs_name + ) assert ( - vs_info["status"] - and "rate-limit-primary is missing or invalid" in vs_info["status"]["message"] - and vs_info["status"]["reason"] == "AddedOrUpdatedWithWarning" - and vs_info["status"]["state"] == "Warning" + vs_info["status"] + and "rate-limit-primary is missing or invalid" in vs_info["status"]["message"] + and vs_info["status"]["reason"] == "AddedOrUpdatedWithWarning" + and vs_info["status"]["state"] == "Warning" ) delete_policy(kube_apis.custom_objects, pol_name, test_namespace) self.restore_default_vs(kube_apis, virtual_server_setup) - diff --git a/tests/suite/test_prometheus_metrics.py b/tests/suite/test_prometheus_metrics.py index 12be90abe7..f59e28fe66 100644 --- a/tests/suite/test_prometheus_metrics.py +++ b/tests/suite/test_prometheus_metrics.py @@ -1,31 +1,28 @@ import pytest import requests - -from kubernetes.client import V1ContainerPort - +from settings import TEST_DATA from suite.custom_resources_utils import ( - create_ts_from_yaml, - patch_ts_from_yaml, - patch_ts, delete_ts, create_gc_from_yaml, + create_ts_from_yaml, delete_gc, + delete_ts, + patch_ts, + patch_ts_from_yaml, ) from suite.resources_utils import ( - ensure_connection_to_public_endpoint, - create_items_from_yaml, create_example_app, + create_items_from_yaml, + create_secret_from_yaml, delete_common_app, delete_items_from_yaml, - wait_until_all_pods_are_ready, + delete_secret, + ensure_connection, + ensure_connection_to_public_endpoint, ensure_response_from_backend, wait_before_test, wait_until_all_pods_are_ready, - ensure_connection, - delete_secret, - create_secret_from_yaml, ) from suite.yaml_utils import get_first_ingress_host_from_yaml -from settings import TEST_DATA class IngressSetup: @@ -58,15 +55,9 @@ def fin(): @pytest.fixture(scope="class") def ingress_setup(request, kube_apis, ingress_controller_endpoint, test_namespace) -> IngressSetup: print("------------------------- Deploy Ingress Example -----------------------------------") - secret_name = create_secret_from_yaml( - kube_apis.v1, test_namespace, f"{TEST_DATA}/smoke/smoke-secret.yaml" - ) - create_items_from_yaml( - kube_apis, f"{TEST_DATA}/smoke/standard/smoke-ingress.yaml", test_namespace - ) - ingress_host = get_first_ingress_host_from_yaml( - f"{TEST_DATA}/smoke/standard/smoke-ingress.yaml" - ) + secret_name = create_secret_from_yaml(kube_apis.v1, test_namespace, f"{TEST_DATA}/smoke/smoke-secret.yaml") + create_items_from_yaml(kube_apis, f"{TEST_DATA}/smoke/standard/smoke-ingress.yaml", test_namespace) + ingress_host = get_first_ingress_host_from_yaml(f"{TEST_DATA}/smoke/standard/smoke-ingress.yaml") create_example_app(kube_apis, "simple", test_namespace) wait_until_all_pods_are_ready(kube_apis.v1, test_namespace) ensure_connection_to_public_endpoint( @@ -79,9 +70,7 @@ def ingress_setup(request, kube_apis, ingress_controller_endpoint, test_namespac def fin(): print("Clean up simple app") delete_common_app(kube_apis, "simple", test_namespace) - delete_items_from_yaml( - kube_apis, f"{TEST_DATA}/smoke/standard/smoke-ingress.yaml", test_namespace - ) + delete_items_from_yaml(kube_apis, f"{TEST_DATA}/smoke/standard/smoke-ingress.yaml", test_namespace) delete_secret(kube_apis.v1, secret_name, test_namespace) request.addfinalizer(fin) @@ -89,7 +78,6 @@ def fin(): return IngressSetup(req_url, ingress_host) - @pytest.mark.ingresses @pytest.mark.smoke class TestPrometheusExporter: @@ -123,7 +111,7 @@ def test_metrics( ingress_controller, expected_metrics, ingress_setup, - ): + ): ensure_connection(ingress_setup.req_url, 200, {"host": ingress_setup.ingress_host}) resp = requests.get(ingress_setup.req_url, headers={"host": ingress_setup.ingress_host}, verify=False) assert resp.status_code == 200 @@ -172,7 +160,13 @@ def test_latency_metrics( "ingress_controller, expected_metrics", [ pytest.param( - {"extra_args": ["-enable-prometheus-metrics", "-enable-latency-metrics", "-prometheus-tls-secret=nginx-ingress/prometheus-test-secret"]}, + { + "extra_args": [ + "-enable-prometheus-metrics", + "-enable-latency-metrics", + "-prometheus-tls-secret=nginx-ingress/prometheus-test-secret", + ] + }, [ 'nginx_ingress_controller_ingress_resources_total{class="nginx",type="master"} 0', 'nginx_ingress_controller_ingress_resources_total{class="nginx",type="minion"} 0', @@ -182,21 +176,20 @@ def test_latency_metrics( indirect=["ingress_controller"], ) def test_https_metrics( - self, - prometheus_secret_setup, - ingress_controller_endpoint, - ingress_controller, - expected_metrics, - ingress_setup, + self, + prometheus_secret_setup, + ingress_controller_endpoint, + ingress_controller, + expected_metrics, + ingress_setup, ): # assert http fails req_url = f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.metrics_port}/metrics" ensure_connection(req_url, 400) resp = requests.get(req_url, verify=False) assert ( - "Client sent an HTTP request to an HTTPS server" in resp.text and - resp.status_code == 400, f"Expected 400 code for http request to /metrics and got {resp.status_code}" - ) + "Client sent an HTTP request to an HTTPS server" in resp.text and resp.status_code == 400 + ), f"Expected 400 code for http request to /metrics and got {resp.status_code}" # assert https succeeds req_url = f"https://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.metrics_port}/metrics" @@ -228,7 +221,10 @@ def assert_ts_total_metric(ingress_controller_endpoint, ts_type, value): resp_content = resp.content.decode("utf-8") assert resp.status_code == 200, f"Expected 200 code for /metrics but got {resp.status_code}" - assert f'nginx_ingress_controller_transportserver_resources_total{{class="nginx",type="{ts_type}"}} {value}' in resp_content + assert ( + f'nginx_ingress_controller_transportserver_resources_total{{class="nginx",type="{ts_type}"}} {value}' + in resp_content + ) @pytest.mark.ts @@ -238,31 +234,27 @@ def assert_ts_total_metric(ingress_controller_endpoint, ts_type, value): pytest.param( { "type": "complete", - "extra_args": - [ - "-global-configuration=nginx-ingress/nginx-configuration", - "-enable-tls-passthrough", - "-enable-prometheus-metrics" - ] + "extra_args": [ + "-global-configuration=nginx-ingress/nginx-configuration", + "-enable-tls-passthrough", + "-enable-prometheus-metrics", + ], }, ) ], indirect=True, ) class TestTransportServerMetrics: - @pytest.mark.parametrize("ts", [ - (f"{TEST_DATA}/prometheus/transport-server/passthrough.yaml", "passthrough"), - (f"{TEST_DATA}/prometheus/transport-server/tcp.yaml", "tcp"), - (f"{TEST_DATA}/prometheus/transport-server/udp.yaml", "udp") - ]) + @pytest.mark.parametrize( + "ts", + [ + (f"{TEST_DATA}/prometheus/transport-server/passthrough.yaml", "passthrough"), + (f"{TEST_DATA}/prometheus/transport-server/tcp.yaml", "tcp"), + (f"{TEST_DATA}/prometheus/transport-server/udp.yaml", "udp"), + ], + ) def test_total_metrics( - self, - crd_ingress_controller, - ts_setup, - ingress_controller_endpoint, - kube_apis, - test_namespace, - ts + self, crd_ingress_controller, ts_setup, ingress_controller_endpoint, kube_apis, test_namespace, ts ): """ Tests nginx_ingress_controller_transportserver_resources_total metric for a given TransportServer type. @@ -292,9 +284,7 @@ def test_total_metrics( # restore the TS and check the metric is 1 - patch_ts_from_yaml( - kube_apis.custom_objects, ts_resource["metadata"]["name"], ts_file, test_namespace - ) + patch_ts_from_yaml(kube_apis.custom_objects, ts_resource["metadata"]["name"], ts_file, test_namespace) wait_before_test() assert_ts_total_metric(ingress_controller_endpoint, ts_type, 1) @@ -304,4 +294,4 @@ def test_total_metrics( delete_ts(kube_apis.custom_objects, ts_resource, test_namespace) wait_before_test() - assert_ts_total_metric(ingress_controller_endpoint, ts_type, 0) \ No newline at end of file + assert_ts_total_metric(ingress_controller_endpoint, ts_type, 0) diff --git a/tests/suite/test_rewrites.py b/tests/suite/test_rewrites.py index 0d7ea41e60..879fb6cf3e 100644 --- a/tests/suite/test_rewrites.py +++ b/tests/suite/test_rewrites.py @@ -1,11 +1,17 @@ import pytest import requests - from settings import TEST_DATA -from suite.resources_utils import create_items_from_yaml, wait_until_all_pods_are_ready, \ - delete_items_from_yaml, wait_before_test +from suite.resources_utils import ( + create_items_from_yaml, + delete_items_from_yaml, + wait_before_test, + wait_until_all_pods_are_ready, +) from suite.vs_vsr_resources_utils import ( - create_virtual_server_from_yaml, delete_virtual_server, create_v_s_route_from_yaml, delete_v_s_route, + create_v_s_route_from_yaml, + create_virtual_server_from_yaml, + delete_v_s_route, + delete_virtual_server, ) hello_app_yaml = f"{TEST_DATA}/rewrites/hello.yaml" @@ -31,8 +37,9 @@ def __init__(self, public_endpoint): @pytest.fixture(scope="class") -def vs_rewrites_setup(request, kube_apis, test_namespace, hello_app, ingress_controller_endpoint, - crd_ingress_controller): +def vs_rewrites_setup( + request, kube_apis, test_namespace, hello_app, ingress_controller_endpoint, crd_ingress_controller +): vs = create_virtual_server_from_yaml(kube_apis.custom_objects, vs_yaml, test_namespace) wait_before_test() @@ -51,8 +58,9 @@ def fin(): @pytest.fixture(scope="class") -def vsr_rewrites_setup(request, kube_apis, test_namespace, hello_app, ingress_controller_endpoint, - crd_ingress_controller): +def vsr_rewrites_setup( + request, kube_apis, test_namespace, hello_app, ingress_controller_endpoint, crd_ingress_controller +): vs_parent = create_virtual_server_from_yaml(kube_apis.custom_objects, vs_parent_yaml, test_namespace) vsr_prefixes = create_v_s_route_from_yaml(kube_apis.custom_objects, vsr_prefixes_yaml, test_namespace) vsr_regex1 = create_v_s_route_from_yaml(kube_apis.custom_objects, vsr_regex1_yaml, test_namespace) @@ -70,21 +78,23 @@ def fin(): return RewritesSetup(ingress_controller_endpoint) -test_data = [("/backend1/", {"arg": "value"}, {}, "/?arg=value"), - ("/backend1/abc", {"arg": "value"}, {}, "/abc?arg=value"), - ("/backend2", {"arg": "value"}, {}, "/backend2_1?arg=value"), - ("/backend2/", {"arg": "value"}, {}, "/backend2_1/?arg=value"), - ("/backend2/abc", {"arg": "value"}, {}, "/backend2_1/abc?arg=value"), - ("/match/", {"arg": "value"}, {}, "/?arg=value"), - ("/match/abc", {"arg": "value"}, {}, "/abc?arg=value"), - ("/match/", {"arg": "value"}, {"user": "john"}, "/user/john/?arg=value"), - ("/match/abc", {"arg": "value"}, {"user": "john"}, "/user/john/abc?arg=value"), - ("/regex1/", {"arg": "value"}, {}, "/?arg=value"), - ("/regex1//", {"arg": "value"}, {}, "/?arg=value"), - ("/regex2/abc", {"arg": "value"}, {}, "/abc?arg=value")] +test_data = [ + ("/backend1/", {"arg": "value"}, {}, "/?arg=value"), + ("/backend1/abc", {"arg": "value"}, {}, "/abc?arg=value"), + ("/backend2", {"arg": "value"}, {}, "/backend2_1?arg=value"), + ("/backend2/", {"arg": "value"}, {}, "/backend2_1/?arg=value"), + ("/backend2/abc", {"arg": "value"}, {}, "/backend2_1/abc?arg=value"), + ("/match/", {"arg": "value"}, {}, "/?arg=value"), + ("/match/abc", {"arg": "value"}, {}, "/abc?arg=value"), + ("/match/", {"arg": "value"}, {"user": "john"}, "/user/john/?arg=value"), + ("/match/abc", {"arg": "value"}, {"user": "john"}, "/user/john/abc?arg=value"), + ("/regex1/", {"arg": "value"}, {}, "/?arg=value"), + ("/regex1//", {"arg": "value"}, {}, "/?arg=value"), + ("/regex2/abc", {"arg": "value"}, {}, "/abc?arg=value"), +] -@pytest.mark.parametrize('crd_ingress_controller', [({'type': 'complete'})], indirect=True) +@pytest.mark.parametrize("crd_ingress_controller", [({"type": "complete"})], indirect=True) class TestRewrites: @pytest.mark.vs @pytest.mark.parametrize("path,args,cookies,expected", test_data) diff --git a/tests/suite/test_rl_policies.py b/tests/suite/test_rl_policies.py index 950305d3a1..a2490cc16e 100644 --- a/tests/suite/test_rl_policies.py +++ b/tests/suite/test_rl_policies.py @@ -1,20 +1,17 @@ -import pytest, requests, time +import time + +import pytest +import requests from kubernetes.client.rest import ApiException -from suite.resources_utils import wait_before_test, replace_configmap_from_yaml -from suite.custom_resources_utils import ( - read_custom_resource, -) +from settings import DEPLOYMENTS, TEST_DATA +from suite.custom_resources_utils import read_custom_resource +from suite.policy_resources_utils import create_policy_from_yaml, delete_policy, read_policy +from suite.resources_utils import replace_configmap_from_yaml, wait_before_test from suite.vs_vsr_resources_utils import ( - delete_virtual_server, create_virtual_server_from_yaml, + delete_virtual_server, patch_virtual_server_from_yaml, ) -from suite.policy_resources_utils import ( - create_policy_from_yaml, - delete_policy, - read_policy, -) -from settings import TEST_DATA, DEPLOYMENTS std_vs_src = f"{TEST_DATA}/rate-limit/standard/virtual-server.yaml" rl_pol_pri_src = f"{TEST_DATA}/rate-limit/policies/rate-limit-primary.yaml" @@ -25,9 +22,7 @@ rl_vs_invalid = f"{TEST_DATA}/rate-limit/spec/virtual-server-invalid.yaml" rl_vs_override_spec = f"{TEST_DATA}/rate-limit/spec/virtual-server-override.yaml" rl_vs_override_route = f"{TEST_DATA}/rate-limit/route-subroute/virtual-server-override-route.yaml" -rl_vs_override_spec_route = ( - f"{TEST_DATA}/rate-limit/route-subroute/virtual-server-override-spec-route.yaml" -) +rl_vs_override_spec_route = f"{TEST_DATA}/rate-limit/route-subroute/virtual-server-override-spec-route.yaml" @pytest.mark.policies @@ -42,7 +37,10 @@ f"-enable-leader-election=false", ], }, - {"example": "rate-limit", "app_type": "simple",}, + { + "example": "rate-limit", + "app_type": "simple", + }, ) ], indirect=True, @@ -52,18 +50,19 @@ def restore_default_vs(self, kube_apis, virtual_server_setup) -> None: """ Restore VirtualServer without policy spec """ - delete_virtual_server( - kube_apis.custom_objects, virtual_server_setup.vs_name, virtual_server_setup.namespace - ) - create_virtual_server_from_yaml( - kube_apis.custom_objects, std_vs_src, virtual_server_setup.namespace - ) + delete_virtual_server(kube_apis.custom_objects, virtual_server_setup.vs_name, virtual_server_setup.namespace) + create_virtual_server_from_yaml(kube_apis.custom_objects, std_vs_src, virtual_server_setup.namespace) wait_before_test() @pytest.mark.smoke @pytest.mark.parametrize("src", [rl_vs_pri_src]) def test_rl_policy_1rs( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, src, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + src, ): """ Test if rate-limiting policy is working with 1 rps @@ -83,13 +82,15 @@ def test_rl_policy_1rs( occur = [] t_end = time.perf_counter() + 1 resp = requests.get( - virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host}, ) print(resp.status_code) assert resp.status_code == 200 while time.perf_counter() < t_end: resp = requests.get( - virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host}, ) occur.append(resp.status_code) delete_policy(kube_apis.custom_objects, pol_name, test_namespace) @@ -103,7 +104,12 @@ def test_rl_policy_1rs( @pytest.mark.parametrize("src", [rl_vs_sec_src]) def test_rl_policy_5rs( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, src, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + src, ): """ Test if rate-limiting policy is working with 5 rps @@ -124,12 +130,14 @@ def test_rl_policy_5rs( occur = [] t_end = time.perf_counter() + 1 resp = requests.get( - virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host}, ) assert resp.status_code == 200 while time.perf_counter() < t_end: resp = requests.get( - virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host}, ) occur.append(resp.status_code) delete_policy(kube_apis.custom_objects, pol_name, test_namespace) @@ -143,15 +151,18 @@ def test_rl_policy_5rs( @pytest.mark.parametrize("src", [rl_vs_invalid]) def test_rl_policy_invalid( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, src, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + src, ): """ Test the status code is 500 if invalid policy is deployed """ print(f"Create rl policy") - invalid_pol_name = create_policy_from_yaml( - kube_apis.custom_objects, rl_pol_invalid, test_namespace - ) + invalid_pol_name = create_policy_from_yaml(kube_apis.custom_objects, rl_pol_invalid, test_namespace) print(f"Patch vs with policy: {src}") patch_virtual_server_from_yaml( kube_apis.custom_objects, @@ -161,11 +172,10 @@ def test_rl_policy_invalid( ) wait_before_test() - policy_info = read_custom_resource( - kube_apis.custom_objects, test_namespace, "policies", invalid_pol_name - ) + policy_info = read_custom_resource(kube_apis.custom_objects, test_namespace, "policies", invalid_pol_name) resp = requests.get( - virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host}, ) print(resp.text) delete_policy(kube_apis.custom_objects, invalid_pol_name, test_namespace) @@ -179,7 +189,12 @@ def test_rl_policy_invalid( @pytest.mark.parametrize("src", [rl_vs_pri_src]) def test_rl_policy_deleted( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, src, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + src, ): """ Test the status code if 500 is valid policy is removed @@ -195,31 +210,34 @@ def test_rl_policy_deleted( ) wait_before_test() resp = requests.get( - virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host}, ) assert resp.status_code == 200 delete_policy(kube_apis.custom_objects, pol_name, test_namespace) wait_before_test() resp = requests.get( - virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host}, ) self.restore_default_vs(kube_apis, virtual_server_setup) assert resp.status_code == 500 @pytest.mark.parametrize("src", [rl_vs_override_spec, rl_vs_override_route]) def test_rl_override( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, src, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + src, ): """ List multiple policies in vs and test if the one with less rps is used """ print(f"Create rl policy") - pol_name_pri = create_policy_from_yaml( - kube_apis.custom_objects, rl_pol_pri_src, test_namespace - ) - pol_name_sec = create_policy_from_yaml( - kube_apis.custom_objects, rl_pol_sec_src, test_namespace - ) + pol_name_pri = create_policy_from_yaml(kube_apis.custom_objects, rl_pol_pri_src, test_namespace) + pol_name_sec = create_policy_from_yaml(kube_apis.custom_objects, rl_pol_sec_src, test_namespace) print(f"Patch vs with policy: {src}") patch_virtual_server_from_yaml( kube_apis.custom_objects, @@ -231,12 +249,14 @@ def test_rl_override( occur = [] t_end = time.perf_counter() + 1 resp = requests.get( - virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host}, ) assert resp.status_code == 200 while time.perf_counter() < t_end: resp = requests.get( - virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host}, ) occur.append(resp.status_code) delete_policy(kube_apis.custom_objects, pol_name_pri, test_namespace) @@ -246,7 +266,12 @@ def test_rl_override( @pytest.mark.parametrize("src", [rl_vs_override_spec_route]) def test_rl_override_spec_route( - self, kube_apis, crd_ingress_controller, virtual_server_setup, test_namespace, src, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, + test_namespace, + src, ): """ List policies in vs spec and route resp. and test if route overrides spec @@ -255,12 +280,8 @@ def test_rl_override_spec_route( """ rate_sec = 5 print(f"Create rl policy") - pol_name_pri = create_policy_from_yaml( - kube_apis.custom_objects, rl_pol_pri_src, test_namespace - ) - pol_name_sec = create_policy_from_yaml( - kube_apis.custom_objects, rl_pol_sec_src, test_namespace - ) + pol_name_pri = create_policy_from_yaml(kube_apis.custom_objects, rl_pol_pri_src, test_namespace) + pol_name_sec = create_policy_from_yaml(kube_apis.custom_objects, rl_pol_sec_src, test_namespace) print(f"Patch vs with policy: {src}") patch_virtual_server_from_yaml( kube_apis.custom_objects, @@ -272,12 +293,14 @@ def test_rl_override_spec_route( occur = [] t_end = time.perf_counter() + 1 resp = requests.get( - virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host}, ) assert resp.status_code == 200 while time.perf_counter() < t_end: resp = requests.get( - virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host}, ) occur.append(resp.status_code) delete_policy(kube_apis.custom_objects, pol_name_pri, test_namespace) diff --git a/tests/suite/test_rl_policies_vsr.py b/tests/suite/test_rl_policies_vsr.py index aa130db89d..35fa724e28 100644 --- a/tests/suite/test_rl_policies_vsr.py +++ b/tests/suite/test_rl_policies_vsr.py @@ -1,21 +1,18 @@ -import pytest, requests, time +import time + +import pytest +import requests from kubernetes.client.rest import ApiException -from suite.resources_utils import wait_before_test, replace_configmap_from_yaml -from suite.custom_resources_utils import ( - read_custom_resource, -) +from settings import DEPLOYMENTS, TEST_DATA +from suite.custom_resources_utils import read_custom_resource +from suite.policy_resources_utils import create_policy_from_yaml, delete_policy, read_policy +from suite.resources_utils import replace_configmap_from_yaml, wait_before_test from suite.vs_vsr_resources_utils import ( - delete_virtual_server, create_virtual_server_from_yaml, - patch_virtual_server_from_yaml, + delete_virtual_server, patch_v_s_route_from_yaml, + patch_virtual_server_from_yaml, ) -from suite.policy_resources_utils import ( - create_policy_from_yaml, - delete_policy, - read_policy, -) -from settings import TEST_DATA, DEPLOYMENTS std_vs_src = f"{TEST_DATA}/virtual-server-route/standard/virtual-server.yaml" rl_pol_pri_src = f"{TEST_DATA}/rate-limit/policies/rate-limit-primary.yaml" @@ -23,18 +20,10 @@ rl_pol_sec_src = f"{TEST_DATA}/rate-limit/policies/rate-limit-secondary.yaml" rl_vsr_sec_src = f"{TEST_DATA}/rate-limit/route-subroute/virtual-server-route-sec-subroute.yaml" rl_pol_invalid_src = f"{TEST_DATA}/rate-limit/policies/rate-limit-invalid.yaml" -rl_vsr_invalid_src = ( - f"{TEST_DATA}/rate-limit/route-subroute/virtual-server-route-invalid-subroute.yaml" -) -rl_vsr_override_src = ( - f"{TEST_DATA}/rate-limit/route-subroute/virtual-server-route-override-subroute.yaml" -) -rl_vsr_override_vs_spec_src = ( - f"{TEST_DATA}/rate-limit/route-subroute/virtual-server-vsr-spec-override.yaml" -) -rl_vsr_override_vs_route_src = ( - f"{TEST_DATA}/rate-limit/route-subroute/virtual-server-vsr-route-override.yaml" -) +rl_vsr_invalid_src = f"{TEST_DATA}/rate-limit/route-subroute/virtual-server-route-invalid-subroute.yaml" +rl_vsr_override_src = f"{TEST_DATA}/rate-limit/route-subroute/virtual-server-route-override-subroute.yaml" +rl_vsr_override_vs_spec_src = f"{TEST_DATA}/rate-limit/route-subroute/virtual-server-vsr-spec-override.yaml" +rl_vsr_override_vs_route_src = f"{TEST_DATA}/rate-limit/route-subroute/virtual-server-vsr-route-override.yaml" @pytest.mark.policies @@ -85,9 +74,7 @@ def test_rl_policy_1rs_vsr( req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" print(f"Create rl policy") - pol_name = create_policy_from_yaml( - kube_apis.custom_objects, rl_pol_pri_src, v_s_route_setup.route_m.namespace - ) + pol_name = create_policy_from_yaml(kube_apis.custom_objects, rl_pol_pri_src, v_s_route_setup.route_m.namespace) print(f"Patch vsr with policy: {src}") patch_v_s_route_from_yaml( kube_apis.custom_objects, @@ -139,9 +126,7 @@ def test_rl_policy_5rs_vsr( rate_sec = 5 req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" print(f"Create rl policy") - pol_name = create_policy_from_yaml( - kube_apis.custom_objects, rl_pol_sec_src, v_s_route_setup.route_m.namespace - ) + pol_name = create_policy_from_yaml(kube_apis.custom_objects, rl_pol_sec_src, v_s_route_setup.route_m.namespace) print(f"Patch vsr with policy: {src}") patch_v_s_route_from_yaml( kube_apis.custom_objects, @@ -243,9 +228,7 @@ def test_rl_policy_deleted_vsr( """ req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" print(f"Create rl policy") - pol_name = create_policy_from_yaml( - kube_apis.custom_objects, rl_pol_pri_src, v_s_route_setup.route_m.namespace - ) + pol_name = create_policy_from_yaml(kube_apis.custom_objects, rl_pol_pri_src, v_s_route_setup.route_m.namespace) print(f"Patch vsr with policy: {src}") patch_v_s_route_from_yaml( kube_apis.custom_objects, @@ -326,7 +309,7 @@ def test_override_vs_vsr( src, ): """ - Test if vsr subroute policy overrides vs spec policy + Test if vsr subroute policy overrides vs spec policy And vsr subroute policy overrides vs route policy """ rate_sec = 5 diff --git a/tests/suite/test_smoke.py b/tests/suite/test_smoke.py index c63ee3da6b..349fa87c6f 100644 --- a/tests/suite/test_smoke.py +++ b/tests/suite/test_smoke.py @@ -1,28 +1,28 @@ -import requests -import pytest import json +import pytest +import requests +from settings import TEST_DATA from suite.fixtures import PublicEndpoint from suite.resources_utils import ( + create_example_app, + create_items_from_yaml, create_secret_from_yaml, + delete_common_app, + delete_items_from_yaml, delete_secret, ensure_connection_to_public_endpoint, - create_items_from_yaml, - delete_items_from_yaml, - create_example_app, - delete_common_app, - wait_until_all_pods_are_ready, ensure_response_from_backend, - get_test_file_name, get_last_reload_time, - write_to_json, - scale_deployment, get_pods_amount, + get_reload_count, + get_test_file_name, + scale_deployment, wait_before_test, - get_reload_count + wait_until_all_pods_are_ready, + write_to_json, ) from suite.yaml_utils import get_first_ingress_host_from_yaml -from settings import TEST_DATA paths = ["backend1", "backend2"] reload_times = {} @@ -43,19 +43,11 @@ def __init__(self, public_endpoint: PublicEndpoint, ingress_host): @pytest.fixture(scope="class", params=["standard", "mergeable"]) -def smoke_setup( - request, kube_apis, ingress_controller_endpoint, ingress_controller, test_namespace -) -> SmokeSetup: +def smoke_setup(request, kube_apis, ingress_controller_endpoint, ingress_controller, test_namespace) -> SmokeSetup: print("------------------------- Deploy Smoke Example -----------------------------------") - secret_name = create_secret_from_yaml( - kube_apis.v1, test_namespace, f"{TEST_DATA}/smoke/smoke-secret.yaml" - ) - create_items_from_yaml( - kube_apis, f"{TEST_DATA}/smoke/{request.param}/smoke-ingress.yaml", test_namespace - ) - ingress_host = get_first_ingress_host_from_yaml( - f"{TEST_DATA}/smoke/{request.param}/smoke-ingress.yaml" - ) + secret_name = create_secret_from_yaml(kube_apis.v1, test_namespace, f"{TEST_DATA}/smoke/smoke-secret.yaml") + create_items_from_yaml(kube_apis, f"{TEST_DATA}/smoke/{request.param}/smoke-ingress.yaml", test_namespace) + ingress_host = get_first_ingress_host_from_yaml(f"{TEST_DATA}/smoke/{request.param}/smoke-ingress.yaml") create_example_app(kube_apis, "simple", test_namespace) wait_until_all_pods_are_ready(kube_apis.v1, test_namespace) ensure_connection_to_public_endpoint( @@ -67,14 +59,9 @@ def smoke_setup( def fin(): print("Clean up the Smoke Application:") delete_common_app(kube_apis, "simple", test_namespace) - delete_items_from_yaml( - kube_apis, f"{TEST_DATA}/smoke/{request.param}/smoke-ingress.yaml", test_namespace - ) + delete_items_from_yaml(kube_apis, f"{TEST_DATA}/smoke/{request.param}/smoke-ingress.yaml", test_namespace) delete_secret(kube_apis.v1, secret_name, test_namespace) - write_to_json( - f"reload-{get_test_file_name(request.node.fspath)}.json", - reload_times - ) + write_to_json(f"reload-{get_test_file_name(request.node.fspath)}.json", reload_times) request.addfinalizer(fin) @@ -96,11 +83,11 @@ class TestSmoke: indirect=True, ) @pytest.mark.parametrize("path", paths) - def test_response_code_200_and_server_name( - self, request, ingress_controller, smoke_setup, path - ): + def test_response_code_200_and_server_name(self, request, ingress_controller, smoke_setup, path): req_url = f"https://{smoke_setup.public_endpoint.public_ip}:{smoke_setup.public_endpoint.port_ssl}/{path}" - metrics_url = f"http://{smoke_setup.public_endpoint.public_ip}:{smoke_setup.public_endpoint.metrics_port}/metrics" + metrics_url = ( + f"http://{smoke_setup.public_endpoint.public_ip}:{smoke_setup.public_endpoint.metrics_port}/metrics" + ) ensure_response_from_backend(req_url, smoke_setup.ingress_host) resp = requests.get(req_url, headers={"host": smoke_setup.ingress_host}, verify=False) reload_ms = get_last_reload_time(metrics_url, "nginx") @@ -116,19 +103,19 @@ def test_response_code_200_and_server_name( ], indirect=True, ) - def test_reload_count_after_start( - self, kube_apis, smoke_setup, ingress_controller_prerequisites - ): + def test_reload_count_after_start(self, kube_apis, smoke_setup, ingress_controller_prerequisites): ns = ingress_controller_prerequisites.namespace scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "nginx-ingress", ns, 0) - while get_pods_amount(kube_apis.v1, ns) is not 0: + while get_pods_amount(kube_apis.v1, ns) != 0: print(f"Number of replicas not 0, retrying...") wait_before_test() num = scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "nginx-ingress", ns, 1) assert num is None - metrics_url = f"http://{smoke_setup.public_endpoint.public_ip}:{smoke_setup.public_endpoint.metrics_port}/metrics" + metrics_url = ( + f"http://{smoke_setup.public_endpoint.public_ip}:{smoke_setup.public_endpoint.metrics_port}/metrics" + ) count = get_reload_count(metrics_url) assert count == 1 diff --git a/tests/suite/test_snippet_flag.py b/tests/suite/test_snippet_flag.py index 012a632e2d..3f54a20298 100644 --- a/tests/suite/test_snippet_flag.py +++ b/tests/suite/test_snippet_flag.py @@ -1,14 +1,16 @@ -import pytest import time -from suite.resources_utils import get_file_contents -from suite.resources_utils import get_first_pod_name -from suite.resources_utils import create_ingress_from_yaml -from suite.resources_utils import delete_ingress -from suite.resources_utils import get_events +import pytest +from settings import TEST_DATA from suite.custom_assertions import assert_event +from suite.resources_utils import ( + create_ingress_from_yaml, + delete_ingress, + get_events, + get_file_contents, + get_first_pod_name, +) -from settings import TEST_DATA @pytest.mark.ingresses class TestSnippetAnnotation: @@ -17,12 +19,17 @@ class TestSnippetAnnotation: Checks if ingress snippets are enabled as a cli arg, that the value from a snippet annotation defined in an ingress resource is set in the nginx conf. """ - @pytest.mark.parametrize('ingress_controller', - [ - pytest.param({"extra_args": ["-enable-snippets=true"]}), - ], - indirect=["ingress_controller"]) - def test_snippet_annotation_used(self, kube_apis, ingress_controller_prerequisites, ingress_controller, test_namespace): + + @pytest.mark.parametrize( + "ingress_controller", + [ + pytest.param({"extra_args": ["-enable-snippets=true"]}), + ], + indirect=["ingress_controller"], + ) + def test_snippet_annotation_used( + self, kube_apis, ingress_controller_prerequisites, ingress_controller, test_namespace + ): file_name = f"{TEST_DATA}/annotations/standard/annotations-ingress-snippets.yaml" ingress_name = create_ingress_from_yaml(kube_apis.networking_v1, test_namespace, file_name) time.sleep(5) @@ -44,18 +51,24 @@ def test_snippet_annotation_used(self, kube_apis, ingress_controller_prerequisit Checks if ingress snippets are disabled as a cli arg, that the value of the snippet annotation on an ingress resource is ignored and does not get set in the nginx conf. """ - @pytest.mark.parametrize('ingress_controller', - [ - pytest.param({"extra_args": ["-enable-snippets=false"]}), - ], - indirect=["ingress_controller"]) - def test_snippet_annotation_ignored(self, kube_apis, ingress_controller_prerequisites, ingress_controller, test_namespace): + + @pytest.mark.parametrize( + "ingress_controller", + [ + pytest.param({"extra_args": ["-enable-snippets=false"]}), + ], + indirect=["ingress_controller"], + ) + def test_snippet_annotation_ignored( + self, kube_apis, ingress_controller_prerequisites, ingress_controller, test_namespace + ): file_name = f"{TEST_DATA}/annotations/standard/annotations-ingress-snippets.yaml" create_ingress_from_yaml(kube_apis.networking_v1, test_namespace, file_name) time.sleep(5) # Now we assert the status of the ingress has correctly added a warning - event_text = f"annotations.nginx.org/server-snippets: Forbidden: snippet specified but snippets feature is not enabled" + event_text = ( + f"annotations.nginx.org/server-snippets: Forbidden: snippet specified but snippets feature is not enabled" + ) events = get_events(kube_apis.v1, test_namespace) assert_event(event_text, events) - diff --git a/tests/suite/test_tls.py b/tests/suite/test_tls.py index 9f1c681d96..e90ce9bfbb 100644 --- a/tests/suite/test_tls.py +++ b/tests/suite/test_tls.py @@ -1,11 +1,18 @@ import pytest - -from suite.resources_utils import create_ingress_from_yaml, delete_items_from_yaml, wait_before_test, \ - create_secret_from_yaml, delete_secret, replace_secret, is_secret_present, ensure_connection_to_public_endpoint -from suite.yaml_utils import get_first_ingress_host_from_yaml, get_name_from_yaml -from suite.ssl_utils import get_server_certificate_subject -from settings import TEST_DATA from _ssl import SSLError +from settings import TEST_DATA +from suite.resources_utils import ( + create_ingress_from_yaml, + create_secret_from_yaml, + delete_items_from_yaml, + delete_secret, + ensure_connection_to_public_endpoint, + is_secret_present, + replace_secret, + wait_before_test, +) +from suite.ssl_utils import get_server_certificate_subject +from suite.yaml_utils import get_first_ingress_host_from_yaml, get_name_from_yaml def assert_unrecognized_name_error(endpoint, host): @@ -20,19 +27,19 @@ def assert_unrecognized_name_error(endpoint, host): def assert_us_subject(endpoint, host): subject_dict = get_server_certificate_subject(endpoint.public_ip, host, endpoint.port_ssl) - assert subject_dict[b'C'] == b'US' - assert subject_dict[b'ST'] == b'CA' - assert subject_dict[b'O'] == b'Internet Widgits Pty Ltd' - assert subject_dict[b'CN'] == b'cafe.example.com' + assert subject_dict[b"C"] == b"US" + assert subject_dict[b"ST"] == b"CA" + assert subject_dict[b"O"] == b"Internet Widgits Pty Ltd" + assert subject_dict[b"CN"] == b"cafe.example.com" def assert_gb_subject(endpoint, host): subject_dict = get_server_certificate_subject(endpoint.public_ip, host, endpoint.port_ssl) - assert subject_dict[b'C'] == b'GB' - assert subject_dict[b'ST'] == b'Cambridgeshire' - assert subject_dict[b'O'] == b'nginx' - assert subject_dict[b'CN'] == b'cafe.example.com' + assert subject_dict[b"C"] == b"GB" + assert subject_dict[b"ST"] == b"Cambridgeshire" + assert subject_dict[b"O"] == b"nginx" + assert subject_dict[b"CN"] == b"cafe.example.com" class TLSSetup: @@ -45,8 +52,14 @@ def __init__(self, ingress_host, secret_name, secret_path, new_secret_path, inva @pytest.fixture(scope="class") -def tls_setup(request, kube_apis, ingress_controller_prerequisites, ingress_controller_endpoint, - ingress_controller, test_namespace) -> TLSSetup: +def tls_setup( + request, + kube_apis, + ingress_controller_prerequisites, + ingress_controller_endpoint, + ingress_controller, + test_namespace, +) -> TLSSetup: print("------------------------- Deploy TLS setup -----------------------------------") test_data_path = f"{TEST_DATA}/tls" @@ -58,8 +71,9 @@ def tls_setup(request, kube_apis, ingress_controller_prerequisites, ingress_cont ingress_host = get_first_ingress_host_from_yaml(ingress_path) secret_name = get_name_from_yaml(f"{test_data_path}/tls-secret.yaml") - ensure_connection_to_public_endpoint(ingress_controller_endpoint.public_ip, ingress_controller_endpoint.port, - ingress_controller_endpoint.port_ssl) + ensure_connection_to_public_endpoint( + ingress_controller_endpoint.public_ip, ingress_controller_endpoint.port, ingress_controller_endpoint.port_ssl + ) def fin(): print("Clean up TLS setup") @@ -69,14 +83,17 @@ def fin(): request.addfinalizer(fin) - return TLSSetup(ingress_host, secret_name, - f"{test_data_path}/tls-secret.yaml", - f"{test_data_path}/new-tls-secret.yaml", - f"{test_data_path}/invalid-tls-secret.yaml") + return TLSSetup( + ingress_host, + secret_name, + f"{test_data_path}/tls-secret.yaml", + f"{test_data_path}/new-tls-secret.yaml", + f"{test_data_path}/invalid-tls-secret.yaml", + ) @pytest.mark.ingresses -@pytest.mark.parametrize('tls_setup', ["standard","mergeable"], indirect=True) +@pytest.mark.parametrize("tls_setup", ["standard", "mergeable"], indirect=True) class TestIngressTLS: def test_tls_termination(self, kube_apis, ingress_controller_endpoint, test_namespace, tls_setup): print("Step 1: no secret") diff --git a/tests/suite/test_transport_server.py b/tests/suite/test_transport_server.py index bbc1ed810a..5d3d70117d 100644 --- a/tests/suite/test_transport_server.py +++ b/tests/suite/test_transport_server.py @@ -1,26 +1,21 @@ import pytest - -from suite.resources_utils import ( - wait_before_test, - get_ts_nginx_template_conf, -) -from suite.custom_resources_utils import ( - patch_ts_from_yaml, -) from settings import TEST_DATA +from suite.custom_resources_utils import patch_ts_from_yaml +from suite.resources_utils import get_ts_nginx_template_conf, wait_before_test + @pytest.mark.ts @pytest.mark.parametrize( "crd_ingress_controller, transport_server_setup", [ ( - { "type": "complete", - "extra_args": - [ - "-global-configuration=nginx-ingress/nginx-configuration", - "-enable-leader-election=false", - "-enable-snippets", - ] + { + "type": "complete", + "extra_args": [ + "-global-configuration=nginx-ingress/nginx-configuration", + "-enable-leader-election=false", + "-enable-snippets", + ], }, {"example": "transport-server-status"}, ) @@ -28,7 +23,6 @@ indirect=True, ) class TestTransportServer: - def test_snippets( self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites ): @@ -49,7 +43,7 @@ def test_snippets( transport_server_setup.namespace, transport_server_setup.name, transport_server_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace + ingress_controller_prerequisites.namespace, ) print(conf) @@ -62,8 +56,8 @@ def test_snippets( ) assert ( - "limit_conn_zone $binary_remote_addr zone=addr:10m;" in conf # stream-snippets - and "limit_conn addr 1;" in conf # server-snippets + "limit_conn_zone $binary_remote_addr zone=addr:10m;" in conf # stream-snippets + and "limit_conn addr 1;" in conf # server-snippets ) def test_configurable_timeout_directives( @@ -86,7 +80,7 @@ def test_configurable_timeout_directives( transport_server_setup.namespace, transport_server_setup.name, transport_server_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace + ingress_controller_prerequisites.namespace, ) print(conf) @@ -98,11 +92,9 @@ def test_configurable_timeout_directives( transport_server_setup.namespace, ) + assert "proxy_timeout 2s;" in conf # sessionParameters assert ( - "proxy_timeout 2s;" in conf # sessionParameters - ) - assert ( - "proxy_connect_timeout 5s;" in conf # upstreamParameters + "proxy_connect_timeout 5s;" in conf # upstreamParameters and "proxy_next_upstream on;" in conf and "proxy_next_upstream_timeout 4s;" in conf and "proxy_next_upstream_tries 3;" in conf diff --git a/tests/suite/test_transport_server_status.py b/tests/suite/test_transport_server_status.py index ece3527a1f..e153c6f03f 100644 --- a/tests/suite/test_transport_server_status.py +++ b/tests/suite/test_transport_server_status.py @@ -1,11 +1,7 @@ import pytest - -from suite.resources_utils import wait_before_test -from suite.custom_resources_utils import ( - read_ts, - patch_ts_from_yaml, -) from settings import TEST_DATA +from suite.custom_resources_utils import patch_ts_from_yaml, read_ts +from suite.resources_utils import wait_before_test @pytest.mark.ts @@ -15,11 +11,10 @@ ( { "type": "complete", - "extra_args": - [ - "-global-configuration=nginx-ingress/nginx-configuration", - "-enable-leader-election=false" - ] + "extra_args": [ + "-global-configuration=nginx-ingress/nginx-configuration", + "-enable-leader-election=false", + ], }, {"example": "transport-server-status", "app_type": "simple"}, ) @@ -27,7 +22,6 @@ indirect=True, ) class TestTransportServerStatus: - def restore_ts(self, kube_apis, transport_server_setup) -> None: """ Function to revert a TransportServer resource to a valid state. @@ -42,7 +36,10 @@ def restore_ts(self, kube_apis, transport_server_setup) -> None: @pytest.mark.smoke def test_status_valid( - self, kube_apis, crd_ingress_controller, transport_server_setup, + self, + kube_apis, + crd_ingress_controller, + transport_server_setup, ): """ Test TransportServer status with valid fields in yaml. @@ -59,7 +56,10 @@ def test_status_valid( ) def test_status_warning( - self, kube_apis, crd_ingress_controller, transport_server_setup, + self, + kube_apis, + crd_ingress_controller, + transport_server_setup, ): """ Test TransportServer status with a missing listener. @@ -85,7 +85,10 @@ def test_status_warning( ) def test_status_invalid( - self, kube_apis, crd_ingress_controller, transport_server_setup, + self, + kube_apis, + crd_ingress_controller, + transport_server_setup, ): """ Test TransportServer status with an invalid protocol. diff --git a/tests/suite/test_transport_server_tcp_load_balance.py b/tests/suite/test_transport_server_tcp_load_balance.py index 4739068d42..044e7d6a88 100644 --- a/tests/suite/test_transport_server_tcp_load_balance.py +++ b/tests/suite/test_transport_server_tcp_load_balance.py @@ -1,24 +1,18 @@ -import pytest import re import socket import time -from urllib3.exceptions import NewConnectionError - +import pytest +from settings import TEST_DATA +from suite.custom_resources_utils import create_ts_from_yaml, delete_ts, patch_ts_from_yaml, read_ts from suite.resources_utils import ( - wait_before_test, + get_events, get_ts_nginx_template_conf, scale_deployment, - get_events, + wait_before_test, wait_for_event_increment, ) -from suite.custom_resources_utils import ( - patch_ts_from_yaml, - read_ts, - delete_ts, - create_ts_from_yaml, -) -from settings import TEST_DATA +from urllib3.exceptions import NewConnectionError @pytest.mark.ts @@ -29,11 +23,10 @@ ( { "type": "complete", - "extra_args": - [ - "-global-configuration=nginx-ingress/nginx-configuration", - "-enable-leader-election=false" - ] + "extra_args": [ + "-global-configuration=nginx-ingress/nginx-configuration", + "-enable-leader-election=false", + ], }, {"example": "transport-server-tcp-load-balance"}, ) @@ -41,7 +34,6 @@ indirect=True, ) class TestTransportServerTcpLoadBalance: - def restore_ts(self, kube_apis, transport_server_setup) -> None: """ Function to revert a TransportServer resource to a valid state. @@ -61,42 +53,42 @@ def test_number_of_replicas( """ The load balancing of TCP should result in 4 servers to match the 4 replicas of a service. """ - original = scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, - "tcp-service", transport_server_setup.namespace, 4) + original = scale_deployment( + kube_apis.v1, kube_apis.apps_v1_api, "tcp-service", transport_server_setup.namespace, 4 + ) num_servers = 0 retry = 0 - while(num_servers is not 4 and retry <= 30): + while num_servers != 4 and retry <= 30: result_conf = get_ts_nginx_template_conf( kube_apis.v1, transport_server_setup.namespace, transport_server_setup.name, transport_server_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace + ingress_controller_prerequisites.namespace, ) - pattern = 'server .*;' + pattern = "server .*;" num_servers = len(re.findall(pattern, result_conf)) retry += 1 wait_before_test(1) print(f"Retry #{retry}") - assert num_servers is 4 + assert num_servers == 4 - scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "tcp-service", - transport_server_setup.namespace, original) + scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "tcp-service", transport_server_setup.namespace, original) retry = 0 - while(num_servers is not original and retry <= 50): + while num_servers is not original and retry <= 50: result_conf = get_ts_nginx_template_conf( kube_apis.v1, transport_server_setup.namespace, transport_server_setup.name, transport_server_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace + ingress_controller_prerequisites.namespace, ) - pattern = 'server .*;' + pattern = "server .*;" num_servers = len(re.findall(pattern, result_conf)) retry += 1 wait_before_test(1) @@ -105,7 +97,7 @@ def test_number_of_replicas( assert num_servers is original def test_tcp_request_load_balanced( - self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites + self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites ): """ Requests to the load balanced TCP service should result in responses from 3 different endpoints. @@ -118,14 +110,14 @@ def test_tcp_request_load_balanced( endpoints = {} retry = 0 - while(len(endpoints) is not 3 and retry <= 30): + while len(endpoints) != 3 and retry <= 30: for i in range(20): host = host.strip("[]") - client = socket.create_connection((host,port)) - client.sendall(b'connect') + client = socket.create_connection((host, port)) + client.sendall(b"connect") response = client.recv(4096) endpoint = response.decode() - print(f' req number {i}; response: {endpoint}') + print(f" req number {i}; response: {endpoint}") if endpoint not in endpoints: endpoints[endpoint] = 1 else: @@ -135,17 +127,17 @@ def test_tcp_request_load_balanced( wait_before_test(1) print(f"Retry #{retry}") - assert len(endpoints) is 3 + assert len(endpoints) == 3 result_conf = get_ts_nginx_template_conf( kube_apis.v1, transport_server_setup.namespace, transport_server_setup.name, transport_server_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace + ingress_controller_prerequisites.namespace, ) - pattern = 'server .*;' + pattern = "server .*;" servers = re.findall(pattern, result_conf) for key in endpoints.keys(): found = False @@ -154,9 +146,7 @@ def test_tcp_request_load_balanced( found = True assert found - def test_tcp_request_load_balanced_multiple( - self, kube_apis, crd_ingress_controller, transport_server_setup - ): + def test_tcp_request_load_balanced_multiple(self, kube_apis, crd_ingress_controller, transport_server_setup): """ Requests to the load balanced TCP service should result in responses from 3 different endpoints. """ @@ -166,13 +156,13 @@ def test_tcp_request_load_balanced_multiple( # Step 1, confirm load balancing is working. print(f"sending tcp requests to: {host}:{port}") host = host.strip("[]") - client = socket.create_connection((host,port)) - client.sendall(b'connect') + client = socket.create_connection((host, port)) + client.sendall(b"connect") response = client.recv(4096) endpoint = response.decode() - print(f'response: {endpoint}') + print(f"response: {endpoint}") client.close() - assert endpoint is not "" + assert endpoint != "" # Step 2, add a second TransportServer with the same port and confirm the collision transport_server_file = f"{TEST_DATA}/transport-server-tcp-load-balance/second-transport-server.yaml" @@ -181,7 +171,7 @@ def test_tcp_request_load_balanced_multiple( ) wait_before_test() - second_ts_name = ts_resource['metadata']['name'] + second_ts_name = ts_resource["metadata"]["name"] response = read_ts( kube_apis.custom_objects, transport_server_setup.namespace, @@ -195,8 +185,7 @@ def test_tcp_request_load_balanced_multiple( ) # Step 3, remove the default TransportServer with the same port - delete_ts(kube_apis.custom_objects, transport_server_setup.resource, - transport_server_setup.namespace) + delete_ts(kube_apis.custom_objects, transport_server_setup.resource, transport_server_setup.namespace) wait_before_test() response = read_ts( @@ -213,25 +202,21 @@ def test_tcp_request_load_balanced_multiple( # Step 4, confirm load balancing is still working. print(f"sending tcp requests to: {host}:{port}") host = host.strip("[]") - client = socket.create_connection((host,port)) - client.sendall(b'connect') + client = socket.create_connection((host, port)) + client.sendall(b"connect") response = client.recv(4096) endpoint = response.decode() - print(f'response: {endpoint}') + print(f"response: {endpoint}") client.close() - assert endpoint is not "" + assert endpoint != "" # cleanup delete_ts(kube_apis.custom_objects, ts_resource, transport_server_setup.namespace) transport_server_file = f"{TEST_DATA}/transport-server-tcp-load-balance/standard/transport-server.yaml" - create_ts_from_yaml( - kube_apis.custom_objects, transport_server_file, transport_server_setup.namespace - ) + create_ts_from_yaml(kube_apis.custom_objects, transport_server_file, transport_server_setup.namespace) wait_before_test() - def test_tcp_request_load_balanced_wrong_port( - self, kube_apis, crd_ingress_controller, transport_server_setup - ): + def test_tcp_request_load_balanced_wrong_port(self, kube_apis, crd_ingress_controller, transport_server_setup): """ Requests to the load balanced TCP service should result in responses from 3 different endpoints. """ @@ -253,16 +238,14 @@ def test_tcp_request_load_balanced_wrong_port( for i in range(3): try: host = host.strip("[]") - client = socket.create_connection((host,port)) - client.sendall(b'connect') + client = socket.create_connection((host, port)) + client.sendall(b"connect") except ConnectionResetError as E: print("The expected exception occurred:", E) self.restore_ts(kube_apis, transport_server_setup) - def test_tcp_request_load_balanced_missing_service( - self, kube_apis, crd_ingress_controller, transport_server_setup - ): + def test_tcp_request_load_balanced_missing_service(self, kube_apis, crd_ingress_controller, transport_server_setup): """ Requests to the load balanced TCP service should result in responses from 3 different endpoints. """ @@ -284,8 +267,8 @@ def test_tcp_request_load_balanced_missing_service( for i in range(3): try: host = host.strip("[]") - client = socket.create_connection((host,port)) - client.sendall(b'connect') + client = socket.create_connection((host, port)) + client.sendall(b"connect") except ConnectionResetError as E: print("The expected exception occurred:", E) @@ -294,15 +277,15 @@ def test_tcp_request_load_balanced_missing_service( def make_holding_connection(self, host, port): print(f"sending tcp requests to: {host}:{port}") host = host.strip("[]") - client = socket.create_connection((host,port)) - client.sendall(b'hold') + client = socket.create_connection((host, port)) + client.sendall(b"hold") response = client.recv(4096) endpoint = response.decode() - print(f'response: {endpoint}') + print(f"response: {endpoint}") return client def test_tcp_request_max_connections( - self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites + self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites ): """ The config, maxConns, should limit the number of open TCP connections. @@ -320,22 +303,22 @@ def test_tcp_request_max_connections( wait_before_test() configs = 0 retry = 0 - while(configs is not 3 and retry <= 30): + while configs != 3 and retry <= 30: result_conf = get_ts_nginx_template_conf( kube_apis.v1, transport_server_setup.namespace, transport_server_setup.name, transport_server_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace + ingress_controller_prerequisites.namespace, ) - pattern = 'max_conns=2' + pattern = "max_conns=2" configs = len(re.findall(pattern, result_conf)) retry += 1 wait_before_test(1) print(f"Retry #{retry}") - assert configs is 3 + assert configs == 3 # step 2 - make the number of allowed connections port = transport_server_setup.public_endpoint.tcp_server_port @@ -377,7 +360,7 @@ def test_tcp_request_max_connections( c.close() def test_tcp_request_load_balanced_method( - self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites + self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites ): """ Update load balancing method to 'hash'. This send requests to a specific pod based on it's IP. In this case @@ -396,22 +379,22 @@ def test_tcp_request_load_balanced_method( wait_before_test() num_servers = 0 retry = 0 - while(num_servers is not 3 and retry <= 30): + while num_servers != 3 and retry <= 30: result_conf = get_ts_nginx_template_conf( kube_apis.v1, transport_server_setup.namespace, transport_server_setup.name, transport_server_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace + ingress_controller_prerequisites.namespace, ) - pattern = 'server .*;' + pattern = "server .*;" num_servers = len(re.findall(pattern, result_conf)) retry += 1 wait_before_test(1) print(f"Retry #{retry}") - assert num_servers is 3 + assert num_servers == 3 # Step 2 - confirm all request go to the same endpoint. @@ -419,14 +402,14 @@ def test_tcp_request_load_balanced_method( host = transport_server_setup.public_endpoint.public_ip endpoints = {} retry = 0 - while(len(endpoints) is not 1 and retry <= 30): + while len(endpoints) != 1 and retry <= 30: for i in range(20): host = host.strip("[]") - client = socket.create_connection((host,port)) - client.sendall(b'connect') + client = socket.create_connection((host, port)) + client.sendall(b"connect") response = client.recv(4096) endpoint = response.decode() - print(f' req number {i}; response: {endpoint}') + print(f" req number {i}; response: {endpoint}") if endpoint not in endpoints: endpoints[endpoint] = 1 else: @@ -436,7 +419,7 @@ def test_tcp_request_load_balanced_method( wait_before_test(1) print(f"Retry #{retry}") - assert len(endpoints) is 1 + assert len(endpoints) == 1 # Step 3 - restore to default load balancing method and confirm requests are balanced. @@ -445,14 +428,14 @@ def test_tcp_request_load_balanced_method( endpoints = {} retry = 0 - while(len(endpoints) is not 3 and retry <= 30): + while len(endpoints) != 3 and retry <= 30: for i in range(20): host = host.strip("[]") - client = socket.create_connection((host,port)) - client.sendall(b'connect') + client = socket.create_connection((host, port)) + client.sendall(b"connect") response = client.recv(4096) endpoint = response.decode() - print(f' req number {i}; response: {endpoint}') + print(f" req number {i}; response: {endpoint}") if endpoint not in endpoints: endpoints[endpoint] = 1 else: @@ -462,11 +445,11 @@ def test_tcp_request_load_balanced_method( wait_before_test(1) print(f"Retry #{retry}") - assert len(endpoints) is 3 + assert len(endpoints) == 3 @pytest.mark.skip_for_nginx_oss def test_tcp_passing_healthcheck_with_match( - self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites + self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites ): """ Configure a passing health check and check that all backend pods return responses. @@ -489,7 +472,7 @@ def test_tcp_passing_healthcheck_with_match( transport_server_setup.namespace, transport_server_setup.name, transport_server_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace + ingress_controller_prerequisites.namespace, ) match = f"match_ts_{transport_server_setup.namespace}_transport-server_tcp-app" @@ -507,14 +490,14 @@ def test_tcp_passing_healthcheck_with_match( endpoints = {} retry = 0 - while(len(endpoints) is not 3 and retry <= 30): + while len(endpoints) != 3 and retry <= 30: for i in range(20): host = host.strip("[]") - client = socket.create_connection((host,port)) - client.sendall(b'connect') + client = socket.create_connection((host, port)) + client.sendall(b"connect") response = client.recv(4096) endpoint = response.decode() - print(f' req number {i}; response: {endpoint}') + print(f" req number {i}; response: {endpoint}") if endpoint not in endpoints: endpoints[endpoint] = 1 else: @@ -523,7 +506,7 @@ def test_tcp_passing_healthcheck_with_match( retry += 1 wait_before_test(1) print(f"Retry #{retry}") - assert len(endpoints) is 3 + assert len(endpoints) == 3 # Step 3 - restore @@ -531,7 +514,7 @@ def test_tcp_passing_healthcheck_with_match( @pytest.mark.skip_for_nginx_oss def test_tcp_failing_healthcheck_with_match( - self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites + self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites ): """ Configure a failing health check and check that NGINX Plus resets connections. @@ -554,7 +537,7 @@ def test_tcp_failing_healthcheck_with_match( transport_server_setup.namespace, transport_server_setup.name, transport_server_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace + ingress_controller_prerequisites.namespace, ) match = f"match_ts_{transport_server_setup.namespace}_transport-server_tcp-app" @@ -571,8 +554,8 @@ def test_tcp_failing_healthcheck_with_match( host = transport_server_setup.public_endpoint.public_ip host = host.strip("[]") - client = socket.create_connection((host,port)) - client.sendall(b'connect') + client = socket.create_connection((host, port)) + client.sendall(b"connect") try: client.recv(4096) # must return ConnectionResetError diff --git a/tests/suite/test_transport_server_udp_load_balance.py b/tests/suite/test_transport_server_udp_load_balance.py index a07adc99f5..4e25a50a41 100644 --- a/tests/suite/test_transport_server_udp_load_balance.py +++ b/tests/suite/test_transport_server_udp_load_balance.py @@ -1,22 +1,18 @@ -import pytest +import ipaddress import re import socket -import ipaddress +import pytest +from settings import TEST_DATA +from suite.custom_resources_utils import create_ts_from_yaml, delete_ts, patch_ts_from_yaml, read_ts from suite.resources_utils import ( - wait_before_test, + get_events, get_ts_nginx_template_conf, scale_deployment, - get_events, + wait_before_test, wait_for_event_increment, ) -from suite.custom_resources_utils import ( - patch_ts_from_yaml, - read_ts, - delete_ts, - create_ts_from_yaml, -) -from settings import TEST_DATA + # Helper functions def chk_endpoint(endp): @@ -24,17 +20,18 @@ def chk_endpoint(endp): If an endpoint is IPv6, return a formatted [ip]:port endpoint. Otherwise, return unmodified endpoint. """ - ip = endp[:endp.rfind(":")] + ip = endp[: endp.rfind(":")] try: address = ipaddress.ip_address(ip) except ValueError: return endp if address.version == 6: - port = endp[endp.rfind(":"):] + port = endp[endp.rfind(":") :] return f"[{ip}]{port}" else: return endp + def ipfamily_from_host(host): """ Return socket type (AF_INET or AF_INET6) based on @@ -49,6 +46,7 @@ def ipfamily_from_host(host): pass return sock + @pytest.mark.ts @pytest.mark.skip_for_loadbalancer @pytest.mark.parametrize( @@ -57,11 +55,10 @@ def ipfamily_from_host(host): ( { "type": "complete", - "extra_args": - [ - "-global-configuration=nginx-ingress/nginx-configuration", - "-enable-leader-election=false" - ] + "extra_args": [ + "-global-configuration=nginx-ingress/nginx-configuration", + "-enable-leader-election=false", + ], }, {"example": "transport-server-udp-load-balance"}, ) @@ -69,7 +66,6 @@ def ipfamily_from_host(host): indirect=True, ) class TestTransportServerUdpLoadBalance: - def restore_ts(self, kube_apis, transport_server_setup) -> None: """ Function to revert a TransportServer resource to a valid state. @@ -88,41 +84,41 @@ def test_number_of_replicas( """ The load balancing of UDP should result in 4 servers to match the 4 replicas of a service. """ - original = scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, - "udp-service", transport_server_setup.namespace, 4) + original = scale_deployment( + kube_apis.v1, kube_apis.apps_v1_api, "udp-service", transport_server_setup.namespace, 4 + ) num_servers = 0 retry = 0 - while(num_servers is not 4 and retry <= 50): + while num_servers != 4 and retry <= 50: result_conf = get_ts_nginx_template_conf( kube_apis.v1, transport_server_setup.namespace, transport_server_setup.name, transport_server_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace + ingress_controller_prerequisites.namespace, ) - pattern = 'server .*;' + pattern = "server .*;" num_servers = len(re.findall(pattern, result_conf)) retry += 1 wait_before_test(1) print(f"Retry #{retry}") - assert num_servers is 4 + assert num_servers == 4 - scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "udp-service", - transport_server_setup.namespace, original) + scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "udp-service", transport_server_setup.namespace, original) retry = 0 - while(num_servers is not original and retry <= 50): + while num_servers is not original and retry <= 50: result_conf = get_ts_nginx_template_conf( kube_apis.v1, transport_server_setup.namespace, transport_server_setup.name, transport_server_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace + ingress_controller_prerequisites.namespace, ) - pattern = 'server .*;' + pattern = "server .*;" num_servers = len(re.findall(pattern, result_conf)) retry += 1 wait_before_test(1) @@ -131,7 +127,7 @@ def test_number_of_replicas( assert num_servers is original def test_udp_request_load_balanced( - self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites + self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites ): """ Requests to the load balanced UDP service should result in responses from 3 different endpoints. @@ -144,14 +140,14 @@ def test_udp_request_load_balanced( endpoints = {} retry = 0 - while(len(endpoints) is not 3 and retry <= 30): + while len(endpoints) != 3 and retry <= 30: for i in range(20): host = host.strip("[]") client = socket.socket(ipfamily_from_host(host), socket.SOCK_DGRAM, 0) - client.sendto("ping".encode('utf-8'), (host, port)) + client.sendto(b"ping", (host, port)) data, address = client.recvfrom(4096) endpoint = data.decode() - print(f' req number {i}; response: {endpoint}') + print(f" req number {i}; response: {endpoint}") if endpoint not in endpoints: endpoints[endpoint] = 1 else: @@ -161,17 +157,17 @@ def test_udp_request_load_balanced( wait_before_test(1) print(f"Retry #{retry}") - assert len(endpoints) is 3 + assert len(endpoints) == 3 result_conf = get_ts_nginx_template_conf( kube_apis.v1, transport_server_setup.namespace, transport_server_setup.name, transport_server_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace + ingress_controller_prerequisites.namespace, ) - pattern = 'server .*;' + pattern = "server .*;" servers = re.findall(pattern, result_conf) for key in endpoints.keys(): found = False @@ -180,9 +176,7 @@ def test_udp_request_load_balanced( found = True assert found - def test_udp_request_load_balanced_multiple( - self, kube_apis, crd_ingress_controller, transport_server_setup - ): + def test_udp_request_load_balanced_multiple(self, kube_apis, crd_ingress_controller, transport_server_setup): """ Requests to the load balanced UDP service should result in responses from 3 different endpoints. """ @@ -193,10 +187,10 @@ def test_udp_request_load_balanced_multiple( print(f"sending udp requests to: {host}:{port}") host = host.strip("[]") client = socket.socket(ipfamily_from_host(host), socket.SOCK_DGRAM, 0) - client.sendto("ping".encode('utf-8'), (host, port)) + client.sendto(b"ping", (host, port)) data, address = client.recvfrom(4096) endpoint = data.decode() - print(f'response: {endpoint}') + print(f"response: {endpoint}") client.close() # Step 2, add a second TransportServer with the same port and confirm the collision @@ -206,7 +200,7 @@ def test_udp_request_load_balanced_multiple( ) wait_before_test() - second_ts_name = ts_resource['metadata']['name'] + second_ts_name = ts_resource["metadata"]["name"] response = read_ts( kube_apis.custom_objects, transport_server_setup.namespace, @@ -220,8 +214,7 @@ def test_udp_request_load_balanced_multiple( ) # Step 3, remove the default TransportServer with the same port - delete_ts(kube_apis.custom_objects, transport_server_setup.resource, - transport_server_setup.namespace) + delete_ts(kube_apis.custom_objects, transport_server_setup.resource, transport_server_setup.namespace) wait_before_test() response = read_ts( @@ -237,25 +230,21 @@ def test_udp_request_load_balanced_multiple( # Step 4, confirm load balancing is still working. client = socket.socket(ipfamily_from_host(host), socket.SOCK_DGRAM, 0) - client.sendto("ping".encode('utf-8'), (host, port)) + client.sendto(b"ping", (host, port)) data, address = client.recvfrom(4096) endpoint = data.decode() - print(f'response: {endpoint}') + print(f"response: {endpoint}") client.close() - assert endpoint is not "" + assert endpoint != "" # cleanup delete_ts(kube_apis.custom_objects, ts_resource, transport_server_setup.namespace) transport_server_file = f"{TEST_DATA}/transport-server-udp-load-balance/standard/transport-server.yaml" - create_ts_from_yaml( - kube_apis.custom_objects, transport_server_file, transport_server_setup.namespace - ) + create_ts_from_yaml(kube_apis.custom_objects, transport_server_file, transport_server_setup.namespace) wait_before_test() @pytest.mark.parametrize("file", ["wrong-port-transport-server.yaml", "missing-service-transport-server.yaml"]) - def test_udp_request_fails( - self, kube_apis, crd_ingress_controller, transport_server_setup, file - ): + def test_udp_request_fails(self, kube_apis, crd_ingress_controller, transport_server_setup, file): patch_src = f"{TEST_DATA}/transport-server-udp-load-balance/{file}" patch_ts_from_yaml( kube_apis.custom_objects, @@ -275,7 +264,7 @@ def test_udp_request_fails( host = host.strip("[]") client = socket.socket(ipfamily_from_host(host), socket.SOCK_DGRAM, 0) client.settimeout(2) - client.sendto("ping".encode('utf-8'), (host, port)) + client.sendto(b"ping", (host, port)) try: client.recvfrom(4096) # it should timeout @@ -289,7 +278,7 @@ def test_udp_request_fails( @pytest.mark.skip_for_nginx_oss def test_udp_passing_healthcheck_with_match( - self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites + self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites ): """ Configure a passing health check and check that all backend pods return responses. @@ -313,7 +302,7 @@ def test_udp_passing_healthcheck_with_match( transport_server_setup.namespace, transport_server_setup.name, transport_server_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace + ingress_controller_prerequisites.namespace, ) match = f"match_ts_{transport_server_setup.namespace}_transport-server_udp-app" @@ -333,14 +322,14 @@ def test_udp_passing_healthcheck_with_match( retry = 0 endpoints = {} - while(len(endpoints) is not 3 and retry <= 30): + while len(endpoints) != 3 and retry <= 30: for i in range(20): host = host.strip("[]") client = socket.socket(ipfamily_from_host(host), socket.SOCK_DGRAM, 0) - client.sendto("ping".encode('utf-8'), (host, port)) + client.sendto(b"ping", (host, port)) data, address = client.recvfrom(4096) endpoint = data.decode() - print(f' req number {i}; response: {endpoint}') + print(f" req number {i}; response: {endpoint}") if endpoint not in endpoints: endpoints[endpoint] = 1 else: @@ -350,7 +339,7 @@ def test_udp_passing_healthcheck_with_match( wait_before_test(1) print(f"Retry #{retry}") - assert len(endpoints) is 3 + assert len(endpoints) == 3 # Step 3 - restore @@ -358,7 +347,7 @@ def test_udp_passing_healthcheck_with_match( @pytest.mark.skip_for_nginx_oss def test_udp_failing_healthcheck_with_match( - self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites + self, kube_apis, crd_ingress_controller, transport_server_setup, ingress_controller_prerequisites ): """ Configure a failing health check and check that NGINX Plus doesn't respond. @@ -380,7 +369,7 @@ def test_udp_failing_healthcheck_with_match( transport_server_setup.namespace, transport_server_setup.name, transport_server_setup.ingress_pod_name, - ingress_controller_prerequisites.namespace + ingress_controller_prerequisites.namespace, ) match = f"match_ts_{transport_server_setup.namespace}_transport-server_udp-app" @@ -399,12 +388,12 @@ def test_udp_failing_healthcheck_with_match( host = host.strip("[]") client = socket.socket(ipfamily_from_host(host), socket.SOCK_DGRAM, 0) client.settimeout(2) - client.sendto("ping".encode('utf-8'), (host, port)) + client.sendto(b"ping", (host, port)) try: # client.recvfrom(4096) data, address = client.recvfrom(4096) endpoint = data.decode() - print(f' req number response: {endpoint}') + print(f" req number response: {endpoint}") # it should timeout pytest.fail("expected a timeout") except socket.timeout: diff --git a/tests/suite/test_ts_tls_passthrough.py b/tests/suite/test_ts_tls_passthrough.py index fe16c16dbf..00c8fd9fec 100644 --- a/tests/suite/test_ts_tls_passthrough.py +++ b/tests/suite/test_ts_tls_passthrough.py @@ -1,28 +1,22 @@ -import pytest, ssl -import requests +import ssl from pprint import pprint + +import pytest +import requests +from settings import TEST_DATA +from suite.custom_resources_utils import create_ts_from_yaml, delete_ts, read_ts from suite.fixtures import PublicEndpoint from suite.resources_utils import ( - wait_before_test, create_items_from_yaml, delete_items_from_yaml, - wait_until_all_pods_are_ready, get_first_pod_name, + wait_before_test, + wait_until_all_pods_are_ready, ) -from suite.custom_resources_utils import ( - read_ts, - delete_ts, - create_ts_from_yaml, - -) -from suite.vs_vsr_resources_utils import ( - read_vs, - create_virtual_server_from_yaml, - delete_virtual_server, -) +from suite.ssl_utils import create_sni_session, get_server_certificate_subject +from suite.vs_vsr_resources_utils import create_virtual_server_from_yaml, delete_virtual_server, read_vs from suite.yaml_utils import get_first_host_from_yaml -from suite.ssl_utils import get_server_certificate_subject, create_sni_session -from settings import TEST_DATA + class TransportServerTlsSetup: """ @@ -57,18 +51,14 @@ def transport_server_tls_passthrough_setup( :param ingress_controller_endpoint: ip and port information :return TransportServerTlsSetup: """ - print( - "------------------------- Deploy Transport Server with tls passthrough -----------------------------------" - ) + print("------------------------- Deploy Transport Server with tls passthrough -----------------------------------") # deploy secure_app secure_app_file = f"{TEST_DATA}/{request.param['example']}/standard/secure-app.yaml" create_items_from_yaml(kube_apis, secure_app_file, test_namespace) # deploy transport server transport_server_std_src = f"{TEST_DATA}/{request.param['example']}/standard/transport-server.yaml" - ts_resource = create_ts_from_yaml( - kube_apis.custom_objects, transport_server_std_src, test_namespace - ) + ts_resource = create_ts_from_yaml(kube_apis.custom_objects, transport_server_std_src, test_namespace) ts_host = get_first_host_from_yaml(transport_server_std_src) wait_until_all_pods_are_ready(kube_apis.v1, test_namespace) @@ -112,10 +102,10 @@ def restore_ts(self, kube_apis, transport_server_tls_passthrough_setup) -> None: """ ts_std_src = f"{TEST_DATA}/transport-server-tls-passthrough/standard/transport-server.yaml" ts_std_res = create_ts_from_yaml( - kube_apis.custom_objects, - ts_std_src, - transport_server_tls_passthrough_setup.namespace, - ) + kube_apis.custom_objects, + ts_std_src, + transport_server_tls_passthrough_setup.namespace, + ) wait_before_test(1) pprint(ts_std_res) @@ -128,7 +118,7 @@ def test_tls_passthrough( test_namespace, ): """ - Test TransportServer TLS passthrough on https port. + Test TransportServer TLS passthrough on https port. """ session = create_sni_session() req_url = ( @@ -143,7 +133,7 @@ def test_tls_passthrough( ) assert resp.status_code == 200 assert f"hello from pod {get_first_pod_name(kube_apis.v1, test_namespace)}" in resp.text - + def test_tls_passthrough_host_collision_ts( self, kube_apis, @@ -152,19 +142,13 @@ def test_tls_passthrough_host_collision_ts( test_namespace, ): """ - Test host collision handling in TransportServer with another TransportServer. + Test host collision handling in TransportServer with another TransportServer. """ print("Step 1: Create second TS with same host") - ts_src_same_host = ( - f"{TEST_DATA}/transport-server-tls-passthrough/transport-server-same-host.yaml" - ) - ts_same_host = create_ts_from_yaml( - kube_apis.custom_objects, ts_src_same_host, test_namespace - ) + ts_src_same_host = f"{TEST_DATA}/transport-server-tls-passthrough/transport-server-same-host.yaml" + ts_same_host = create_ts_from_yaml(kube_apis.custom_objects, ts_src_same_host, test_namespace) wait_before_test() - response = read_ts( - kube_apis.custom_objects, test_namespace, ts_same_host["metadata"]["name"] - ) + response = read_ts(kube_apis.custom_objects, test_namespace, ts_same_host["metadata"]["name"]) assert ( response["status"]["reason"] == "Rejected" and response["status"]["message"] == "Host is taken by another resource" @@ -177,27 +161,13 @@ def test_tls_passthrough_host_collision_ts( test_namespace, ) wait_before_test(1) - response = read_ts( - kube_apis.custom_objects, test_namespace, ts_same_host["metadata"]["name"] - ) - assert ( - response["status"]["reason"] == "AddedOrUpdated" - and response["status"]["state"] == "Valid" - ) + response = read_ts(kube_apis.custom_objects, test_namespace, ts_same_host["metadata"]["name"]) + assert response["status"]["reason"] == "AddedOrUpdated" and response["status"]["state"] == "Valid" print("Step 3: Delete second TS and re-create standard one") - delete_ts( - kube_apis.custom_objects, - ts_same_host, - test_namespace - ) + delete_ts(kube_apis.custom_objects, ts_same_host, test_namespace) self.restore_ts(kube_apis, transport_server_tls_passthrough_setup) - response = read_ts( - kube_apis.custom_objects, test_namespace, transport_server_tls_passthrough_setup.name - ) - assert ( - response["status"]["reason"] == "AddedOrUpdated" - and response["status"]["state"] == "Valid" - ) + response = read_ts(kube_apis.custom_objects, test_namespace, transport_server_tls_passthrough_setup.name) + assert response["status"]["reason"] == "AddedOrUpdated" and response["status"]["state"] == "Valid" def test_tls_passthrough_host_collision_vs( self, @@ -207,15 +177,11 @@ def test_tls_passthrough_host_collision_vs( test_namespace, ): """ - Test host collision handling in TransportServer with VirtualServer. + Test host collision handling in TransportServer with VirtualServer. """ print("Step 1: Create VirtualServer with same host") - vs_src_same_host = ( - f"{TEST_DATA}/transport-server-tls-passthrough/virtual-server-same-host.yaml" - ) - vs_same_host_name = create_virtual_server_from_yaml( - kube_apis.custom_objects, vs_src_same_host, test_namespace - ) + vs_src_same_host = f"{TEST_DATA}/transport-server-tls-passthrough/virtual-server-same-host.yaml" + vs_same_host_name = create_virtual_server_from_yaml(kube_apis.custom_objects, vs_src_same_host, test_namespace) wait_before_test(1) response = read_vs(kube_apis.custom_objects, test_namespace, vs_same_host_name) delete_virtual_server(kube_apis.custom_objects, vs_same_host_name, test_namespace) diff --git a/tests/suite/test_v_s_route.py b/tests/suite/test_v_s_route.py index 3843531ed3..e64660005e 100644 --- a/tests/suite/test_v_s_route.py +++ b/tests/suite/test_v_s_route.py @@ -1,15 +1,29 @@ -import requests import pytest +import requests from kubernetes.client.rest import ApiException - from settings import TEST_DATA -from suite.custom_assertions import assert_event_and_count, assert_event_and_get_count, \ - assert_event_with_full_equality_and_count -from suite.vs_vsr_resources_utils import create_virtual_server_from_yaml, \ - delete_virtual_server, create_v_s_route_from_yaml, delete_v_s_route, get_vs_nginx_template_conf, \ - patch_v_s_route_from_yaml -from suite.resources_utils import delete_service, get_first_pod_name, get_events, \ - wait_before_test, read_service, replace_service, create_service_with_name +from suite.custom_assertions import ( + assert_event_and_count, + assert_event_and_get_count, + assert_event_with_full_equality_and_count, +) +from suite.resources_utils import ( + create_service_with_name, + delete_service, + get_events, + get_first_pod_name, + read_service, + replace_service, + wait_before_test, +) +from suite.vs_vsr_resources_utils import ( + create_v_s_route_from_yaml, + create_virtual_server_from_yaml, + delete_v_s_route, + delete_virtual_server, + get_vs_nginx_template_conf, + patch_v_s_route_from_yaml, +) from suite.yaml_utils import get_paths_from_vsr_yaml @@ -35,17 +49,16 @@ def assert_locations_not_in_config(config, paths): @pytest.mark.smoke @pytest.mark.vsr -@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, {"example": "virtual-server-route"})], + indirect=True, +) class TestVirtualServerRoute: @pytest.mark.flaky(max_runs=3) - def test_responses_and_events_in_flow(self, kube_apis, - ingress_controller_prerequisites, - crd_ingress_controller, - v_s_route_setup, - v_s_route_app_setup): + def test_responses_and_events_in_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup + ): req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) vs_name = f"{v_s_route_setup.namespace}/{v_s_route_setup.vs_name}" @@ -55,19 +68,18 @@ def test_responses_and_events_in_flow(self, kube_apis, vs_event_text = f"Configuration for {vs_name} was added or updated" vs_warning_event_text = f"Configuration for {vs_name} was added or updated with warning(s): VirtualServerRoute {vsr_1_name} doesn't exist or invalid" vsr_2_event_text = f"Configuration for {vsr_2_name} was added or updated" - initial_config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + initial_config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) print("\nStep 1: initial check") - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", - headers={"host": v_s_route_setup.vs_host}) - resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", headers={"host": v_s_route_setup.vs_host}) + resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) events_ns_1 = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) events_ns_2 = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) assert_responses_and_server_name(resp_1, resp_2, resp_3) @@ -78,18 +90,17 @@ def test_responses_and_events_in_flow(self, kube_apis, initial_count_vsr_2 = assert_event_and_get_count(vsr_2_event_text, events_ns_2) print("\nStep 2: update multiple VSRoute and check") - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, - f"{TEST_DATA}/virtual-server-route/route-multiple-updated.yaml", - v_s_route_setup.route_m.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_m.name, + f"{TEST_DATA}/virtual-server-route/route-multiple-updated.yaml", + v_s_route_setup.route_m.namespace, + ) new_vsr_paths = get_paths_from_vsr_yaml(f"{TEST_DATA}/virtual-server-route/route-multiple-updated.yaml") wait_before_test(1) - resp_1 = requests.get(f"{req_url}{new_vsr_paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{new_vsr_paths[1]}", - headers={"host": v_s_route_setup.vs_host}) - resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + resp_1 = requests.get(f"{req_url}{new_vsr_paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{new_vsr_paths[1]}", headers={"host": v_s_route_setup.vs_host}) + resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) assert_responses_and_server_name(resp_1, resp_2, resp_3) events_ns_1 = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) events_ns_2 = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) @@ -99,17 +110,16 @@ def test_responses_and_events_in_flow(self, kube_apis, assert_event_and_count(vsr_2_event_text, initial_count_vsr_2 + 1, events_ns_2) print("\nStep 3: restore VSRoute and check") - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, - f"{TEST_DATA}/virtual-server-route/route-multiple.yaml", - v_s_route_setup.route_m.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_m.name, + f"{TEST_DATA}/virtual-server-route/route-multiple.yaml", + v_s_route_setup.route_m.namespace, + ) wait_before_test(1) - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", - headers={"host": v_s_route_setup.vs_host}) - resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", headers={"host": v_s_route_setup.vs_host}) + resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) assert_responses_and_server_name(resp_1, resp_2, resp_3) events_ns_1 = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) events_ns_2 = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) @@ -122,10 +132,8 @@ def test_responses_and_events_in_flow(self, kube_apis, svc_1.spec.ports[0].port = 8080 replace_service(kube_apis.v1, "backend1-svc", v_s_route_setup.route_m.namespace, svc_1) wait_before_test(1) - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", - headers={"host": v_s_route_setup.vs_host}) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", headers={"host": v_s_route_setup.vs_host}) assert resp_1.status_code == 502 assert resp_2.status_code == 200 events_ns_1 = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) @@ -139,10 +147,8 @@ def test_responses_and_events_in_flow(self, kube_apis, svc_1.spec.ports[0].port = 80 replace_service(kube_apis.v1, "backend1-svc", v_s_route_setup.route_m.namespace, svc_1) wait_before_test(1) - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", - headers={"host": v_s_route_setup.vs_host}) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", headers={"host": v_s_route_setup.vs_host}) assert resp_1.status_code == 200 assert resp_2.status_code == 200 events_ns_1 = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) @@ -154,17 +160,16 @@ def test_responses_and_events_in_flow(self, kube_apis, print("\nStep 6: remove VSRoute and check") delete_v_s_route(kube_apis.custom_objects, v_s_route_setup.route_m.name, v_s_route_setup.namespace) wait_before_test(1) - new_config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", - headers={"host": v_s_route_setup.vs_host}) - resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + new_config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", headers={"host": v_s_route_setup.vs_host}) + resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) assert resp_1.status_code == 404 assert resp_2.status_code == 404 assert resp_3.status_code == 200 @@ -178,21 +183,20 @@ def test_responses_and_events_in_flow(self, kube_apis, assert_event_and_count(vsr_2_event_text, initial_count_vsr_2 + 5, events_ns_2) print("\nStep 7: restore VSRoute and check") - create_v_s_route_from_yaml(kube_apis.custom_objects, - f"{TEST_DATA}/virtual-server-route/route-multiple.yaml", - v_s_route_setup.namespace) + create_v_s_route_from_yaml( + kube_apis.custom_objects, f"{TEST_DATA}/virtual-server-route/route-multiple.yaml", v_s_route_setup.namespace + ) wait_before_test(1) - new_config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", - headers={"host": v_s_route_setup.vs_host}) - resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + new_config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", headers={"host": v_s_route_setup.vs_host}) + resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) assert_responses_and_server_name(resp_1, resp_2, resp_3) events_ns_1 = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) events_ns_2 = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) @@ -204,12 +208,9 @@ def test_responses_and_events_in_flow(self, kube_apis, print("\nStep 8: remove one backend service and check") delete_service(kube_apis.v1, "backend1-svc", v_s_route_setup.route_m.namespace) wait_before_test(1) - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", - headers={"host": v_s_route_setup.vs_host}) - resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", headers={"host": v_s_route_setup.vs_host}) + resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) assert resp_1.status_code == 502 assert resp_2.status_code == 200 assert resp_3.status_code == 200 @@ -222,12 +223,9 @@ def test_responses_and_events_in_flow(self, kube_apis, print("\nStep 9: restore backend service and check") create_service_with_name(kube_apis.v1, v_s_route_setup.route_m.namespace, "backend1-svc") wait_before_test(1) - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", - headers={"host": v_s_route_setup.vs_host}) - resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", headers={"host": v_s_route_setup.vs_host}) + resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) assert_responses_and_server_name(resp_1, resp_2, resp_3) events_ns_1 = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) events_ns_2 = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) @@ -238,12 +236,9 @@ def test_responses_and_events_in_flow(self, kube_apis, print("\nStep 10: remove VS and check") delete_virtual_server(kube_apis.custom_objects, v_s_route_setup.vs_name, v_s_route_setup.namespace) wait_before_test(1) - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", - headers={"host": v_s_route_setup.vs_host}) - resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", headers={"host": v_s_route_setup.vs_host}) + resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) assert resp_1.status_code == 404 assert resp_2.status_code == 404 assert resp_3.status_code == 404 @@ -254,16 +249,15 @@ def test_responses_and_events_in_flow(self, kube_apis, assert_event_and_count(vsr_2_event_text, initial_count_vsr_2 + 8, list0_list_ns_2) print("\nStep 11: restore VS and check") - create_virtual_server_from_yaml(kube_apis.custom_objects, - f"{TEST_DATA}/virtual-server-route/standard/virtual-server.yaml", - v_s_route_setup.namespace) + create_virtual_server_from_yaml( + kube_apis.custom_objects, + f"{TEST_DATA}/virtual-server-route/standard/virtual-server.yaml", + v_s_route_setup.namespace, + ) wait_before_test(1) - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", - headers={"host": v_s_route_setup.vs_host}) - resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", headers={"host": v_s_route_setup.vs_host}) + resp_3 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) assert_responses_and_server_name(resp_1, resp_2, resp_3) list1_list_ns_1 = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) list1_list_ns_2 = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) @@ -273,80 +267,89 @@ def test_responses_and_events_in_flow(self, kube_apis, @pytest.mark.vsr -@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, {"example": "virtual-server-route"})], + indirect=True, +) class TestVirtualServerRouteValidation: - def test_vsr_without_vs(self, kube_apis, - ingress_controller_prerequisites, - crd_ingress_controller, - v_s_route_setup, - test_namespace): + def test_vsr_without_vs( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup, test_namespace + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - vsr_name = create_v_s_route_from_yaml(kube_apis.custom_objects, - f"{TEST_DATA}/virtual-server-route/route-orphan.yaml", - test_namespace) + vsr_name = create_v_s_route_from_yaml( + kube_apis.custom_objects, f"{TEST_DATA}/virtual-server-route/route-orphan.yaml", test_namespace + ) vsr_paths = get_paths_from_vsr_yaml(f"{TEST_DATA}/virtual-server-route/route-orphan.yaml") wait_before_test(1) - new_config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + new_config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) new_list_ns_3 = get_events(kube_apis.v1, test_namespace) assert_locations_not_in_config(new_config, vsr_paths) - assert_event_and_count(f"VirtualServer {v_s_route_setup.namespace}/{v_s_route_setup.vs_name} ignores VirtualServerRoute", 1, new_list_ns_3) + assert_event_and_count( + f"VirtualServer {v_s_route_setup.namespace}/{v_s_route_setup.vs_name} ignores VirtualServerRoute", + 1, + new_list_ns_3, + ) - @pytest.mark.parametrize("route_yaml", [f"{TEST_DATA}/virtual-server-route/route-single-invalid-host.yaml", - f"{TEST_DATA}/virtual-server-route/route-single-duplicate-path.yaml"]) - def test_make_existing_vsr_invalid(self, kube_apis, - ingress_controller_prerequisites, - crd_ingress_controller, - v_s_route_setup, - route_yaml): + @pytest.mark.parametrize( + "route_yaml", + [ + f"{TEST_DATA}/virtual-server-route/route-single-invalid-host.yaml", + f"{TEST_DATA}/virtual-server-route/route-single-duplicate-path.yaml", + ], + ) + def test_make_existing_vsr_invalid( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup, route_yaml + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_s.name, - route_yaml, - v_s_route_setup.route_s.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, v_s_route_setup.route_s.name, route_yaml, v_s_route_setup.route_s.namespace + ) wait_before_test(1) - new_config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + new_config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) new_vs_events = get_events(kube_apis.v1, v_s_route_setup.namespace) new_vsr_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) assert_locations_not_in_config(new_config, v_s_route_setup.route_s.paths) text = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" - assert_event_and_count(f"Configuration for {v_s_route_setup.namespace}/{v_s_route_setup.vs_name} was added or updated with warning(s)", - 1, - new_vs_events) + assert_event_and_count( + f"Configuration for {v_s_route_setup.namespace}/{v_s_route_setup.vs_name} was added or updated with warning(s)", + 1, + new_vs_events, + ) if route_yaml == f"{TEST_DATA}/virtual-server-route/route-single-invalid-host.yaml": - assert_event_and_count(f"VirtualServer is invalid or doesn't exist", - 1, - new_vsr_events) + assert_event_and_count(f"VirtualServer is invalid or doesn't exist", 1, new_vsr_events) else: - assert_event_and_count(f"VirtualServerRoute {text} was rejected with error", - 1, - new_vsr_events) + assert_event_and_count(f"VirtualServerRoute {text} was rejected with error", 1, new_vsr_events) - def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, v_s_route_setup): + def test_openapi_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config_old = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_old = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) route_yaml = f"{TEST_DATA}/virtual-server-route/route-single-invalid-openapi.yaml" try: - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_s.name, - route_yaml, - v_s_route_setup.route_s.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, v_s_route_setup.route_s.name, route_yaml, v_s_route_setup.route_s.namespace + ) except ApiException as ex: assert ex.status == 422 and "action.pass in body must be of type" in ex.body except Exception as ex: @@ -355,49 +358,47 @@ def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisit pytest.fail("Expected an exception but there was none") wait_before_test(1) - config_new = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_new = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert config_old == config_new, "Expected: config doesn't change" @pytest.mark.vsr @pytest.mark.flaky(max_runs=3) -@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, {"example": "virtual-server-route"})], + indirect=True, +) class TestCreateInvalidVirtualServerRoute: - def test_create_invalid_vsr(self, kube_apis, - ingress_controller_prerequisites, - crd_ingress_controller, - v_s_route_setup): + def test_create_invalid_vsr( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup + ): route_yaml = f"{TEST_DATA}/virtual-server-route/route-single-duplicate-path.yaml" ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) text = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" vs_event_text = f"Configuration for {v_s_route_setup.namespace}/{v_s_route_setup.vs_name} was added or updated with warning(s)" - vsr_event_text = f"VirtualServerRoute {text} was rejected with error: spec.subroutes[1].path: Duplicate value: \"/backend2\"" - delete_v_s_route(kube_apis.custom_objects, - v_s_route_setup.route_s.name, - v_s_route_setup.route_s.namespace) + vsr_event_text = ( + f'VirtualServerRoute {text} was rejected with error: spec.subroutes[1].path: Duplicate value: "/backend2"' + ) + delete_v_s_route(kube_apis.custom_objects, v_s_route_setup.route_s.name, v_s_route_setup.route_s.namespace) - create_v_s_route_from_yaml(kube_apis.custom_objects, - route_yaml, - v_s_route_setup.route_s.namespace) + create_v_s_route_from_yaml(kube_apis.custom_objects, route_yaml, v_s_route_setup.route_s.namespace) wait_before_test(1) - new_config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + new_config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) new_vs_events = get_events(kube_apis.v1, v_s_route_setup.namespace) new_vsr_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) assert_locations_not_in_config(new_config, v_s_route_setup.route_s.paths) - assert_event_and_count(vs_event_text, - 1, - new_vs_events) - assert_event_and_count(vsr_event_text, - 1, - new_vsr_events) + assert_event_and_count(vs_event_text, 1, new_vs_events) + assert_event_and_count(vsr_event_text, 1, new_vsr_events) diff --git a/tests/suite/test_v_s_route_advanced_routing.py b/tests/suite/test_v_s_route_advanced_routing.py index cff5eda6e0..fbf9e85043 100644 --- a/tests/suite/test_v_s_route_advanced_routing.py +++ b/tests/suite/test_v_s_route_advanced_routing.py @@ -1,13 +1,21 @@ import pytest import requests - from settings import TEST_DATA -from suite.vs_vsr_resources_utils import create_virtual_server_from_yaml, create_v_s_route_from_yaml, \ - patch_v_s_route_from_yaml from suite.custom_resource_fixtures import VirtualServerRoute -from suite.resources_utils import wait_before_test, ensure_response_from_backend, create_example_app, \ - wait_until_all_pods_are_ready, create_namespace_with_name_from_yaml, delete_namespace -from suite.yaml_utils import get_paths_from_vsr_yaml, get_first_host_from_yaml, get_route_namespace_from_vs_yaml +from suite.resources_utils import ( + create_example_app, + create_namespace_with_name_from_yaml, + delete_namespace, + ensure_response_from_backend, + wait_before_test, + wait_until_all_pods_are_ready, +) +from suite.vs_vsr_resources_utils import ( + create_v_s_route_from_yaml, + create_virtual_server_from_yaml, + patch_v_s_route_from_yaml, +) +from suite.yaml_utils import get_first_host_from_yaml, get_paths_from_vsr_yaml, get_route_namespace_from_vs_yaml def execute_assertions(resp_1, resp_2, resp_3): @@ -46,8 +54,9 @@ def __init__(self, namespace, vs_host, vs_name, route: VirtualServerRoute, backe @pytest.fixture(scope="class") -def vsr_adv_routing_setup(request, kube_apis, - ingress_controller_prerequisites, ingress_controller_endpoint) -> VSRAdvancedRoutingSetup: +def vsr_adv_routing_setup( + request, kube_apis, ingress_controller_prerequisites, ingress_controller_endpoint +) -> VSRAdvancedRoutingSetup: """ Prepare an example app for advanced routing VSR. @@ -60,20 +69,19 @@ def vsr_adv_routing_setup(request, kube_apis, :return: """ vs_routes_ns = get_route_namespace_from_vs_yaml( - f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml") - ns_1 = create_namespace_with_name_from_yaml(kube_apis.v1, - vs_routes_ns[0], - f"{TEST_DATA}/common/ns.yaml") + f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml" + ) + ns_1 = create_namespace_with_name_from_yaml(kube_apis.v1, vs_routes_ns[0], f"{TEST_DATA}/common/ns.yaml") print("------------------------- Deploy Virtual Server -----------------------------------") - vs_name = create_virtual_server_from_yaml(kube_apis.custom_objects, - f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml", - ns_1) + vs_name = create_virtual_server_from_yaml( + kube_apis.custom_objects, f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml", ns_1 + ) vs_host = get_first_host_from_yaml(f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml") print("------------------------- Deploy Virtual Server Route -----------------------------------") - vsr_name = create_v_s_route_from_yaml(kube_apis.custom_objects, - f"{TEST_DATA}/{request.param['example']}/virtual-server-route-header.yaml", - ns_1) + vsr_name = create_v_s_route_from_yaml( + kube_apis.custom_objects, f"{TEST_DATA}/{request.param['example']}/virtual-server-route-header.yaml", ns_1 + ) vsr_paths = get_paths_from_vsr_yaml(f"{TEST_DATA}/{request.param['example']}/virtual-server-route-header.yaml") route = VirtualServerRoute(ns_1, vsr_name, vsr_paths) backends_url = f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.port}{vsr_paths[0]}" @@ -92,57 +100,84 @@ def fin(): @pytest.mark.vsr -@pytest.mark.parametrize('crd_ingress_controller, vsr_adv_routing_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route-advanced-routing"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, vsr_adv_routing_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-route-advanced-routing"}, + ) + ], + indirect=True, +) class TestVSRAdvancedRouting: def test_flow_with_header(self, kube_apis, crd_ingress_controller, vsr_adv_routing_setup): ensure_responses_from_backends(vsr_adv_routing_setup.backends_url, vsr_adv_routing_setup.vs_host) - resp_1 = requests.get(vsr_adv_routing_setup.backends_url, - headers={"host": vsr_adv_routing_setup.vs_host, "x-version": "future"}) - resp_2 = requests.get(vsr_adv_routing_setup.backends_url, - headers={"host": vsr_adv_routing_setup.vs_host, "x-version": "deprecated"}) - resp_3 = requests.get(vsr_adv_routing_setup.backends_url, - headers={"host": vsr_adv_routing_setup.vs_host, "x-version-invalid": "deprecated"}) + resp_1 = requests.get( + vsr_adv_routing_setup.backends_url, headers={"host": vsr_adv_routing_setup.vs_host, "x-version": "future"} + ) + resp_2 = requests.get( + vsr_adv_routing_setup.backends_url, + headers={"host": vsr_adv_routing_setup.vs_host, "x-version": "deprecated"}, + ) + resp_3 = requests.get( + vsr_adv_routing_setup.backends_url, + headers={"host": vsr_adv_routing_setup.vs_host, "x-version-invalid": "deprecated"}, + ) execute_assertions(resp_1, resp_2, resp_3) def test_flow_with_argument(self, kube_apis, crd_ingress_controller, vsr_adv_routing_setup): - patch_v_s_route_from_yaml(kube_apis.custom_objects, - vsr_adv_routing_setup.route.name, - f"{TEST_DATA}/virtual-server-route-advanced-routing/virtual-server-route-argument.yaml", - vsr_adv_routing_setup.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + vsr_adv_routing_setup.route.name, + f"{TEST_DATA}/virtual-server-route-advanced-routing/virtual-server-route-argument.yaml", + vsr_adv_routing_setup.namespace, + ) wait_before_test(1) - resp_1 = requests.get(vsr_adv_routing_setup.backends_url + "?arg1=v1", - headers={"host": vsr_adv_routing_setup.vs_host}) - resp_2 = requests.get(vsr_adv_routing_setup.backends_url + "?arg1=v2", - headers={"host": vsr_adv_routing_setup.vs_host}) - resp_3 = requests.get(vsr_adv_routing_setup.backends_url + "?argument1=v1", - headers={"host": vsr_adv_routing_setup.vs_host}) + resp_1 = requests.get( + vsr_adv_routing_setup.backends_url + "?arg1=v1", headers={"host": vsr_adv_routing_setup.vs_host} + ) + resp_2 = requests.get( + vsr_adv_routing_setup.backends_url + "?arg1=v2", headers={"host": vsr_adv_routing_setup.vs_host} + ) + resp_3 = requests.get( + vsr_adv_routing_setup.backends_url + "?argument1=v1", headers={"host": vsr_adv_routing_setup.vs_host} + ) execute_assertions(resp_1, resp_2, resp_3) def test_flow_with_cookie(self, kube_apis, crd_ingress_controller, vsr_adv_routing_setup): - patch_v_s_route_from_yaml(kube_apis.custom_objects, - vsr_adv_routing_setup.route.name, - f"{TEST_DATA}/virtual-server-route-advanced-routing/virtual-server-route-cookie.yaml", - vsr_adv_routing_setup.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + vsr_adv_routing_setup.route.name, + f"{TEST_DATA}/virtual-server-route-advanced-routing/virtual-server-route-cookie.yaml", + vsr_adv_routing_setup.namespace, + ) wait_before_test(1) - resp_1 = requests.get(vsr_adv_routing_setup.backends_url, - headers={"host": vsr_adv_routing_setup.vs_host}, cookies={"user": "some"}) - resp_2 = requests.get(vsr_adv_routing_setup.backends_url, - headers={"host": vsr_adv_routing_setup.vs_host}, cookies={"user": "bad"}) - resp_3 = requests.get(vsr_adv_routing_setup.backends_url, - headers={"host": vsr_adv_routing_setup.vs_host}, cookies={"user": "anonymous"}) + resp_1 = requests.get( + vsr_adv_routing_setup.backends_url, + headers={"host": vsr_adv_routing_setup.vs_host}, + cookies={"user": "some"}, + ) + resp_2 = requests.get( + vsr_adv_routing_setup.backends_url, headers={"host": vsr_adv_routing_setup.vs_host}, cookies={"user": "bad"} + ) + resp_3 = requests.get( + vsr_adv_routing_setup.backends_url, + headers={"host": vsr_adv_routing_setup.vs_host}, + cookies={"user": "anonymous"}, + ) execute_assertions(resp_1, resp_2, resp_3) def test_flow_with_variable(self, kube_apis, crd_ingress_controller, vsr_adv_routing_setup): - patch_v_s_route_from_yaml(kube_apis.custom_objects, - vsr_adv_routing_setup.route.name, - f"{TEST_DATA}/virtual-server-route-advanced-routing/virtual-server-route-variable.yaml", - vsr_adv_routing_setup.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + vsr_adv_routing_setup.route.name, + f"{TEST_DATA}/virtual-server-route-advanced-routing/virtual-server-route-variable.yaml", + vsr_adv_routing_setup.namespace, + ) wait_before_test(1) resp_1 = requests.get(vsr_adv_routing_setup.backends_url, headers={"host": vsr_adv_routing_setup.vs_host}) @@ -151,19 +186,27 @@ def test_flow_with_variable(self, kube_apis, crd_ingress_controller, vsr_adv_rou execute_assertions(resp_1, resp_2, resp_3) def test_flow_with_complex_conditions(self, kube_apis, crd_ingress_controller, vsr_adv_routing_setup): - patch_v_s_route_from_yaml(kube_apis.custom_objects, - vsr_adv_routing_setup.route.name, - f"{TEST_DATA}/virtual-server-route-advanced-routing/virtual-server-route-complex.yaml", - vsr_adv_routing_setup.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + vsr_adv_routing_setup.route.name, + f"{TEST_DATA}/virtual-server-route-advanced-routing/virtual-server-route-complex.yaml", + vsr_adv_routing_setup.namespace, + ) wait_before_test(1) - resp_1 = requests.get(vsr_adv_routing_setup.backends_url + "?arg1=v1", - headers={"host": vsr_adv_routing_setup.vs_host, - "x-version": "future"}, cookies={"user": "some"}) - resp_2 = requests.post(vsr_adv_routing_setup.backends_url + "?arg1=v2", - headers={"host": vsr_adv_routing_setup.vs_host, - "x-version": "deprecated"}, cookies={"user": "bad"}) - resp_3 = requests.get(vsr_adv_routing_setup.backends_url + "?arg1=v2", - headers={"host": vsr_adv_routing_setup.vs_host, - "x-version": "deprecated"}, cookies={"user": "bad"}) + resp_1 = requests.get( + vsr_adv_routing_setup.backends_url + "?arg1=v1", + headers={"host": vsr_adv_routing_setup.vs_host, "x-version": "future"}, + cookies={"user": "some"}, + ) + resp_2 = requests.post( + vsr_adv_routing_setup.backends_url + "?arg1=v2", + headers={"host": vsr_adv_routing_setup.vs_host, "x-version": "deprecated"}, + cookies={"user": "bad"}, + ) + resp_3 = requests.get( + vsr_adv_routing_setup.backends_url + "?arg1=v2", + headers={"host": vsr_adv_routing_setup.vs_host, "x-version": "deprecated"}, + cookies={"user": "bad"}, + ) execute_assertions(resp_1, resp_2, resp_3) diff --git a/tests/suite/test_v_s_route_api.py b/tests/suite/test_v_s_route_api.py index 93cb65bd64..72f2253a87 100644 --- a/tests/suite/test_v_s_route_api.py +++ b/tests/suite/test_v_s_route_api.py @@ -1,29 +1,40 @@ -import pytest -import requests import json +import pytest +import requests from settings import NGINX_API_VERSION - -from suite.nginx_api_utils import wait_for_empty_array, wait_for_non_empty_array, get_nginx_generation_value +from suite.nginx_api_utils import get_nginx_generation_value, wait_for_empty_array, wait_for_non_empty_array from suite.resources_utils import scale_deployment @pytest.mark.vsr @pytest.mark.skip_for_nginx_oss -@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', - [({"type": "complete", "extra_args": ["-enable-custom-resources", - "-nginx-status-allow-cidrs=0.0.0.0/0,::/0"]}, - {"example": "virtual-server-route-dynamic-configuration"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [ + ( + { + "type": "complete", + "extra_args": ["-enable-custom-resources", "-nginx-status-allow-cidrs=0.0.0.0/0,::/0"], + }, + {"example": "virtual-server-route-dynamic-configuration"}, + ) + ], + indirect=True, +) class TestVSRNginxPlusApi: - def test_dynamic_configuration(self, kube_apis, - ingress_controller_endpoint, crd_ingress_controller, - v_s_route_setup, v_s_route_app_setup): + def test_dynamic_configuration( + self, kube_apis, ingress_controller_endpoint, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup + ): req_url = f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.api_port}" - vsr_s_upstream = f"vs_{v_s_route_setup.namespace}_{v_s_route_setup.vs_name}_" \ + vsr_s_upstream = ( + f"vs_{v_s_route_setup.namespace}_{v_s_route_setup.vs_name}_" f"vsr_{v_s_route_setup.route_s.namespace}_{v_s_route_setup.route_s.name}_backend2" - vsr_m_upstream = f"vs_{v_s_route_setup.namespace}_{v_s_route_setup.vs_name}_" \ + ) + vsr_m_upstream = ( + f"vs_{v_s_route_setup.namespace}_{v_s_route_setup.vs_name}_" f"vsr_{v_s_route_setup.route_m.namespace}_{v_s_route_setup.route_m.name}_backend1" + ) initial_reloads_count = get_nginx_generation_value(req_url) upstream_servers_s_url = f"{req_url}/api/{NGINX_API_VERSION}/http/upstreams/{vsr_s_upstream}/servers" upstream_servers_m_url = f"{req_url}/api/{NGINX_API_VERSION}/http/upstreams/{vsr_m_upstream}/servers" @@ -43,14 +54,14 @@ def test_dynamic_configuration(self, kube_apis, new_reloads_count = get_nginx_generation_value(req_url) assert new_reloads_count == initial_reloads_count, "Expected: no new reloads" for resp in [resp_s, resp_m]: - assert resp[0]['max_conns'] == 32 - assert resp[0]['max_fails'] == 25 - assert resp[0]['fail_timeout'] == '15s' - assert resp[0]['slow_start'] == '10s' + assert resp[0]["max_conns"] == 32 + assert resp[0]["max_fails"] == 25 + assert resp[0]["fail_timeout"] == "15s" + assert resp[0]["slow_start"] == "10s" - def test_status_zone_support(self, kube_apis, - ingress_controller_endpoint, crd_ingress_controller, - v_s_route_setup, v_s_route_app_setup): + def test_status_zone_support( + self, kube_apis, ingress_controller_endpoint, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup + ): req_url = f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.api_port}" status_zone_url = f"{req_url}/api/{NGINX_API_VERSION}/http/server_zones" resp = json.loads(requests.get(status_zone_url).text) diff --git a/tests/suite/test_v_s_route_canned_responses.py b/tests/suite/test_v_s_route_canned_responses.py index 75ea9990cf..fec6db0509 100644 --- a/tests/suite/test_v_s_route_canned_responses.py +++ b/tests/suite/test_v_s_route_canned_responses.py @@ -1,29 +1,41 @@ -import pytest import json + +import pytest import requests from kubernetes.client.rest import ApiException - from settings import TEST_DATA -from suite.custom_assertions import assert_event_and_get_count, wait_and_assert_status_code, \ - assert_event_count_increased, assert_event_starts_with_text_and_contains_errors +from suite.custom_assertions import ( + assert_event_and_get_count, + assert_event_count_increased, + assert_event_starts_with_text_and_contains_errors, + wait_and_assert_status_code, +) +from suite.resources_utils import get_events, get_first_pod_name, wait_before_test from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, patch_v_s_route_from_yaml -from suite.resources_utils import get_first_pod_name, get_events, wait_before_test @pytest.mark.vsr -@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route-canned-responses"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-route-canned-responses"}, + ) + ], + indirect=True, +) class TestVSRCannedResponses: def test_config(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup): wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert "error_page 418 =407" in config and "error_page 418 =200" in config def test_custom_canned_response(self, kube_apis, crd_ingress_controller, v_s_route_setup): @@ -32,38 +44,40 @@ def test_custom_canned_response(self, kube_apis, crd_ingress_controller, v_s_rou wait_and_assert_status_code(407, req_url, v_s_route_setup.vs_host) resp = requests.get(req_url, headers={"host": v_s_route_setup.vs_host}) resp_content = json.loads(resp.content) - assert resp.headers['content-type'] == 'application/json' \ - and resp_content['host'] == v_s_route_setup.vs_host \ - and resp_content['request_time'] != "" \ - and resp_content['pid'] != "" \ - and resp_content['server_protocol'] == "HTTP/1.1" \ - and resp_content['connections_active'] != "" \ - and resp_content['connections_writing'] != "" \ - and resp_content['request_uri'] == f"{v_s_route_setup.route_m.paths[0]}?arg1=arg" \ - and resp_content['remote_addr'] != "" \ - and resp_content['remote_port'] != "" \ - and resp_content['server_addr'] != "" \ - and resp_content['request_method'] == "GET" \ - and resp_content['scheme'] == "http" \ - and resp_content['request_length'] != "" \ - and resp_content['nginx_version'] != "" \ - and resp_content['connection'] != "" \ - and resp_content['time_local'] != "" \ - and resp_content['server_port'] != "" \ - and resp_content['server_name'] == v_s_route_setup.vs_host \ - and resp_content['connections_waiting'] != "" \ - and resp_content['request_body'] == "" \ - and resp_content['args'] == "arg1=arg" \ - and resp_content['time_iso8601'] != "" \ - and resp_content['connections_reading'] != "" + assert ( + resp.headers["content-type"] == "application/json" + and resp_content["host"] == v_s_route_setup.vs_host + and resp_content["request_time"] != "" + and resp_content["pid"] != "" + and resp_content["server_protocol"] == "HTTP/1.1" + and resp_content["connections_active"] != "" + and resp_content["connections_writing"] != "" + and resp_content["request_uri"] == f"{v_s_route_setup.route_m.paths[0]}?arg1=arg" + and resp_content["remote_addr"] != "" + and resp_content["remote_port"] != "" + and resp_content["server_addr"] != "" + and resp_content["request_method"] == "GET" + and resp_content["scheme"] == "http" + and resp_content["request_length"] != "" + and resp_content["nginx_version"] != "" + and resp_content["connection"] != "" + and resp_content["time_local"] != "" + and resp_content["server_port"] != "" + and resp_content["server_name"] == v_s_route_setup.vs_host + and resp_content["connections_waiting"] != "" + and resp_content["request_body"] == "" + and resp_content["args"] == "arg1=arg" + and resp_content["time_iso8601"] != "" + and resp_content["connections_reading"] != "" + ) def test_default_canned_response(self, kube_apis, crd_ingress_controller, v_s_route_setup): req_host = f"{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" req_url = f"http://{req_host}{v_s_route_setup.route_m.paths[1]}" wait_and_assert_status_code(200, req_url, v_s_route_setup.vs_host) resp = requests.get(req_url, headers={"host": v_s_route_setup.vs_host}) - resp_content = resp.content.decode('utf-8') - assert resp.headers['content-type'] == 'text/plain' and resp_content == "line1\nline2\nline3" + resp_content = resp.content.decode("utf-8") + assert resp.headers["content-type"] == "text/plain" and resp_content == "line1\nline2\nline3" def test_update(self, kube_apis, crd_ingress_controller, v_s_route_setup): req_host = f"{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" @@ -78,65 +92,73 @@ def test_update(self, kube_apis, crd_ingress_controller, v_s_route_setup): initial_count_vs = assert_event_and_get_count(vs_event_text, events_ns) initial_count_vsr = assert_event_and_get_count(vsr_event_text, events_ns) vsr_src = f"{TEST_DATA}/virtual-server-route-canned-responses/route-multiple-updated.yaml" - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.namespace + ) wait_and_assert_status_code(501, req_url_1, v_s_route_setup.vs_host) resp = requests.get(req_url_1, headers={"host": v_s_route_setup.vs_host}) - resp_content = resp.content.decode('utf-8') - assert resp.headers['content-type'] == 'some/type' and resp_content == "{}" + resp_content = resp.content.decode("utf-8") + assert resp.headers["content-type"] == "some/type" and resp_content == "{}" wait_and_assert_status_code(201, req_url_2, v_s_route_setup.vs_host) resp = requests.get(req_url_2, headers={"host": v_s_route_setup.vs_host}) - resp_content = resp.content.decode('utf-8') - assert resp.headers['content-type'] == 'user-type' and resp_content == "line1\nline2" + resp_content = resp.content.decode("utf-8") + assert resp.headers["content-type"] == "user-type" and resp_content == "line1\nline2" new_events_ns = get_events(kube_apis.v1, v_s_route_setup.namespace) assert_event_count_increased(vs_event_text, initial_count_vs, new_events_ns) assert_event_count_increased(vsr_event_text, initial_count_vsr, new_events_ns) def test_validation_flow(self, kube_apis, crd_ingress_controller, v_s_route_setup): - invalid_fields = [ - "spec.subroutes[0].action.return.code", "spec.subroutes[0].action.return.body" - ] + invalid_fields = ["spec.subroutes[0].action.return.code", "spec.subroutes[0].action.return.body"] req_host = f"{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" req_url = f"http://{req_host}{v_s_route_setup.route_s.paths[0]}" text = f"{v_s_route_setup.namespace}/{v_s_route_setup.route_m.name}" vsr_m_event_text = f"VirtualServerRoute {text} was rejected with error:" vsr_src = f"{TEST_DATA}/virtual-server-route-canned-responses/route-multiple-invalid.yaml" - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.namespace + ) wait_before_test(1) wait_and_assert_status_code(404, req_url, v_s_route_setup.vs_host) events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) assert_event_starts_with_text_and_contains_errors(vsr_m_event_text, events, invalid_fields) - def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, v_s_route_setup): + def test_openapi_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config_old = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_old = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) vsr_src = f"{TEST_DATA}/virtual-server-route-canned-responses/route-multiple-invalid-openapi.yaml" try: - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.namespace + ) except ApiException as ex: - assert ex.status == 422 \ - and "action.return.type in body must be of type" in ex.body \ - and "action.return.body in body must be of type" in ex.body \ - and "action.return.code in body must be of type" in ex.body + assert ( + ex.status == 422 + and "action.return.type in body must be of type" in ex.body + and "action.return.body in body must be of type" in ex.body + and "action.return.code in body must be of type" in ex.body + ) except Exception as ex: pytest.fail(f"An unexpected exception is raised: {ex}") else: pytest.fail("Expected an exception but there was none") wait_before_test(1) - config_new = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_new = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert config_old == config_new, "Expected: config doesn't change" diff --git a/tests/suite/test_v_s_route_error_pages.py b/tests/suite/test_v_s_route_error_pages.py index 1fb6ea0d3e..4c9bfa5cad 100644 --- a/tests/suite/test_v_s_route_error_pages.py +++ b/tests/suite/test_v_s_route_error_pages.py @@ -1,95 +1,120 @@ -import requests -import pytest import json +import pytest +import requests from kubernetes.client.rest import ApiException - from settings import TEST_DATA -from suite.custom_assertions import wait_and_assert_status_code, \ - assert_event_starts_with_text_and_contains_errors -from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, patch_v_s_route_from_yaml, \ - patch_virtual_server_from_yaml -from suite.resources_utils import get_first_pod_name, get_events, wait_before_test +from suite.custom_assertions import assert_event_starts_with_text_and_contains_errors, wait_and_assert_status_code +from suite.resources_utils import get_events, get_first_pod_name, wait_before_test +from suite.vs_vsr_resources_utils import ( + get_vs_nginx_template_conf, + patch_v_s_route_from_yaml, + patch_virtual_server_from_yaml, +) @pytest.mark.vsr -@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route-error-pages"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-route-error-pages"}, + ) + ], + indirect=True, +) class TestVSRErrorPages: - def test_redirect_strategy(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - v_s_route_setup): + def test_redirect_strategy( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup + ): req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" - wait_and_assert_status_code(307, f"{req_url}{v_s_route_setup.route_m.paths[0]}", - v_s_route_setup.vs_host, allow_redirects=False) - resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}, allow_redirects=False) - assert f'http://{v_s_route_setup.vs_host}/error.html' in resp.next.url + wait_and_assert_status_code( + 307, f"{req_url}{v_s_route_setup.route_m.paths[0]}", v_s_route_setup.vs_host, allow_redirects=False + ) + resp = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers={"host": v_s_route_setup.vs_host}, + allow_redirects=False, + ) + assert f"http://{v_s_route_setup.vs_host}/error.html" in resp.next.url - def test_return_strategy(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - v_s_route_setup): + def test_return_strategy( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup + ): req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" wait_and_assert_status_code(207, f"{req_url}{v_s_route_setup.route_m.paths[1]}", v_s_route_setup.vs_host) - resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", - headers={"host": v_s_route_setup.vs_host}) + resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", headers={"host": v_s_route_setup.vs_host}) resp_content = json.loads(resp.content) - assert resp_content['status'] == '502' \ - and resp_content['message'] == 'Forbidden' \ - and resp.headers.get('x-debug-original-status') == '502' + assert ( + resp_content["status"] == "502" + and resp_content["message"] == "Forbidden" + and resp.headers.get("x-debug-original-status") == "502" + ) - def test_virtual_server_after_update(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - v_s_route_setup): + def test_virtual_server_after_update( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup + ): req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, - f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple-updated.yaml", - v_s_route_setup.route_m.namespace) - wait_and_assert_status_code(301, f"{req_url}{v_s_route_setup.route_m.paths[0]}", - v_s_route_setup.vs_host, allow_redirects=False) - resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host, "x-forwarded-proto": "http"}, - allow_redirects=False) - assert f'http://{v_s_route_setup.vs_host}/error_http.html' in resp.next.url + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_m.name, + f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple-updated.yaml", + v_s_route_setup.route_m.namespace, + ) + wait_and_assert_status_code( + 301, f"{req_url}{v_s_route_setup.route_m.paths[0]}", v_s_route_setup.vs_host, allow_redirects=False + ) + resp = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers={"host": v_s_route_setup.vs_host, "x-forwarded-proto": "http"}, + allow_redirects=False, + ) + assert f"http://{v_s_route_setup.vs_host}/error_http.html" in resp.next.url - wait_and_assert_status_code(502, f"{req_url}{v_s_route_setup.route_m.paths[1]}", - v_s_route_setup.vs_host, allow_redirects=False) - resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", - headers={"host": v_s_route_setup.vs_host}) - resp_content = resp.content.decode('utf-8') - assert resp_content == 'Hello World!\n' + wait_and_assert_status_code( + 502, f"{req_url}{v_s_route_setup.route_m.paths[1]}", v_s_route_setup.vs_host, allow_redirects=False + ) + resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}", headers={"host": v_s_route_setup.vs_host}) + resp_content = resp.content.decode("utf-8") + assert resp_content == "Hello World!\n" - def test_validation_event_flow(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - v_s_route_setup): + def test_validation_event_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup + ): invalid_fields_m = [ "spec.subroutes[0].errorPages[0].redirect.url: Invalid value", "spec.subroutes[0].errorPages[0].redirect.code: Invalid value: 101", - "spec.subroutes[1].errorPages[0].return.body: Invalid value: \"status\"", + 'spec.subroutes[1].errorPages[0].return.body: Invalid value: "status"', "spec.subroutes[1].errorPages[0].return.code: Invalid value: 100", - "spec.subroutes[1].errorPages[0].return.headers[0].value: Invalid value: \"schema\"" - ] - invalid_fields_s = [ - "spec.subroutes[0].errorPages[0].redirect.url: Required value: must specify a url" + 'spec.subroutes[1].errorPages[0].return.headers[0].value: Invalid value: "schema"', ] + invalid_fields_s = ["spec.subroutes[0].errorPages[0].redirect.url: Required value: must specify a url"] text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" vsr_s_event_text = f"VirtualServerRoute {text_s} was rejected with error:" vsr_m_event_text = f"VirtualServerRoute {text_m} was rejected with error:" - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_s.name, - f"{TEST_DATA}/virtual-server-route-error-pages/route-single-invalid.yaml", - v_s_route_setup.route_s.namespace) - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, - f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple-invalid.yaml", - v_s_route_setup.route_m.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_s.name, + f"{TEST_DATA}/virtual-server-route-error-pages/route-single-invalid.yaml", + v_s_route_setup.route_s.namespace, + ) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_m.name, + f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple-invalid.yaml", + v_s_route_setup.route_m.namespace, + ) wait_before_test(2) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) @@ -97,74 +122,99 @@ def test_validation_event_flow(self, kube_apis, ingress_controller_prerequisites assert_event_starts_with_text_and_contains_errors(vsr_m_event_text, vsr_m_events, invalid_fields_m) assert "upstream" not in config - def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, v_s_route_setup): + def test_openapi_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config_old = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_old = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) vsr_src = f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple-invalid-openapi.yaml" try: - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, - vsr_src, - v_s_route_setup.route_m.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.route_m.namespace + ) except ApiException as ex: - assert ex.status == 422 \ - and "codes in body must be of type" in ex.body \ - and "redirect.code in body must be of type" in ex.body \ - and "redirect.url in body must be of type" in ex.body \ - and "return.code in body must be of type" in ex.body \ - and "return.type in body must be of type" in ex.body \ - and "return.body in body must be of type" in ex.body \ - and "name in body must be of type" in ex.body \ - and "value in body must be of type" in ex.body + assert ( + ex.status == 422 + and "codes in body must be of type" in ex.body + and "redirect.code in body must be of type" in ex.body + and "redirect.url in body must be of type" in ex.body + and "return.code in body must be of type" in ex.body + and "return.type in body must be of type" in ex.body + and "return.body in body must be of type" in ex.body + and "name in body must be of type" in ex.body + and "value in body must be of type" in ex.body + ) except Exception as ex: pytest.fail(f"An unexpected exception is raised: {ex}") else: pytest.fail("Expected an exception but there was none") wait_before_test(1) - config_new = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_new = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert config_old == config_new, "Expected: config doesn't change" - @pytest.mark.parametrize('v_s_r_data', [ - {"src": "route-multiple-splits.yaml", "expected_code": 308}, - {"src": "route-multiple-matches.yaml", "expected_code": 307} - ]) - def test_splits_and_matches(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - v_s_route_setup, v_s_r_data): + @pytest.mark.parametrize( + "v_s_r_data", + [ + {"src": "route-multiple-splits.yaml", "expected_code": 308}, + {"src": "route-multiple-matches.yaml", "expected_code": 307}, + ], + ) + def test_splits_and_matches( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup, v_s_r_data + ): req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, - f"{TEST_DATA}/virtual-server-route-error-pages/{v_s_r_data['src']}", - v_s_route_setup.route_m.namespace) - wait_and_assert_status_code(v_s_r_data["expected_code"], f"{req_url}{v_s_route_setup.route_m.paths[0]}", - v_s_route_setup.vs_host, allow_redirects=False) - resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}, allow_redirects=False) - assert f'http://{v_s_route_setup.vs_host}/error.html' in resp.next.url + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_m.name, + f"{TEST_DATA}/virtual-server-route-error-pages/{v_s_r_data['src']}", + v_s_route_setup.route_m.namespace, + ) + wait_and_assert_status_code( + v_s_r_data["expected_code"], + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + v_s_route_setup.vs_host, + allow_redirects=False, + ) + resp = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers={"host": v_s_route_setup.vs_host}, + allow_redirects=False, + ) + assert f"http://{v_s_route_setup.vs_host}/error.html" in resp.next.url - def test_vsr_overrides_vs(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - v_s_route_setup): + def test_vsr_overrides_vs( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup + ): req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" vs_src = f"{TEST_DATA}/virtual-server-route-error-pages/standard/virtual-server-updated.yaml" - patch_virtual_server_from_yaml(kube_apis.custom_objects, - v_s_route_setup.vs_name, - vs_src, - v_s_route_setup.namespace) - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, - f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple.yaml", - v_s_route_setup.route_m.namespace) - wait_and_assert_status_code(307, f"{req_url}{v_s_route_setup.route_m.paths[0]}", - v_s_route_setup.vs_host, allow_redirects=False) - resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}, allow_redirects=False) - assert f'http://{v_s_route_setup.vs_host}/error.html' in resp.next.url + patch_virtual_server_from_yaml( + kube_apis.custom_objects, v_s_route_setup.vs_name, vs_src, v_s_route_setup.namespace + ) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_m.name, + f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple.yaml", + v_s_route_setup.route_m.namespace, + ) + wait_and_assert_status_code( + 307, f"{req_url}{v_s_route_setup.route_m.paths[0]}", v_s_route_setup.vs_host, allow_redirects=False + ) + resp = requests.get( + f"{req_url}{v_s_route_setup.route_m.paths[0]}", + headers={"host": v_s_route_setup.vs_host}, + allow_redirects=False, + ) + assert f"http://{v_s_route_setup.vs_host}/error.html" in resp.next.url diff --git a/tests/suite/test_v_s_route_externalname.py b/tests/suite/test_v_s_route_externalname.py index e7043e7ba0..873b4f2172 100644 --- a/tests/suite/test_v_s_route_externalname.py +++ b/tests/suite/test_v_s_route_externalname.py @@ -1,17 +1,34 @@ import pytest - from settings import TEST_DATA -from suite.custom_assertions import assert_event_and_count, assert_event_and_get_count, wait_and_assert_status_code, \ - wait_for_event_count_increases -from suite.vs_vsr_resources_utils import create_virtual_server_from_yaml, \ - create_v_s_route_from_yaml, get_vs_nginx_template_conf -from suite.fixtures import PublicEndpoint +from suite.custom_assertions import ( + assert_event_and_count, + assert_event_and_get_count, + wait_and_assert_status_code, + wait_for_event_count_increases, +) from suite.custom_resource_fixtures import VirtualServerRoute -from suite.resources_utils import get_first_pod_name, get_events, \ - wait_before_test, replace_configmap_from_yaml, create_service_from_yaml, \ - delete_namespace, create_namespace_with_name_from_yaml, read_service, replace_service, replace_configmap, \ - create_service_with_name, create_deployment_with_name, ensure_response_from_backend -from suite.yaml_utils import get_paths_from_vsr_yaml, get_route_namespace_from_vs_yaml, get_first_host_from_yaml +from suite.fixtures import PublicEndpoint +from suite.resources_utils import ( + create_deployment_with_name, + create_namespace_with_name_from_yaml, + create_service_from_yaml, + create_service_with_name, + delete_namespace, + ensure_response_from_backend, + get_events, + get_first_pod_name, + read_service, + replace_configmap, + replace_configmap_from_yaml, + replace_service, + wait_before_test, +) +from suite.vs_vsr_resources_utils import ( + create_v_s_route_from_yaml, + create_virtual_server_from_yaml, + get_vs_nginx_template_conf, +) +from suite.yaml_utils import get_first_host_from_yaml, get_paths_from_vsr_yaml, get_route_namespace_from_vs_yaml class ReducedVirtualServerRouteSetup: @@ -26,8 +43,16 @@ class ReducedVirtualServerRouteSetup: route (VirtualServerRoute): route with single subroute """ - def __init__(self, public_endpoint: PublicEndpoint, - namespace, vs_host, vs_name, route: VirtualServerRoute, external_svc, external_host): + def __init__( + self, + public_endpoint: PublicEndpoint, + namespace, + vs_host, + vs_name, + route: VirtualServerRoute, + external_svc, + external_host, + ): self.public_endpoint = public_endpoint self.namespace = namespace self.vs_host = vs_host @@ -38,9 +63,9 @@ def __init__(self, public_endpoint: PublicEndpoint, @pytest.fixture(scope="class") -def vsr_externalname_setup(request, kube_apis, - ingress_controller_prerequisites, - ingress_controller_endpoint) -> ReducedVirtualServerRouteSetup: +def vsr_externalname_setup( + request, kube_apis, ingress_controller_prerequisites, ingress_controller_endpoint +) -> ReducedVirtualServerRouteSetup: """ Prepare an example app for Virtual Server Route. @@ -53,36 +78,39 @@ def vsr_externalname_setup(request, kube_apis, :return: """ vs_routes_ns = get_route_namespace_from_vs_yaml( - f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml") - ns_1 = create_namespace_with_name_from_yaml(kube_apis.v1, - vs_routes_ns[0], - f"{TEST_DATA}/common/ns.yaml") + f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml" + ) + ns_1 = create_namespace_with_name_from_yaml(kube_apis.v1, vs_routes_ns[0], f"{TEST_DATA}/common/ns.yaml") print("------------------------- Deploy External-Backend -----------------------------------") external_ns = create_namespace_with_name_from_yaml(kube_apis.v1, "external-ns", f"{TEST_DATA}/common/ns.yaml") external_svc_name = create_service_with_name(kube_apis.v1, external_ns, "external-backend-svc") create_deployment_with_name(kube_apis.apps_v1_api, external_ns, "external-backend") print("------------------------- Deploy Virtual Server -----------------------------------") - vs_name = create_virtual_server_from_yaml(kube_apis.custom_objects, - f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml", - ns_1) + vs_name = create_virtual_server_from_yaml( + kube_apis.custom_objects, f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml", ns_1 + ) vs_host = get_first_host_from_yaml(f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml") print("------------------------- Deploy Virtual Server Route -----------------------------------") - vsr_name = create_v_s_route_from_yaml(kube_apis.custom_objects, - f"{TEST_DATA}/{request.param['example']}/route-single.yaml", - ns_1) + vsr_name = create_v_s_route_from_yaml( + kube_apis.custom_objects, f"{TEST_DATA}/{request.param['example']}/route-single.yaml", ns_1 + ) vsr_paths = get_paths_from_vsr_yaml(f"{TEST_DATA}/{request.param['example']}/route-single.yaml") route = VirtualServerRoute(ns_1, vsr_name, vsr_paths) print("---------------------- Deploy ExternalName service and update ConfigMap ----------------------------") config_map_name = ingress_controller_prerequisites.config_map["metadata"]["name"] - replace_configmap_from_yaml(kube_apis.v1, config_map_name, - ingress_controller_prerequisites.namespace, - f"{TEST_DATA}/{request.param['example']}/nginx-config.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + config_map_name, + ingress_controller_prerequisites.namespace, + f"{TEST_DATA}/{request.param['example']}/nginx-config.yaml", + ) external_svc_host = f"{external_svc_name}.{external_ns}.svc.cluster.local" - svc_name = create_service_from_yaml(kube_apis.v1, - ns_1, f"{TEST_DATA}/{request.param['example']}/externalname-svc.yaml") + svc_name = create_service_from_yaml( + kube_apis.v1, ns_1, f"{TEST_DATA}/{request.param['example']}/externalname-svc.yaml" + ) wait_before_test(2) req_url = f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.port}" ensure_response_from_backend(f"{req_url}{route.paths[0]}", vs_host) @@ -94,47 +122,60 @@ def fin(): request.addfinalizer(fin) - return ReducedVirtualServerRouteSetup(ingress_controller_endpoint, - ns_1, vs_host, vs_name, route, svc_name, external_svc_host) + return ReducedVirtualServerRouteSetup( + ingress_controller_endpoint, ns_1, vs_host, vs_name, route, svc_name, external_svc_host + ) + @pytest.mark.vsr @pytest.mark.skip_for_nginx_oss -@pytest.mark.parametrize('crd_ingress_controller, vsr_externalname_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route-externalname"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, vsr_externalname_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-route-externalname"}, + ) + ], + indirect=True, +) class TestVSRWithExternalNameService: - def test_responses(self, kube_apis, - crd_ingress_controller, - vsr_externalname_setup): - req_url = f"http://{vsr_externalname_setup.public_endpoint.public_ip}:" \ + def test_responses(self, kube_apis, crd_ingress_controller, vsr_externalname_setup): + req_url = ( + f"http://{vsr_externalname_setup.public_endpoint.public_ip}:" f"{vsr_externalname_setup.public_endpoint.port}" - wait_and_assert_status_code(200, f"{req_url}{vsr_externalname_setup.route.paths[0]}", - vsr_externalname_setup.vs_host) - - def test_template_config(self, kube_apis, - ingress_controller_prerequisites, - crd_ingress_controller, - vsr_externalname_setup): + ) + wait_and_assert_status_code( + 200, f"{req_url}{vsr_externalname_setup.route.paths[0]}", vsr_externalname_setup.vs_host + ) + + def test_template_config( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, vsr_externalname_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - initial_config = get_vs_nginx_template_conf(kube_apis.v1, - vsr_externalname_setup.namespace, - vsr_externalname_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - - line = f"zone vs_{vsr_externalname_setup.namespace}_{vsr_externalname_setup.vs_name}" \ + initial_config = get_vs_nginx_template_conf( + kube_apis.v1, + vsr_externalname_setup.namespace, + vsr_externalname_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + + line = ( + f"zone vs_{vsr_externalname_setup.namespace}_{vsr_externalname_setup.vs_name}" f"_vsr_{vsr_externalname_setup.route.namespace}_{vsr_externalname_setup.route.name}_ext-backend 512k;" + ) assert line in initial_config assert "random two least_conn;" in initial_config - assert f"server {vsr_externalname_setup.external_host}:80 max_fails=1 fail_timeout=10s max_conns=0 resolve;"\ - in initial_config + assert ( + f"server {vsr_externalname_setup.external_host}:80 max_fails=1 fail_timeout=10s max_conns=0 resolve;" + in initial_config + ) @pytest.mark.xfail - def test_events_flows(self, kube_apis, - ingress_controller_prerequisites, - crd_ingress_controller, - vsr_externalname_setup): + def test_events_flows( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, vsr_externalname_setup + ): text_vsr = f"{vsr_externalname_setup.route.namespace}/{vsr_externalname_setup.route.name}" text_vs = f"{vsr_externalname_setup.namespace}/{vsr_externalname_setup.vs_name}" vsr_event_text = f"Configuration for {text_vsr} was added or updated" @@ -149,21 +190,26 @@ def test_events_flows(self, kube_apis, print("Step 1: Update external host in externalName service") external_svc = read_service(kube_apis.v1, vsr_externalname_setup.external_svc, vsr_externalname_setup.namespace) external_svc.spec.external_name = "demo.nginx.com" - replace_service(kube_apis.v1, - vsr_externalname_setup.external_svc, vsr_externalname_setup.namespace, external_svc) + replace_service( + kube_apis.v1, vsr_externalname_setup.external_svc, vsr_externalname_setup.namespace, external_svc + ) wait_before_test(10) - wait_for_event_count_increases(kube_apis, vsr_event_text, - initial_count_vsr, vsr_externalname_setup.route.namespace) + wait_for_event_count_increases( + kube_apis, vsr_event_text, initial_count_vsr, vsr_externalname_setup.route.namespace + ) events_step_1 = get_events(kube_apis.v1, vsr_externalname_setup.route.namespace) assert_event_and_count(vsr_event_text, initial_count_vsr + 1, events_step_1) assert_event_and_count(vs_event_text, initial_count_vs + 1, events_step_1) print("Step 2: Remove resolver from ConfigMap to trigger an error") config_map_name = ingress_controller_prerequisites.config_map["metadata"]["name"] - replace_configmap(kube_apis.v1, config_map_name, - ingress_controller_prerequisites.namespace, - ingress_controller_prerequisites.config_map) + replace_configmap( + kube_apis.v1, + config_map_name, + ingress_controller_prerequisites.namespace, + ingress_controller_prerequisites.config_map, + ) wait_before_test(10) events_step_2 = get_events(kube_apis.v1, vsr_externalname_setup.route.namespace) diff --git a/tests/suite/test_v_s_route_focused_canary.py b/tests/suite/test_v_s_route_focused_canary.py index 0839429147..6a640ff4d5 100644 --- a/tests/suite/test_v_s_route_focused_canary.py +++ b/tests/suite/test_v_s_route_focused_canary.py @@ -1,14 +1,18 @@ import pytest import requests import yaml - -from yaml.loader import Loader from settings import TEST_DATA -from suite.vs_vsr_resources_utils import create_virtual_server_from_yaml, create_v_s_route_from_yaml from suite.custom_resource_fixtures import VirtualServerRoute -from suite.resources_utils import ensure_response_from_backend, create_example_app, \ - wait_until_all_pods_are_ready, create_namespace_with_name_from_yaml, delete_namespace -from suite.yaml_utils import get_paths_from_vsr_yaml, get_first_host_from_yaml, get_route_namespace_from_vs_yaml +from suite.resources_utils import ( + create_example_app, + create_namespace_with_name_from_yaml, + delete_namespace, + ensure_response_from_backend, + wait_until_all_pods_are_ready, +) +from suite.vs_vsr_resources_utils import create_v_s_route_from_yaml, create_virtual_server_from_yaml +from suite.yaml_utils import get_first_host_from_yaml, get_paths_from_vsr_yaml, get_route_namespace_from_vs_yaml +from yaml.loader import Loader def get_weights_of_splitting(file) -> []: @@ -22,8 +26,8 @@ def get_weights_of_splitting(file) -> []: with open(file) as f: docs = yaml.load_all(f, Loader=Loader) for dep in docs: - for item in dep['spec']['subroutes'][0]['matches'][0]['splits']: - weights.append(item['weight']) + for item in dep["spec"]["subroutes"][0]["matches"][0]["splits"]: + weights.append(item["weight"]) return weights @@ -38,8 +42,8 @@ def get_upstreams_of_splitting(file) -> []: with open(file) as f: docs = yaml.load_all(f, Loader=Loader) for dep in docs: - for item in dep['spec']['subroutes'][0]['matches'][0]['splits']: - upstreams.append(item['action']['pass']) + for item in dep["spec"]["subroutes"][0]["matches"][0]["splits"]: + upstreams.append(item["action"]["pass"]) return upstreams @@ -64,8 +68,9 @@ def __init__(self, namespace, vs_host, vs_name, route: VirtualServerRoute, backe @pytest.fixture(scope="class") -def vsr_canary_setup(request, kube_apis, - ingress_controller_prerequisites, ingress_controller_endpoint) -> VSRAdvancedRoutingSetup: +def vsr_canary_setup( + request, kube_apis, ingress_controller_prerequisites, ingress_controller_endpoint +) -> VSRAdvancedRoutingSetup: """ Prepare an example app for advanced routing VSR. @@ -78,20 +83,19 @@ def vsr_canary_setup(request, kube_apis, :return: """ vs_routes_ns = get_route_namespace_from_vs_yaml( - f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml") - ns_1 = create_namespace_with_name_from_yaml(kube_apis.v1, - vs_routes_ns[0], - f"{TEST_DATA}/common/ns.yaml") + f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml" + ) + ns_1 = create_namespace_with_name_from_yaml(kube_apis.v1, vs_routes_ns[0], f"{TEST_DATA}/common/ns.yaml") print("------------------------- Deploy Virtual Server -----------------------------------") - vs_name = create_virtual_server_from_yaml(kube_apis.custom_objects, - f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml", - ns_1) + vs_name = create_virtual_server_from_yaml( + kube_apis.custom_objects, f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml", ns_1 + ) vs_host = get_first_host_from_yaml(f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml") print("------------------------- Deploy Virtual Server Route -----------------------------------") - vsr_name = create_v_s_route_from_yaml(kube_apis.custom_objects, - f"{TEST_DATA}/{request.param['example']}/virtual-server-route.yaml", - ns_1) + vsr_name = create_v_s_route_from_yaml( + kube_apis.custom_objects, f"{TEST_DATA}/{request.param['example']}/virtual-server-route.yaml", ns_1 + ) vsr_paths = get_paths_from_vsr_yaml(f"{TEST_DATA}/{request.param['example']}/virtual-server-route.yaml") route = VirtualServerRoute(ns_1, vsr_name, vsr_paths) backends_url = f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.port}{vsr_paths[0]}" @@ -111,25 +115,32 @@ def fin(): @pytest.mark.flaky(max_runs=3) @pytest.mark.vsr -@pytest.mark.parametrize('crd_ingress_controller, vsr_canary_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route-focused-canary"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, vsr_canary_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-route-focused-canary"}, + ) + ], + indirect=True, +) class TestVSRFocusedCanaryRelease: def test_flow_with_header(self, kube_apis, crd_ingress_controller, vsr_canary_setup): ensure_response_from_backend(vsr_canary_setup.backends_url, vsr_canary_setup.vs_host) - weights = get_weights_of_splitting( - f"{TEST_DATA}/virtual-server-route-focused-canary/virtual-server-route.yaml") + weights = get_weights_of_splitting(f"{TEST_DATA}/virtual-server-route-focused-canary/virtual-server-route.yaml") upstreams = get_upstreams_of_splitting( - f"{TEST_DATA}/virtual-server-route-focused-canary/virtual-server-route.yaml") + f"{TEST_DATA}/virtual-server-route-focused-canary/virtual-server-route.yaml" + ) sum_weights = sum(weights) - ratios = [round(i/sum_weights, 1) for i in weights] + ratios = [round(i / sum_weights, 1) for i in weights] counter_v1, counter_v2 = 0, 0 for _ in range(100): - resp = requests.get(vsr_canary_setup.backends_url, - headers={"host": vsr_canary_setup.vs_host, "x-version": "canary"}) + resp = requests.get( + vsr_canary_setup.backends_url, headers={"host": vsr_canary_setup.vs_host, "x-version": "canary"} + ) if upstreams[0] in resp.text in resp.text: counter_v1 = counter_v1 + 1 elif upstreams[1] in resp.text in resp.text: @@ -137,5 +148,5 @@ def test_flow_with_header(self, kube_apis, crd_ingress_controller, vsr_canary_se else: pytest.fail(f"An unexpected backend in response: {resp.text}") - assert abs(round(counter_v1/(counter_v1 + counter_v2), 1) - ratios[0]) <= 0.2 - assert abs(round(counter_v2/(counter_v1 + counter_v2), 1) - ratios[1]) <= 0.2 + assert abs(round(counter_v1 / (counter_v1 + counter_v2), 1) - ratios[0]) <= 0.2 + assert abs(round(counter_v2 / (counter_v1 + counter_v2), 1) - ratios[1]) <= 0.2 diff --git a/tests/suite/test_v_s_route_grpc.py b/tests/suite/test_v_s_route_grpc.py index f8e8c24b3e..55116d5d36 100644 --- a/tests/suite/test_v_s_route_grpc.py +++ b/tests/suite/test_v_s_route_grpc.py @@ -1,20 +1,29 @@ import grpc import pytest from kubernetes.client.rest import ApiException - -from settings import TEST_DATA, DEPLOYMENTS -from suite.custom_assertions import assert_event_starts_with_text_and_contains_errors, \ - assert_grpc_entries_exist, assert_proxy_entries_do_not_exist, assert_proxy_entries_exist +from settings import DEPLOYMENTS, TEST_DATA +from suite.custom_assertions import ( + assert_event_starts_with_text_and_contains_errors, + assert_grpc_entries_exist, + assert_proxy_entries_do_not_exist, + assert_proxy_entries_exist, +) from suite.custom_resources_utils import read_custom_resource from suite.grpc.helloworld_pb2 import HelloRequest from suite.grpc.helloworld_pb2_grpc import GreeterStub -from suite.resources_utils import create_example_app, wait_until_all_pods_are_ready, \ - delete_common_app, create_secret_from_yaml, replace_configmap_from_yaml, \ - delete_items_from_yaml, get_first_pod_name, get_events +from suite.resources_utils import ( + create_example_app, + create_secret_from_yaml, + delete_common_app, + delete_items_from_yaml, + get_events, + get_first_pod_name, + replace_configmap_from_yaml, + wait_before_test, + wait_until_all_pods_are_ready, +) from suite.ssl_utils import get_certificate -from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, \ - patch_v_s_route_from_yaml -from suite.resources_utils import wait_before_test +from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, patch_v_s_route_from_yaml @pytest.fixture(scope="function") @@ -30,41 +39,48 @@ def backend_setup(request, kube_apis, ingress_controller_prerequisites, test_nam try: print("------------------------- Replace ConfigMap with HTTP2 -------------------------") cm_source = f"{TEST_DATA}/virtual-server-route-grpc/nginx-config.yaml" - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - cm_source) + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + cm_source, + ) print("------------------------- Deploy App -----------------------------") app_name = request.param.get("app_type") create_example_app(kube_apis, app_name, test_namespace) wait_until_all_pods_are_ready(kube_apis.v1, test_namespace) except Exception as ex: print("Failed to complete setup, cleaning up..") - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - f"{DEPLOYMENTS}/common/nginx-config.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + f"{DEPLOYMENTS}/common/nginx-config.yaml", + ) delete_common_app(kube_apis, app_name, test_namespace) pytest.fail(f"VSR GRPC setup failed") def fin(): print("Clean up:") - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - f"{DEPLOYMENTS}/common/nginx-config.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + f"{DEPLOYMENTS}/common/nginx-config.yaml", + ) delete_common_app(kube_apis, app_name, test_namespace) request.addfinalizer(fin) + @pytest.mark.vsr @pytest.mark.smoke -@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route-grpc"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, {"example": "virtual-server-route-grpc"})], + indirect=True, +) class TestVirtualServerRouteGrpc: - def patch_valid_vs_route(self, kube_apis, v_s_route_setup) -> None: """ Function to revert vs deployment to valid state @@ -88,43 +104,54 @@ def deploy_tls_secrets(self, kube_apis, v_s_route_setup) -> None: wait_before_test(1) @pytest.mark.parametrize("backend_setup", [{"app_type": "grpc-vs"}], indirect=True) - def test_config_after_setup(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - backend_setup, v_s_route_setup): + def test_config_after_setup( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, v_s_route_setup + ): self.deploy_tls_secrets(kube_apis, v_s_route_setup) print("\nStep 1: assert config") ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert_proxy_entries_do_not_exist(config) assert_grpc_entries_exist(config) @pytest.mark.parametrize("backend_setup", [{"app_type": "grpc-vs"}], indirect=True) - def test_config_after_enable_tls(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, backend_setup, v_s_route_setup): + def test_config_after_enable_tls( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, v_s_route_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, - f"{TEST_DATA}/virtual-server-route-grpc/route-updated.yaml", - v_s_route_setup.route_m.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_m.name, + f"{TEST_DATA}/virtual-server-route-grpc/route-updated.yaml", + v_s_route_setup.route_m.namespace, + ) wait_before_test() - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - assert 'grpc_pass grpcs://' in config + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + assert "grpc_pass grpcs://" in config @pytest.mark.parametrize("backend_setup", [{"app_type": "grpc-vs"}], indirect=True) - def test_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, backend_setup, v_s_route_setup): + def test_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, v_s_route_setup + ): print("\nTest 1: Wrong type") - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, - f"{TEST_DATA}/virtual-server-route-grpc/route-invalid-type.yaml", - v_s_route_setup.route_m.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_m.name, + f"{TEST_DATA}/virtual-server-route-grpc/route-invalid-type.yaml", + v_s_route_setup.route_m.namespace, + ) wait_before_test() text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" vsr_m_event_text = f"VirtualServerRoute {text_m} was rejected with error:" @@ -136,18 +163,23 @@ def test_validation_flow(self, kube_apis, ingress_controller_prerequisites, wait_before_test() @pytest.mark.parametrize("backend_setup", [{"app_type": "grpc-vs-mixed"}], indirect=True) - def test_mixed_config(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - backend_setup, v_s_route_setup): - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, - f"{TEST_DATA}/virtual-server-route-grpc/route-multiple-mixed.yaml", - v_s_route_setup.route_m.namespace) + def test_mixed_config( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, v_s_route_setup + ): + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_m.name, + f"{TEST_DATA}/virtual-server-route-grpc/route-multiple-mixed.yaml", + v_s_route_setup.route_m.namespace, + ) wait_before_test() ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert_proxy_entries_exist(config) assert_grpc_entries_exist(config) diff --git a/tests/suite/test_v_s_route_redirects.py b/tests/suite/test_v_s_route_redirects.py index 9c740a6baf..3c9d1f6758 100644 --- a/tests/suite/test_v_s_route_redirects.py +++ b/tests/suite/test_v_s_route_redirects.py @@ -1,43 +1,54 @@ import pytest import requests from kubernetes.client.rest import ApiException - from settings import TEST_DATA -from suite.custom_assertions import assert_event_and_get_count, wait_and_assert_status_code, \ - assert_event_count_increased, assert_event_starts_with_text_and_contains_errors +from suite.custom_assertions import ( + assert_event_and_get_count, + assert_event_count_increased, + assert_event_starts_with_text_and_contains_errors, + wait_and_assert_status_code, +) +from suite.resources_utils import get_events, get_first_pod_name, wait_before_test from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, patch_v_s_route_from_yaml -from suite.resources_utils import get_first_pod_name, get_events, wait_before_test @pytest.mark.vsr -@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route-redirects"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-route-redirects"}, + ) + ], + indirect=True, +) class TestVSRRedirects: def test_config(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup): wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - assert 'error_page 418 =307' in config and 'error_page 418 =301' in config + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + assert "error_page 418 =307" in config and "error_page 418 =301" in config def test_custom_redirect(self, kube_apis, crd_ingress_controller, v_s_route_setup): req_host = f"{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" req_url = f"http://{req_host}{v_s_route_setup.route_m.paths[0]}?arg1=arg" wait_and_assert_status_code(307, req_url, v_s_route_setup.vs_host, allow_redirects=False) resp = requests.get(req_url, headers={"host": v_s_route_setup.vs_host}, allow_redirects=False) - assert resp.headers['location'] == "http://example.com" + assert resp.headers["location"] == "http://example.com" def test_default_redirect(self, kube_apis, crd_ingress_controller, v_s_route_setup): req_host = f"{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" req_url = f"http://{req_host}{v_s_route_setup.route_m.paths[1]}" wait_and_assert_status_code(301, req_url, v_s_route_setup.vs_host, allow_redirects=False) resp = requests.get(req_url, headers={"host": v_s_route_setup.vs_host}, allow_redirects=False) - assert resp.headers['location'] == f"http://{v_s_route_setup.vs_host}/backends/default-redirect?arg=" + assert resp.headers["location"] == f"http://{v_s_route_setup.vs_host}/backends/default-redirect?arg=" def test_update(self, kube_apis, crd_ingress_controller, v_s_route_setup): req_host = f"{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" @@ -52,15 +63,16 @@ def test_update(self, kube_apis, crd_ingress_controller, v_s_route_setup): initial_count_vs = assert_event_and_get_count(vs_event_text, events_ns) initial_count_vsr = assert_event_and_get_count(vsr_event_text, events_ns) vsr_src = f"{TEST_DATA}/virtual-server-route-redirects/route-multiple-updated.yaml" - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.namespace + ) wait_and_assert_status_code(301, req_url_1, v_s_route_setup.vs_host, allow_redirects=False) resp = requests.get(req_url_1, headers={"host": v_s_route_setup.vs_host}, allow_redirects=False) - assert resp.headers['location'] == "http://demo.nginx.com" + assert resp.headers["location"] == "http://demo.nginx.com" wait_and_assert_status_code(302, req_url_2, v_s_route_setup.vs_host, allow_redirects=False) resp = requests.get(req_url_2, headers={"host": v_s_route_setup.vs_host}, allow_redirects=False) - assert resp.headers['location'] == "http://demo.nginx.com" + assert resp.headers["location"] == "http://demo.nginx.com" new_events_ns = get_events(kube_apis.v1, v_s_route_setup.namespace) assert_event_count_increased(vs_event_text, initial_count_vs, new_events_ns) @@ -71,43 +83,50 @@ def test_validation_flow(self, kube_apis, crd_ingress_controller, v_s_route_setu req_url = f"http://{req_host}{v_s_route_setup.route_s.paths[0]}" text = f"{v_s_route_setup.namespace}/{v_s_route_setup.route_m.name}" event_text = f"VirtualServerRoute {text} was rejected with error:" - invalid_fields = [ - "spec.subroutes[0].action.redirect.code", "spec.subroutes[1].action.redirect.url" - ] + invalid_fields = ["spec.subroutes[0].action.redirect.code", "spec.subroutes[1].action.redirect.url"] vsr_src = f"{TEST_DATA}/virtual-server-route-redirects/route-multiple-invalid.yaml" - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.namespace + ) wait_before_test(2) wait_and_assert_status_code(404, req_url, v_s_route_setup.vs_host, allow_redirects=False) events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) assert_event_starts_with_text_and_contains_errors(event_text, events, invalid_fields) - def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, v_s_route_setup): + def test_openapi_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config_old = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_old = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) vsr_src = f"{TEST_DATA}/virtual-server-route-redirects/route-multiple-invalid-openapi.yaml" try: - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, v_s_route_setup.route_m.name, vsr_src, v_s_route_setup.namespace + ) except ApiException as ex: - assert ex.status == 422 \ - and "action.redirect.url in body must be of type" in ex.body \ - and "action.redirect.code in body must be of type" in ex.body + assert ( + ex.status == 422 + and "action.redirect.url in body must be of type" in ex.body + and "action.redirect.code in body must be of type" in ex.body + ) except Exception as ex: pytest.fail(f"An unexpected exception is raised: {ex}") else: pytest.fail("Expected an exception but there was none") wait_before_test(1) - config_new = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_new = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert config_old == config_new, "Expected: config doesn't change" diff --git a/tests/suite/test_v_s_route_regexp_location.py b/tests/suite/test_v_s_route_regexp_location.py index 2357a33b02..6586d03e8c 100644 --- a/tests/suite/test_v_s_route_regexp_location.py +++ b/tests/suite/test_v_s_route_regexp_location.py @@ -1,54 +1,101 @@ -import requests import pytest - +import requests from settings import TEST_DATA from suite.custom_assertions import assert_event, assert_vs_conf_not_exists -from suite.vs_vsr_resources_utils import patch_v_s_route_from_yaml, patch_virtual_server_from_yaml, \ - get_vs_nginx_template_conf, create_virtual_server_from_yaml, create_v_s_route_from_yaml -from suite.resources_utils import wait_before_test, get_events, get_first_pod_name, \ - create_example_app, wait_until_all_pods_are_ready, ensure_response_from_backend +from suite.resources_utils import ( + create_example_app, + ensure_response_from_backend, + get_events, + get_first_pod_name, + wait_before_test, + wait_until_all_pods_are_ready, +) +from suite.vs_vsr_resources_utils import ( + create_v_s_route_from_yaml, + create_virtual_server_from_yaml, + get_vs_nginx_template_conf, + patch_v_s_route_from_yaml, + patch_virtual_server_from_yaml, +) from suite.yaml_utils import get_first_host_from_yaml @pytest.mark.vsr -@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route-regexp-location"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-route-regexp-location"}, + ) + ], + indirect=True, +) class TestRegexpLocation: - @pytest.mark.parametrize('test_data', [ - pytest.param({"regex_type": "exact", - "expected_results": {"/exact-match$request": 200, - "/exact-match$request/": 404, - "/exact-match$request?var1=value": 200}}, id="exact"), - pytest.param({"regex_type": "case-sensitive", - "expected_results": {"/case-SENsitiVe/match": 200, - "/case-sensitive/match/": 404, - "/case-SENsitiVe/match/": 200}}, id="case-sensitive"), - pytest.param({"regex_type": "case-insensitive", - "expected_results": {"/case-inSENsitiVe/match": 200, - "/case-insensitive/match/": 200, - "/case-inSENsitiVe/match/": 200}}, id="case-insensitive") - ]) - def test_response_for_regex_location(self, kube_apis, - ingress_controller_prerequisites, crd_ingress_controller, - v_s_route_setup, v_s_route_app_setup, test_data): + @pytest.mark.parametrize( + "test_data", + [ + pytest.param( + { + "regex_type": "exact", + "expected_results": { + "/exact-match$request": 200, + "/exact-match$request/": 404, + "/exact-match$request?var1=value": 200, + }, + }, + id="exact", + ), + pytest.param( + { + "regex_type": "case-sensitive", + "expected_results": { + "/case-SENsitiVe/match": 200, + "/case-sensitive/match/": 404, + "/case-SENsitiVe/match/": 200, + }, + }, + id="case-sensitive", + ), + pytest.param( + { + "regex_type": "case-insensitive", + "expected_results": { + "/case-inSENsitiVe/match": 200, + "/case-insensitive/match/": 200, + "/case-inSENsitiVe/match/": 200, + }, + }, + id="case-insensitive", + ), + ], + ) + def test_response_for_regex_location( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + v_s_route_setup, + v_s_route_app_setup, + test_data, + ): req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" - vs_src_yaml = f"{TEST_DATA}" \ - f"/virtual-server-route-regexp-location/standard/virtual-server-{test_data['regex_type']}.yaml" + vs_src_yaml = ( + f"{TEST_DATA}" + f"/virtual-server-route-regexp-location/standard/virtual-server-{test_data['regex_type']}.yaml" + ) vsr_src_yaml = f"{TEST_DATA}/virtual-server-route-regexp-location/route-single-{test_data['regex_type']}.yaml" - patch_virtual_server_from_yaml(kube_apis.custom_objects, v_s_route_setup.vs_name, - vs_src_yaml, - v_s_route_setup.namespace) - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_s.name, - vsr_src_yaml, - v_s_route_setup.route_s.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, v_s_route_setup.vs_name, vs_src_yaml, v_s_route_setup.namespace + ) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, v_s_route_setup.route_s.name, vsr_src_yaml, v_s_route_setup.route_s.namespace + ) wait_before_test(1) - for item in test_data['expected_results']: + for item in test_data["expected_results"]: uri = item - expected_code = test_data['expected_results'][uri] + expected_code = test_data["expected_results"][uri] ensure_response_from_backend(f"{req_url}{uri}", v_s_route_setup.vs_host) resp = requests.get(f"{req_url}{uri}", headers={"host": v_s_route_setup.vs_host}) if expected_code == 200: @@ -56,51 +103,59 @@ def test_response_for_regex_location(self, kube_apis, else: assert resp.status_code == expected_code, "Expected 404 for URI that doesn't match" - def test_flow_for_invalid_vs(self, kube_apis, - ingress_controller_prerequisites, crd_ingress_controller, - v_s_route_setup, v_s_route_app_setup): + def test_flow_for_invalid_vs( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) text_vs = f"{v_s_route_setup.namespace}/{v_s_route_setup.vs_name}" - vs_event_text = f'VirtualServer {text_vs} was rejected with error: ' \ - f'spec.routes[1].path: Duplicate value: "=/exact-match$request"' - vs_src_yaml = f"{TEST_DATA}" \ - f"/virtual-server-route-regexp-location/standard/virtual-server-invalid-duplicate-routes.yaml" - patch_virtual_server_from_yaml(kube_apis.custom_objects, v_s_route_setup.vs_name, - vs_src_yaml, - v_s_route_setup.namespace) + vs_event_text = ( + f"VirtualServer {text_vs} was rejected with error: " + f'spec.routes[1].path: Duplicate value: "=/exact-match$request"' + ) + vs_src_yaml = ( + f"{TEST_DATA}" + f"/virtual-server-route-regexp-location/standard/virtual-server-invalid-duplicate-routes.yaml" + ) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, v_s_route_setup.vs_name, vs_src_yaml, v_s_route_setup.namespace + ) wait_before_test(2) vs_events = get_events(kube_apis.v1, v_s_route_setup.namespace) assert_vs_conf_not_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, v_s_route_setup) assert_event(vs_event_text, vs_events) - def test_flow_for_invalid_vsr(self, kube_apis, - ingress_controller_prerequisites, crd_ingress_controller, - v_s_route_setup, v_s_route_app_setup): + def test_flow_for_invalid_vsr( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) text_vs = f"{v_s_route_setup.namespace}/{v_s_route_setup.vs_name}" text_vsr_s = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" - vs_event_text = f'Configuration for {text_vs} was added or updated with warning(s)' - vsr_event_text = f'VirtualServerRoute {text_vsr_s} was rejected with error: ' \ - f'spec.subroutes[1].path: Duplicate value: "=/backends/exact-match$request"' - vs_src_yaml = f"{TEST_DATA}" \ - f"/virtual-server-route-regexp-location/standard/virtual-server-exact.yaml" - patch_virtual_server_from_yaml(kube_apis.custom_objects, v_s_route_setup.vs_name, - vs_src_yaml, - v_s_route_setup.namespace) - vsr_src_yaml = f"{TEST_DATA}" \ - f"/virtual-server-route-regexp-location/route-multiple-invalid-multiple-regexp-subroutes.yaml" - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, - vsr_src_yaml, - v_s_route_setup.route_m.namespace) + vs_event_text = f"Configuration for {text_vs} was added or updated with warning(s)" + vsr_event_text = ( + f"VirtualServerRoute {text_vsr_s} was rejected with error: " + f'spec.subroutes[1].path: Duplicate value: "=/backends/exact-match$request"' + ) + vs_src_yaml = f"{TEST_DATA}" f"/virtual-server-route-regexp-location/standard/virtual-server-exact.yaml" + patch_virtual_server_from_yaml( + kube_apis.custom_objects, v_s_route_setup.vs_name, vs_src_yaml, v_s_route_setup.namespace + ) + vsr_src_yaml = ( + f"{TEST_DATA}" + f"/virtual-server-route-regexp-location/route-multiple-invalid-multiple-regexp-subroutes.yaml" + ) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, v_s_route_setup.route_m.name, vsr_src_yaml, v_s_route_setup.route_m.namespace + ) wait_before_test(2) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) ns_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) assert_event(vsr_event_text, ns_events) and assert_event(vs_event_text, ns_events) assert "location =/backends/exact-match$request {" not in config @@ -123,8 +178,9 @@ def __init__(self, namespace, vs_host, vs_name): @pytest.fixture(scope="class") -def vsr_regexp_setup(request, kube_apis, - ingress_controller_prerequisites, ingress_controller_endpoint, test_namespace) -> VSRRegexpSetup: +def vsr_regexp_setup( + request, kube_apis, ingress_controller_prerequisites, ingress_controller_endpoint, test_namespace +) -> VSRRegexpSetup: """ Prepare an example app for advanced routing VSR. @@ -143,10 +199,12 @@ def vsr_regexp_setup(request, kube_apis, vs_host = get_first_host_from_yaml(vs_src_yaml) print("------------------------- Deploy VSRs -----------------------------------") - for item in ['prefix', 'exact', 'regexp']: - create_v_s_route_from_yaml(kube_apis.custom_objects, - f"{TEST_DATA}/{request.param['example']}/additional-case/route-{item}.yaml", - test_namespace) + for item in ["prefix", "exact", "regexp"]: + create_v_s_route_from_yaml( + kube_apis.custom_objects, + f"{TEST_DATA}/{request.param['example']}/additional-case/route-{item}.yaml", + test_namespace, + ) print("---------------------- Deploy simple app ----------------------------") create_example_app(kube_apis, "extended", test_namespace) @@ -156,28 +214,46 @@ def vsr_regexp_setup(request, kube_apis, @pytest.mark.vsr -@pytest.mark.parametrize('crd_ingress_controller, vsr_regexp_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route-regexp-location"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, vsr_regexp_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-route-regexp-location"}, + ) + ], + indirect=True, +) class TestVSRRegexpMultipleMatches: - def test_exact_match_overrides_all(self, kube_apis, - ingress_controller_prerequisites, ingress_controller_endpoint, - crd_ingress_controller, vsr_regexp_setup): + def test_exact_match_overrides_all( + self, + kube_apis, + ingress_controller_prerequisites, + ingress_controller_endpoint, + crd_ingress_controller, + vsr_regexp_setup, + ): req_url = f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.port}" ensure_response_from_backend(f"{req_url}/backends/match", vsr_regexp_setup.vs_host) resp = requests.get(f"{req_url}/backends/match", headers={"host": vsr_regexp_setup.vs_host}) assert resp.status_code == 200 and "Server name: backend2-" in resp.text - def test_regexp_overrides_prefix(self, kube_apis, - ingress_controller_prerequisites, ingress_controller_endpoint, - crd_ingress_controller, vsr_regexp_setup): + def test_regexp_overrides_prefix( + self, + kube_apis, + ingress_controller_prerequisites, + ingress_controller_endpoint, + crd_ingress_controller, + vsr_regexp_setup, + ): req_url = f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.port}" - vs_src_yaml = f"{TEST_DATA}" \ - f"/virtual-server-route-regexp-location/additional-case/virtual-server-regexp-over-prefix.yaml" - patch_virtual_server_from_yaml(kube_apis.custom_objects, vsr_regexp_setup.vs_name, - vs_src_yaml, - vsr_regexp_setup.namespace) + vs_src_yaml = ( + f"{TEST_DATA}" + f"/virtual-server-route-regexp-location/additional-case/virtual-server-regexp-over-prefix.yaml" + ) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, vsr_regexp_setup.vs_name, vs_src_yaml, vsr_regexp_setup.namespace + ) wait_before_test(1) ensure_response_from_backend(f"{req_url}/backends/match", vsr_regexp_setup.vs_host) resp = requests.get(f"{req_url}/backends/match", headers={"host": vsr_regexp_setup.vs_host}) diff --git a/tests/suite/test_v_s_route_split_traffic.py b/tests/suite/test_v_s_route_split_traffic.py index fa009c5da9..f0f39c1315 100644 --- a/tests/suite/test_v_s_route_split_traffic.py +++ b/tests/suite/test_v_s_route_split_traffic.py @@ -1,11 +1,10 @@ -from yaml.loader import Loader import pytest import requests import yaml - from settings import TEST_DATA from suite.resources_utils import ensure_response_from_backend from suite.yaml_utils import get_paths_from_vsr_yaml +from yaml.loader import Loader def get_weights_of_splitting(file) -> []: @@ -19,8 +18,8 @@ def get_weights_of_splitting(file) -> []: with open(file) as f: docs = yaml.load_all(f, Loader=Loader) for dep in docs: - for item in dep['spec']['subroutes'][0]['splits']: - weights.append(item['weight']) + for item in dep["spec"]["subroutes"][0]["splits"]: + weights.append(item["weight"]) return weights @@ -35,32 +34,37 @@ def get_upstreams_of_splitting(file) -> []: with open(file) as f: docs = yaml.load_all(f, Loader=Loader) for dep in docs: - for item in dep['spec']['subroutes'][0]['splits']: - upstreams.append(item['action']['pass']) + for item in dep["spec"]["subroutes"][0]["splits"]: + upstreams.append(item["action"]["pass"]) return upstreams @pytest.mark.vsr -@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route-split-traffic"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-route-split-traffic"}, + ) + ], + indirect=True, +) class TestVSRTrafficSplitting: def test_several_requests(self, kube_apis, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup): split_path = get_paths_from_vsr_yaml(f"{TEST_DATA}/virtual-server-route-split-traffic/route-multiple.yaml") - req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}{split_path[0]}" + req_url = ( + f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}{split_path[0]}" + ) ensure_response_from_backend(req_url, v_s_route_setup.vs_host) - weights = get_weights_of_splitting( - f"{TEST_DATA}/virtual-server-route-split-traffic/route-multiple.yaml") - upstreams = get_upstreams_of_splitting( - f"{TEST_DATA}/virtual-server-route-split-traffic/route-multiple.yaml") + weights = get_weights_of_splitting(f"{TEST_DATA}/virtual-server-route-split-traffic/route-multiple.yaml") + upstreams = get_upstreams_of_splitting(f"{TEST_DATA}/virtual-server-route-split-traffic/route-multiple.yaml") sum_weights = sum(weights) - ratios = [round(i/sum_weights, 1) for i in weights] + ratios = [round(i / sum_weights, 1) for i in weights] counter_v1, counter_v2 = 0, 0 for _ in range(100): - resp = requests.get(req_url, - headers={"host": v_s_route_setup.vs_host}) + resp = requests.get(req_url, headers={"host": v_s_route_setup.vs_host}) if resp.status_code == 502: print("Backend is not ready yet, skip.") if upstreams[0] in resp.text in resp.text: @@ -70,5 +74,5 @@ def test_several_requests(self, kube_apis, crd_ingress_controller, v_s_route_set else: pytest.fail(f"An unexpected response: {resp.text}") - assert abs(round(counter_v1/(counter_v1 + counter_v2), 1) - ratios[0]) <= 0.2 - assert abs(round(counter_v2/(counter_v1 + counter_v2), 1) - ratios[1]) <= 0.2 + assert abs(round(counter_v1 / (counter_v1 + counter_v2), 1) - ratios[0]) <= 0.2 + assert abs(round(counter_v2 / (counter_v1 + counter_v2), 1) - ratios[1]) <= 0.2 diff --git a/tests/suite/test_v_s_route_status.py b/tests/suite/test_v_s_route_status.py index 18152ac7bb..42deac3791 100644 --- a/tests/suite/test_v_s_route_status.py +++ b/tests/suite/test_v_s_route_status.py @@ -1,23 +1,25 @@ import pytest from kubernetes.client.rest import ApiException +from settings import TEST_DATA +from suite.custom_resources_utils import read_custom_resource from suite.resources_utils import wait_before_test -from suite.custom_resources_utils import ( - read_custom_resource, -) from suite.vs_vsr_resources_utils import ( - patch_virtual_server_from_yaml, - patch_v_s_route_from_yaml, - delete_virtual_server, create_virtual_server_from_yaml, + delete_virtual_server, + patch_v_s_route_from_yaml, + patch_virtual_server_from_yaml, ) -from settings import TEST_DATA + @pytest.mark.vsr @pytest.mark.parametrize( "crd_ingress_controller, v_s_route_setup", [ ( - {"type": "complete", "extra_args": [f"-enable-custom-resources", f"-enable-leader-election=false"],}, + { + "type": "complete", + "extra_args": [f"-enable-custom-resources", f"-enable-leader-election=false"], + }, {"example": "virtual-server-route-status"}, ) ], @@ -51,14 +53,15 @@ def patch_valid_vs(self, kube_apis, v_s_route_setup) -> None: """ patch_src = f"{TEST_DATA}/virtual-server-route-status/standard/virtual-server.yaml" patch_virtual_server_from_yaml( - kube_apis.custom_objects, v_s_route_setup.vs_name, patch_src, v_s_route_setup.namespace, + kube_apis.custom_objects, + v_s_route_setup.vs_name, + patch_src, + v_s_route_setup.namespace, ) wait_before_test() @pytest.mark.smoke - def test_status_valid( - self, kube_apis, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup - ): + def test_status_valid(self, kube_apis, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup): """ Test VirtualServerRoute status with a valid fields in yaml """ @@ -88,9 +91,7 @@ def test_status_valid( and response_s["status"]["state"] == "Valid" ) - def test_status_invalid( - self, kube_apis, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup - ): + def test_status_invalid(self, kube_apis, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup): """ Test VirtualServerRoute status with a invalid paths in vsr yaml """ @@ -138,10 +139,8 @@ def test_status_invalid( and not response_s["status"]["referencedBy"] and response_s["status"]["state"] == "Invalid" ) - - def test_status_invalid_prefix( - self, kube_apis, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup - ): + + def test_status_invalid_prefix(self, kube_apis, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup): """ Test VirtualServerRoute status with a invalid path /prefix in vsr yaml i.e. referring to non-existing path @@ -191,16 +190,17 @@ def test_status_invalid_prefix( and response_s["status"]["state"] == "Warning" ) - def test_status_invalid_vsr_in_vs( - self, kube_apis, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup - ): + def test_status_invalid_vsr_in_vs(self, kube_apis, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup): """ Test VirtualServerRoute status with invalid vsr reference in vs yaml """ patch_src = f"{TEST_DATA}/virtual-server-route-status/virtual-server-invalid.yaml" patch_virtual_server_from_yaml( - kube_apis.custom_objects, v_s_route_setup.vs_name, patch_src, v_s_route_setup.namespace, + kube_apis.custom_objects, + v_s_route_setup.vs_name, + patch_src, + v_s_route_setup.namespace, ) wait_before_test() @@ -231,14 +231,14 @@ def test_status_invalid_vsr_in_vs( and response_s["status"]["state"] == "Warning" ) - def test_status_remove_vs( - self, kube_apis, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup - ): + def test_status_remove_vs(self, kube_apis, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup): """ Test VirtualServerRoute status after deleting referenced VirtualServer """ delete_virtual_server( - kube_apis.custom_objects, v_s_route_setup.vs_name, v_s_route_setup.namespace, + kube_apis.custom_objects, + v_s_route_setup.vs_name, + v_s_route_setup.namespace, ) response_m = read_custom_resource( diff --git a/tests/suite/test_v_s_route_upstream_options.py b/tests/suite/test_v_s_route_upstream_options.py index 573d17ed63..4882809f64 100644 --- a/tests/suite/test_v_s_route_upstream_options.py +++ b/tests/suite/test_v_s_route_upstream_options.py @@ -1,32 +1,44 @@ import pytest import requests from kubernetes.client.rest import ApiException - from settings import TEST_DATA -from suite.custom_assertions import assert_event_and_get_count, assert_event_count_increased, assert_response_codes, \ - assert_event, assert_event_starts_with_text_and_contains_errors, wait_for_event_count_increases -from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, patch_v_s_route_from_yaml, patch_v_s_route -from suite.custom_resources_utils import ( - generate_item_with_upstream_options, +from suite.custom_assertions import ( + assert_event, + assert_event_and_get_count, + assert_event_count_increased, + assert_event_starts_with_text_and_contains_errors, + assert_response_codes, + wait_for_event_count_increases, +) +from suite.custom_resources_utils import generate_item_with_upstream_options +from suite.resources_utils import get_events, get_first_pod_name, replace_configmap_from_yaml, wait_before_test +from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, patch_v_s_route, patch_v_s_route_from_yaml + + +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-route-upstream-options"}, + ) + ], + indirect=True, ) -from suite.resources_utils import get_first_pod_name, wait_before_test, replace_configmap_from_yaml, get_events - - -@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route-upstream-options"})], - indirect=True) @pytest.mark.vsr class TestVSRouteUpstreamOptions: - def test_nginx_config_upstreams_defaults(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, v_s_route_setup, v_s_route_app_setup): + def test_nginx_config_upstreams_defaults( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup, v_s_route_app_setup + ): print("Case 1: no ConfigMap keys, no options in VS") ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert "random two least_conn;" in config assert "ip_hash;" not in config @@ -42,7 +54,7 @@ def test_nginx_config_upstreams_defaults(self, kube_apis, ingress_controller_pre assert "keepalive" not in config assert 'set $default_connection_header "";' not in config - assert 'set $default_connection_header close;' in config + assert "set $default_connection_header close;" in config assert "proxy_set_header Upgrade $http_upgrade;" in config assert "proxy_set_header Connection $vs_connection_header;" in config assert "proxy_http_version 1.1;" in config @@ -59,29 +71,72 @@ def test_nginx_config_upstreams_defaults(self, kube_apis, ingress_controller_pre assert "sticky cookie" not in config - @pytest.mark.parametrize('options, expected_strings', [ - ({"lb-method": "least_conn", "max-fails": 8, - "fail-timeout": "13s", "connect-timeout": "55s", "read-timeout": "1s", "send-timeout": "1h", - "keepalive": 54, "max-conns": 1024, "client-max-body-size": "1048K", - "buffering": True, "buffer-size": "2k", "buffers": {"number": 4, "size": "2k"}}, - ["least_conn;", "max_fails=8 ", - "fail_timeout=13s ", "proxy_connect_timeout 55s;", "proxy_read_timeout 1s;", - "proxy_send_timeout 1h;", "keepalive 54;", 'set $default_connection_header "";', "max_conns=1024;", - "client_max_body_size 1048K;", - "proxy_buffering on;", "proxy_buffer_size 2k;", "proxy_buffers 4 2k;"]), - ({"lb-method": "ip_hash", "connect-timeout": "75", "read-timeout": "15", "send-timeout": "1h"}, - ["ip_hash;", "proxy_connect_timeout 75s;", "proxy_read_timeout 15s;", "proxy_send_timeout 1h;"]), - ({"connect-timeout": "1m", "read-timeout": "1m", "send-timeout": "1s"}, - ["proxy_connect_timeout 1m;", "proxy_read_timeout 1m;", "proxy_send_timeout 1s;"]), - ({"next-upstream": "error timeout non_idempotent", "next-upstream-timeout": "5s", "next-upstream-tries": 10}, - ["proxy_next_upstream error timeout non_idempotent;", - "proxy_next_upstream_timeout 5s;", "proxy_next_upstream_tries 10;"]) - ]) - def test_when_option_in_v_s_r_only(self, kube_apis, - ingress_controller_prerequisites, - crd_ingress_controller, - v_s_route_setup, v_s_route_app_setup, - options, expected_strings): + @pytest.mark.parametrize( + "options, expected_strings", + [ + ( + { + "lb-method": "least_conn", + "max-fails": 8, + "fail-timeout": "13s", + "connect-timeout": "55s", + "read-timeout": "1s", + "send-timeout": "1h", + "keepalive": 54, + "max-conns": 1024, + "client-max-body-size": "1048K", + "buffering": True, + "buffer-size": "2k", + "buffers": {"number": 4, "size": "2k"}, + }, + [ + "least_conn;", + "max_fails=8 ", + "fail_timeout=13s ", + "proxy_connect_timeout 55s;", + "proxy_read_timeout 1s;", + "proxy_send_timeout 1h;", + "keepalive 54;", + 'set $default_connection_header "";', + "max_conns=1024;", + "client_max_body_size 1048K;", + "proxy_buffering on;", + "proxy_buffer_size 2k;", + "proxy_buffers 4 2k;", + ], + ), + ( + {"lb-method": "ip_hash", "connect-timeout": "75", "read-timeout": "15", "send-timeout": "1h"}, + ["ip_hash;", "proxy_connect_timeout 75s;", "proxy_read_timeout 15s;", "proxy_send_timeout 1h;"], + ), + ( + {"connect-timeout": "1m", "read-timeout": "1m", "send-timeout": "1s"}, + ["proxy_connect_timeout 1m;", "proxy_read_timeout 1m;", "proxy_send_timeout 1s;"], + ), + ( + { + "next-upstream": "error timeout non_idempotent", + "next-upstream-timeout": "5s", + "next-upstream-tries": 10, + }, + [ + "proxy_next_upstream error timeout non_idempotent;", + "proxy_next_upstream_timeout 5s;", + "proxy_next_upstream_tries 10;", + ], + ), + ], + ) + def test_when_option_in_v_s_r_only( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + v_s_route_setup, + v_s_route_app_setup, + options, + expected_strings, + ): req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" @@ -93,82 +148,123 @@ def test_when_option_in_v_s_r_only(self, kube_apis, initial_count_vsr_s = assert_event_and_get_count(vsr_s_event_text, events_ns_s) print(f"Case 2: no key in ConfigMap, option specified in VSR") new_body_m = generate_item_with_upstream_options( - f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", - options) + f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", options + ) new_body_s = generate_item_with_upstream_options( - f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", - options) - patch_v_s_route(kube_apis.custom_objects, - v_s_route_setup.route_m.name, v_s_route_setup.route_m.namespace, new_body_m) - patch_v_s_route(kube_apis.custom_objects, - v_s_route_setup.route_s.name, v_s_route_setup.route_s.namespace, new_body_s) + f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", options + ) + patch_v_s_route( + kube_apis.custom_objects, v_s_route_setup.route_m.name, v_s_route_setup.route_m.namespace, new_body_m + ) + patch_v_s_route( + kube_apis.custom_objects, v_s_route_setup.route_s.name, v_s_route_setup.route_s.namespace, new_body_s + ) wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - - wait_for_event_count_increases(kube_apis, vsr_s_event_text, - initial_count_vsr_s, v_s_route_setup.route_s.namespace) - wait_for_event_count_increases(kube_apis, vsr_m_event_text, - initial_count_vsr_m, v_s_route_setup.route_m.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + + wait_for_event_count_increases( + kube_apis, vsr_s_event_text, initial_count_vsr_s, v_s_route_setup.route_s.namespace + ) + wait_for_event_count_increases( + kube_apis, vsr_m_event_text, initial_count_vsr_m, v_s_route_setup.route_m.namespace + ) for _ in expected_strings: assert _ in config assert_response_codes(resp_1, resp_2) - @pytest.mark.parametrize('config_map_file, expected_strings, unexpected_strings', [ - (f"{TEST_DATA}/virtual-server-route-upstream-options/configmap-with-keys.yaml", - ["max_fails=3 ", "fail_timeout=33s ", "max_conns=0;", - "proxy_connect_timeout 44s;", "proxy_read_timeout 22s;", "proxy_send_timeout 55s;", - "keepalive 1024;", 'set $default_connection_header "";', - "client_max_body_size 3m;", - "proxy_buffering off;", "proxy_buffer_size 1k;", "proxy_buffers 8 1k;"], - ["ip_hash;", "least_conn;", "random ", "hash", "least_time ", - "max_fails=1 ", "fail_timeout=10s ", "max_conns=1000;", - "proxy_connect_timeout 60s;", "proxy_read_timeout 60s;", "proxy_send_timeout 60s;", - "client_max_body_size 1m;", - "slow_start=0s", - "proxy_buffering on;"]), - ]) - def test_when_option_in_config_map_only(self, kube_apis, - ingress_controller_prerequisites, - crd_ingress_controller, - v_s_route_setup, v_s_route_app_setup, restore_configmap, - config_map_file, expected_strings, unexpected_strings): + @pytest.mark.parametrize( + "config_map_file, expected_strings, unexpected_strings", + [ + ( + f"{TEST_DATA}/virtual-server-route-upstream-options/configmap-with-keys.yaml", + [ + "max_fails=3 ", + "fail_timeout=33s ", + "max_conns=0;", + "proxy_connect_timeout 44s;", + "proxy_read_timeout 22s;", + "proxy_send_timeout 55s;", + "keepalive 1024;", + 'set $default_connection_header "";', + "client_max_body_size 3m;", + "proxy_buffering off;", + "proxy_buffer_size 1k;", + "proxy_buffers 8 1k;", + ], + [ + "ip_hash;", + "least_conn;", + "random ", + "hash", + "least_time ", + "max_fails=1 ", + "fail_timeout=10s ", + "max_conns=1000;", + "proxy_connect_timeout 60s;", + "proxy_read_timeout 60s;", + "proxy_send_timeout 60s;", + "client_max_body_size 1m;", + "slow_start=0s", + "proxy_buffering on;", + ], + ), + ], + ) + def test_when_option_in_config_map_only( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + v_s_route_setup, + v_s_route_app_setup, + restore_configmap, + config_map_file, + expected_strings, + unexpected_strings, + ): req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" vsr_s_event_text = f"Configuration for {text_s} was added or updated" vsr_m_event_text = f"Configuration for {text_m} was added or updated" print(f"Case 3: key specified in ConfigMap, no option in VS") - patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_m.name, - f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", - v_s_route_setup.route_m.namespace) - patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_s.name, - f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", - v_s_route_setup.route_s.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_m.name, + f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", + v_s_route_setup.route_m.namespace, + ) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_s.name, + f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", + v_s_route_setup.route_s.namespace, + ) config_map_name = ingress_controller_prerequisites.config_map["metadata"]["name"] - replace_configmap_from_yaml(kube_apis.v1, config_map_name, - ingress_controller_prerequisites.namespace, - config_map_file) + replace_configmap_from_yaml( + kube_apis.v1, config_map_name, ingress_controller_prerequisites.namespace, config_map_file + ) wait_before_test() ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) @@ -180,27 +276,70 @@ def test_when_option_in_config_map_only(self, kube_apis, assert _ not in config assert_response_codes(resp_1, resp_2) - @pytest.mark.parametrize('options, expected_strings, unexpected_strings', [ - ({"lb-method": "least_conn", "max-fails": 12, - "fail-timeout": "1m", "connect-timeout": "1m", "read-timeout": "77s", "send-timeout": "23s", - "keepalive": 48, "client-max-body-size": "0", - "buffering": True, "buffer-size": "2k", "buffers": {"number": 4, "size": "2k"}}, - ["least_conn;", "max_fails=12 ", - "fail_timeout=1m ", "max_conns=0;", - "proxy_connect_timeout 1m;", "proxy_read_timeout 77s;", "proxy_send_timeout 23s;", - "keepalive 48;", 'set $default_connection_header "";', - "client_max_body_size 0;", - "proxy_buffering on;", "proxy_buffer_size 2k;", "proxy_buffers 4 2k;"], - ["ip_hash;", "random ", "hash", "least_time ", "max_fails=1 ", "fail_timeout=10s ", - "proxy_connect_timeout 44s;", "proxy_read_timeout 22s;", "proxy_send_timeout 55s;", - "keepalive 1024;", - "client_max_body_size 3m;", "client_max_body_size 1m;", - "proxy_buffering off;", "proxy_buffer_size 1k;", "proxy_buffers 8 1k;"]) - ]) - def test_v_s_r_overrides_config_map(self, kube_apis, - ingress_controller_prerequisites, - crd_ingress_controller, v_s_route_setup, v_s_route_app_setup, restore_configmap, - options, expected_strings, unexpected_strings): + @pytest.mark.parametrize( + "options, expected_strings, unexpected_strings", + [ + ( + { + "lb-method": "least_conn", + "max-fails": 12, + "fail-timeout": "1m", + "connect-timeout": "1m", + "read-timeout": "77s", + "send-timeout": "23s", + "keepalive": 48, + "client-max-body-size": "0", + "buffering": True, + "buffer-size": "2k", + "buffers": {"number": 4, "size": "2k"}, + }, + [ + "least_conn;", + "max_fails=12 ", + "fail_timeout=1m ", + "max_conns=0;", + "proxy_connect_timeout 1m;", + "proxy_read_timeout 77s;", + "proxy_send_timeout 23s;", + "keepalive 48;", + 'set $default_connection_header "";', + "client_max_body_size 0;", + "proxy_buffering on;", + "proxy_buffer_size 2k;", + "proxy_buffers 4 2k;", + ], + [ + "ip_hash;", + "random ", + "hash", + "least_time ", + "max_fails=1 ", + "fail_timeout=10s ", + "proxy_connect_timeout 44s;", + "proxy_read_timeout 22s;", + "proxy_send_timeout 55s;", + "keepalive 1024;", + "client_max_body_size 3m;", + "client_max_body_size 1m;", + "proxy_buffering off;", + "proxy_buffer_size 1k;", + "proxy_buffers 8 1k;", + ], + ) + ], + ) + def test_v_s_r_overrides_config_map( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + v_s_route_setup, + v_s_route_app_setup, + restore_configmap, + options, + expected_strings, + unexpected_strings, + ): req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" @@ -212,30 +351,35 @@ def test_v_s_r_overrides_config_map(self, kube_apis, initial_count_vsr_s = assert_event_and_get_count(vsr_s_event_text, events_ns_s) print(f"Case 4: key specified in ConfigMap, option specified in VS") new_body_m = generate_item_with_upstream_options( - f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", - options) + f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", options + ) new_body_s = generate_item_with_upstream_options( - f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", - options) - patch_v_s_route(kube_apis.custom_objects, - v_s_route_setup.route_m.name, v_s_route_setup.route_m.namespace, new_body_m) - patch_v_s_route(kube_apis.custom_objects, - v_s_route_setup.route_s.name, v_s_route_setup.route_s.namespace, new_body_s) + f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", options + ) + patch_v_s_route( + kube_apis.custom_objects, v_s_route_setup.route_m.name, v_s_route_setup.route_m.namespace, new_body_m + ) + patch_v_s_route( + kube_apis.custom_objects, v_s_route_setup.route_s.name, v_s_route_setup.route_s.namespace, new_body_s + ) config_map_name = ingress_controller_prerequisites.config_map["metadata"]["name"] - replace_configmap_from_yaml(kube_apis.v1, config_map_name, - ingress_controller_prerequisites.namespace, - f"{TEST_DATA}/virtual-server-route-upstream-options/configmap-with-keys.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + config_map_name, + ingress_controller_prerequisites.namespace, + f"{TEST_DATA}/virtual-server-route-upstream-options/configmap-with-keys.yaml", + ) wait_before_test() ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) @@ -249,60 +393,94 @@ def test_v_s_r_overrides_config_map(self, kube_apis, @pytest.mark.vsr -@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route-upstream-options"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-route-upstream-options"}, + ) + ], + indirect=True, +) class TestVSRouteUpstreamOptionsValidation: - def test_event_message_and_config(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, v_s_route_setup): + def test_event_message_and_config( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup + ): invalid_fields_s = [ - "upstreams[0].lb-method", "upstreams[0].fail-timeout", - "upstreams[0].max-fails", "upstreams[0].connect-timeout", - "upstreams[0].read-timeout", "upstreams[0].send-timeout", - "upstreams[0].keepalive", "upstreams[0].max-conns", + "upstreams[0].lb-method", + "upstreams[0].fail-timeout", + "upstreams[0].max-fails", + "upstreams[0].connect-timeout", + "upstreams[0].read-timeout", + "upstreams[0].send-timeout", + "upstreams[0].keepalive", + "upstreams[0].max-conns", "upstreams[0].next-upstream", - "upstreams[0].next-upstream-timeout", "upstreams[0].next-upstream-tries", + "upstreams[0].next-upstream-timeout", + "upstreams[0].next-upstream-tries", "upstreams[0].client-max-body-size", - "upstreams[0].buffers.number", "upstreams[0].buffers.size", "upstreams[0].buffer-size" - ] + "upstreams[0].buffers.number", + "upstreams[0].buffers.size", + "upstreams[0].buffer-size", + ] invalid_fields_m = [ - "upstreams[0].lb-method", "upstreams[0].fail-timeout", - "upstreams[0].max-fails", "upstreams[0].connect-timeout", - "upstreams[0].read-timeout", "upstreams[0].send-timeout", - "upstreams[0].keepalive", "upstreams[0].max-conns", + "upstreams[0].lb-method", + "upstreams[0].fail-timeout", + "upstreams[0].max-fails", + "upstreams[0].connect-timeout", + "upstreams[0].read-timeout", + "upstreams[0].send-timeout", + "upstreams[0].keepalive", + "upstreams[0].max-conns", "upstreams[0].next-upstream", - "upstreams[0].next-upstream-timeout", "upstreams[0].next-upstream-tries", + "upstreams[0].next-upstream-timeout", + "upstreams[0].next-upstream-tries", "upstreams[0].client-max-body-size", - "upstreams[0].buffers.number", "upstreams[0].buffers.size", "upstreams[0].buffer-size", - "upstreams[1].lb-method", "upstreams[1].fail-timeout", - "upstreams[1].max-fails", "upstreams[1].connect-timeout", - "upstreams[1].read-timeout", "upstreams[1].send-timeout", - "upstreams[1].keepalive", "upstreams[1].max-conns", + "upstreams[0].buffers.number", + "upstreams[0].buffers.size", + "upstreams[0].buffer-size", + "upstreams[1].lb-method", + "upstreams[1].fail-timeout", + "upstreams[1].max-fails", + "upstreams[1].connect-timeout", + "upstreams[1].read-timeout", + "upstreams[1].send-timeout", + "upstreams[1].keepalive", + "upstreams[1].max-conns", "upstreams[1].next-upstream", - "upstreams[1].next-upstream-timeout", "upstreams[1].next-upstream-tries", + "upstreams[1].next-upstream-timeout", + "upstreams[1].next-upstream-tries", "upstreams[1].client-max-body-size", - "upstreams[1].buffers.number", "upstreams[1].buffers.size", "upstreams[1].buffer-size" - ] + "upstreams[1].buffers.number", + "upstreams[1].buffers.size", + "upstreams[1].buffer-size", + ] text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" vsr_s_event_text = f"VirtualServerRoute {text_s} was rejected with error:" vsr_m_event_text = f"VirtualServerRoute {text_m} was rejected with error:" - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_s.name, - f"{TEST_DATA}/virtual-server-route-upstream-options/route-single-invalid-keys.yaml", - v_s_route_setup.route_s.namespace) - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, - f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple-invalid-keys.yaml", - v_s_route_setup.route_m.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_s.name, + f"{TEST_DATA}/virtual-server-route-upstream-options/route-single-invalid-keys.yaml", + v_s_route_setup.route_s.namespace, + ) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_m.name, + f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple-invalid-keys.yaml", + v_s_route_setup.route_m.namespace, + ) wait_before_test(2) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) @@ -310,31 +488,41 @@ def test_event_message_and_config(self, kube_apis, ingress_controller_prerequisi assert_event_starts_with_text_and_contains_errors(vsr_m_event_text, vsr_m_events, invalid_fields_m) assert "upstream" not in config - def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, v_s_route_setup): + def test_openapi_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) invalid_fields = [ - "lb-method", "fail-timeout", - "max-fails", "connect-timeout", - "read-timeout", "send-timeout", - "keepalive", "max-conns", + "lb-method", + "fail-timeout", + "max-fails", + "connect-timeout", + "read-timeout", + "send-timeout", + "keepalive", + "max-conns", "next-upstream", - "next-upstream-timeout", "next-upstream-tries", + "next-upstream-timeout", + "next-upstream-tries", "client-max-body-size", - "buffers.number", "buffers.size", "buffer-size", - "buffering", "tls" + "buffers.number", + "buffers.size", + "buffer-size", + "buffering", + "tls", ] - config_old = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_old = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) source_yaml = f"{TEST_DATA}/virtual-server-route-upstream-options/route-single-invalid-keys-openapi.yaml" try: - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_s.name, - source_yaml, - v_s_route_setup.route_s.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, v_s_route_setup.route_s.name, source_yaml, v_s_route_setup.route_s.namespace + ) except ApiException as ex: assert ex.status == 422 for item in invalid_fields: @@ -345,58 +533,110 @@ def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisit pytest.fail("Expected an exception but there was none") wait_before_test(2) - config_new = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_new = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert config_old == config_new, "Expected: config doesn't change" @pytest.mark.vsr @pytest.mark.skip_for_nginx_oss -@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route-upstream-options"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-route-upstream-options"}, + ) + ], + indirect=True, +) class TestOptionsSpecificForPlus: - @pytest.mark.parametrize('options, expected_strings', [ - ({"lb-method": "least_conn", - "healthCheck": {"enable": True, "port": 8080}, - "slow-start": "3h", - "queue": {"size": 100}, - "sessionCookie": {"enable": True, - "name": "TestCookie", - "path": "/some-valid/path", - "expires": "max", - "domain": "virtual-server-route.example.com", "httpOnly": True, "secure": True}}, - ["health_check uri=/ port=8080 interval=5s jitter=0s", "fails=1 passes=1", - "slow_start=3h", "queue 100 timeout=60s;", - "sticky cookie TestCookie expires=max domain=virtual-server-route.example.com httponly secure path=/some-valid/path;"]), - ({"lb-method": "least_conn", - "healthCheck": {"enable": True, "path": "/health", - "interval": "15s", "jitter": "3", - "fails": 2, "passes": 2, "port": 8080, - "tls": {"enable": True}, "statusMatch": "200", - "connect-timeout": "35s", "read-timeout": "45s", "send-timeout": "55s", - "headers": [{"name": "Host", "value": "virtual-server.example.com"}]}, - "slow-start": "0s", - "queue": {"size": 1000, "timeout": "66s"}}, - ["health_check uri=/health port=8080 interval=15s jitter=3", "fails=2 passes=2 match=", - "proxy_pass https://vs", "status 200;", - "proxy_connect_timeout 35s;", "proxy_read_timeout 45s;", "proxy_send_timeout 55s;", - 'proxy_set_header Host "virtual-server.example.com";', - "slow_start=0s", "queue 1000 timeout=66s;"]) - ]) - def test_config_and_events(self, kube_apis, - ingress_controller_prerequisites, - crd_ingress_controller, - v_s_route_setup, v_s_route_app_setup, - options, expected_strings): - expected_strings.append(f"location @hc-vs_{v_s_route_setup.namespace}_{v_s_route_setup.vs_name}" - f"_vsr_{v_s_route_setup.route_m.namespace}_{v_s_route_setup.route_m.name}") - expected_strings.append(f"location @hc-vs_{v_s_route_setup.namespace}_{v_s_route_setup.vs_name}" - f"_vsr_{v_s_route_setup.route_s.namespace}_{v_s_route_setup.route_s.name}") + @pytest.mark.parametrize( + "options, expected_strings", + [ + ( + { + "lb-method": "least_conn", + "healthCheck": {"enable": True, "port": 8080}, + "slow-start": "3h", + "queue": {"size": 100}, + "sessionCookie": { + "enable": True, + "name": "TestCookie", + "path": "/some-valid/path", + "expires": "max", + "domain": "virtual-server-route.example.com", + "httpOnly": True, + "secure": True, + }, + }, + [ + "health_check uri=/ port=8080 interval=5s jitter=0s", + "fails=1 passes=1", + "slow_start=3h", + "queue 100 timeout=60s;", + "sticky cookie TestCookie expires=max domain=virtual-server-route.example.com httponly secure path=/some-valid/path;", + ], + ), + ( + { + "lb-method": "least_conn", + "healthCheck": { + "enable": True, + "path": "/health", + "interval": "15s", + "jitter": "3", + "fails": 2, + "passes": 2, + "port": 8080, + "tls": {"enable": True}, + "statusMatch": "200", + "connect-timeout": "35s", + "read-timeout": "45s", + "send-timeout": "55s", + "headers": [{"name": "Host", "value": "virtual-server.example.com"}], + }, + "slow-start": "0s", + "queue": {"size": 1000, "timeout": "66s"}, + }, + [ + "health_check uri=/health port=8080 interval=15s jitter=3", + "fails=2 passes=2 match=", + "proxy_pass https://vs", + "status 200;", + "proxy_connect_timeout 35s;", + "proxy_read_timeout 45s;", + "proxy_send_timeout 55s;", + 'proxy_set_header Host "virtual-server.example.com";', + "slow_start=0s", + "queue 1000 timeout=66s;", + ], + ), + ], + ) + def test_config_and_events( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + v_s_route_setup, + v_s_route_app_setup, + options, + expected_strings, + ): + expected_strings.append( + f"location @hc-vs_{v_s_route_setup.namespace}_{v_s_route_setup.vs_name}" + f"_vsr_{v_s_route_setup.route_m.namespace}_{v_s_route_setup.route_m.name}" + ) + expected_strings.append( + f"location @hc-vs_{v_s_route_setup.namespace}_{v_s_route_setup.vs_name}" + f"_vsr_{v_s_route_setup.route_s.namespace}_{v_s_route_setup.route_s.name}" + ) req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" @@ -408,26 +648,28 @@ def test_config_and_events(self, kube_apis, initial_count_vsr_s = assert_event_and_get_count(vsr_s_event_text, events_ns_s) print(f"Case 2: no key in ConfigMap, option specified in VSR") new_body_m = generate_item_with_upstream_options( - f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", - options) + f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", options + ) new_body_s = generate_item_with_upstream_options( - f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", - options) - patch_v_s_route(kube_apis.custom_objects, - v_s_route_setup.route_m.name, v_s_route_setup.route_m.namespace, new_body_m) - patch_v_s_route(kube_apis.custom_objects, - v_s_route_setup.route_s.name, v_s_route_setup.route_s.namespace, new_body_s) + f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", options + ) + patch_v_s_route( + kube_apis.custom_objects, v_s_route_setup.route_m.name, v_s_route_setup.route_m.namespace, new_body_m + ) + patch_v_s_route( + kube_apis.custom_objects, v_s_route_setup.route_s.name, v_s_route_setup.route_s.namespace, new_body_s + ) wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) @@ -437,35 +679,47 @@ def test_config_and_events(self, kube_apis, assert _ in config assert_response_codes(resp_1, resp_2) - @pytest.mark.parametrize('options', [{"slow-start": "0s"}]) - def test_slow_start_warning(self, kube_apis, - ingress_controller_prerequisites, crd_ingress_controller, - v_s_route_setup, v_s_route_app_setup, options): + @pytest.mark.parametrize("options", [{"slow-start": "0s"}]) + def test_slow_start_warning( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + v_s_route_setup, + v_s_route_app_setup, + options, + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" - vsr_s_event_text = f"Configuration for {text_s} was added or updated with warning(s): " \ - f"Slow start will be disabled" - vsr_m_event_text = f"Configuration for {text_m} was added or updated with warning(s): " \ - f"Slow start will be disabled" + vsr_s_event_text = ( + f"Configuration for {text_s} was added or updated with warning(s): " f"Slow start will be disabled" + ) + vsr_m_event_text = ( + f"Configuration for {text_m} was added or updated with warning(s): " f"Slow start will be disabled" + ) print(f"Case 2: no key in ConfigMap, option specified in VSR") new_body_m = generate_item_with_upstream_options( - f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", - options) + f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", options + ) new_body_s = generate_item_with_upstream_options( - f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", - options) - patch_v_s_route(kube_apis.custom_objects, - v_s_route_setup.route_m.name, v_s_route_setup.route_m.namespace, new_body_m) - patch_v_s_route(kube_apis.custom_objects, - v_s_route_setup.route_s.name, v_s_route_setup.route_s.namespace, new_body_s) + f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", options + ) + patch_v_s_route( + kube_apis.custom_objects, v_s_route_setup.route_m.name, v_s_route_setup.route_m.namespace, new_body_m + ) + patch_v_s_route( + kube_apis.custom_objects, v_s_route_setup.route_s.name, v_s_route_setup.route_s.namespace, new_body_s + ) wait_before_test(1) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) @@ -473,61 +727,92 @@ def test_slow_start_warning(self, kube_apis, assert_event(vsr_m_event_text, vsr_m_events) assert "slow_start" not in config - def test_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, v_s_route_setup): + def test_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup + ): invalid_fields_s = [ - "upstreams[0].healthCheck.path", "upstreams[0].healthCheck.interval", "upstreams[0].healthCheck.jitter", - "upstreams[0].healthCheck.fails", "upstreams[0].healthCheck.passes", + "upstreams[0].healthCheck.path", + "upstreams[0].healthCheck.interval", + "upstreams[0].healthCheck.jitter", + "upstreams[0].healthCheck.fails", + "upstreams[0].healthCheck.passes", "upstreams[0].healthCheck.connect-timeout", - "upstreams[0].healthCheck.read-timeout", "upstreams[0].healthCheck.send-timeout", - "upstreams[0].healthCheck.headers[0].name", "upstreams[0].healthCheck.headers[0].value", + "upstreams[0].healthCheck.read-timeout", + "upstreams[0].healthCheck.send-timeout", + "upstreams[0].healthCheck.headers[0].name", + "upstreams[0].healthCheck.headers[0].value", "upstreams[0].healthCheck.statusMatch", "upstreams[0].slow-start", - "upstreams[0].queue.size", "upstreams[0].queue.timeout", - "upstreams[0].sessionCookie.name", "upstreams[0].sessionCookie.path", - "upstreams[0].sessionCookie.expires", "upstreams[0].sessionCookie.domain" + "upstreams[0].queue.size", + "upstreams[0].queue.timeout", + "upstreams[0].sessionCookie.name", + "upstreams[0].sessionCookie.path", + "upstreams[0].sessionCookie.expires", + "upstreams[0].sessionCookie.domain", ] invalid_fields_m = [ - "upstreams[0].healthCheck.path", "upstreams[0].healthCheck.interval", "upstreams[0].healthCheck.jitter", - "upstreams[0].healthCheck.fails", "upstreams[0].healthCheck.passes", + "upstreams[0].healthCheck.path", + "upstreams[0].healthCheck.interval", + "upstreams[0].healthCheck.jitter", + "upstreams[0].healthCheck.fails", + "upstreams[0].healthCheck.passes", "upstreams[0].healthCheck.connect-timeout", - "upstreams[0].healthCheck.read-timeout", "upstreams[0].healthCheck.send-timeout", - "upstreams[0].healthCheck.headers[0].name", "upstreams[0].healthCheck.headers[0].value", + "upstreams[0].healthCheck.read-timeout", + "upstreams[0].healthCheck.send-timeout", + "upstreams[0].healthCheck.headers[0].name", + "upstreams[0].healthCheck.headers[0].value", "upstreams[0].healthCheck.statusMatch", "upstreams[0].slow-start", - "upstreams[0].queue.size", "upstreams[0].queue.timeout", - "upstreams[0].sessionCookie.name", "upstreams[0].sessionCookie.path", - "upstreams[0].sessionCookie.expires", "upstreams[0].sessionCookie.domain", - "upstreams[1].healthCheck.path", "upstreams[1].healthCheck.interval", "upstreams[1].healthCheck.jitter", - "upstreams[1].healthCheck.fails", "upstreams[1].healthCheck.passes", + "upstreams[0].queue.size", + "upstreams[0].queue.timeout", + "upstreams[0].sessionCookie.name", + "upstreams[0].sessionCookie.path", + "upstreams[0].sessionCookie.expires", + "upstreams[0].sessionCookie.domain", + "upstreams[1].healthCheck.path", + "upstreams[1].healthCheck.interval", + "upstreams[1].healthCheck.jitter", + "upstreams[1].healthCheck.fails", + "upstreams[1].healthCheck.passes", "upstreams[1].healthCheck.connect-timeout", - "upstreams[1].healthCheck.read-timeout", "upstreams[1].healthCheck.send-timeout", - "upstreams[1].healthCheck.headers[0].name", "upstreams[0].healthCheck.headers[0].value", + "upstreams[1].healthCheck.read-timeout", + "upstreams[1].healthCheck.send-timeout", + "upstreams[1].healthCheck.headers[0].name", + "upstreams[0].healthCheck.headers[0].value", "upstreams[1].healthCheck.statusMatch", "upstreams[1].slow-start", - "upstreams[1].queue.size", "upstreams[1].queue.timeout", - "upstreams[1].sessionCookie.name", "upstreams[1].sessionCookie.path", - "upstreams[1].sessionCookie.expires", "upstreams[1].sessionCookie.domain" + "upstreams[1].queue.size", + "upstreams[1].queue.timeout", + "upstreams[1].sessionCookie.name", + "upstreams[1].sessionCookie.path", + "upstreams[1].sessionCookie.expires", + "upstreams[1].sessionCookie.domain", ] text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" vsr_s_event_text = f"VirtualServerRoute {text_s} was rejected with error:" vsr_m_event_text = f"VirtualServerRoute {text_m} was rejected with error:" - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_s.name, - f"{TEST_DATA}/virtual-server-route-upstream-options/plus-route-s-invalid-keys.yaml", - v_s_route_setup.route_s.namespace) - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_m.name, - f"{TEST_DATA}/virtual-server-route-upstream-options/plus-route-m-invalid-keys.yaml", - v_s_route_setup.route_m.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_s.name, + f"{TEST_DATA}/virtual-server-route-upstream-options/plus-route-s-invalid-keys.yaml", + v_s_route_setup.route_s.namespace, + ) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_m.name, + f"{TEST_DATA}/virtual-server-route-upstream-options/plus-route-m-invalid-keys.yaml", + v_s_route_setup.route_m.namespace, + ) wait_before_test(2) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) @@ -535,33 +820,44 @@ def test_validation_flow(self, kube_apis, ingress_controller_prerequisites, assert_event_starts_with_text_and_contains_errors(vsr_m_event_text, vsr_m_events, invalid_fields_m) assert "upstream" not in config - def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, v_s_route_setup): + def test_openapi_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, v_s_route_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) invalid_fields = [ - "healthCheck.enable", "healthCheck.path", - "healthCheck.interval", "healthCheck.jitter", - "healthCheck.fails", "healthCheck.passes", - "healthCheck.port", "healthCheck.connect-timeout", - "healthCheck.read-timeout", "healthCheck.send-timeout", + "healthCheck.enable", + "healthCheck.path", + "healthCheck.interval", + "healthCheck.jitter", + "healthCheck.fails", + "healthCheck.passes", + "healthCheck.port", + "healthCheck.connect-timeout", + "healthCheck.read-timeout", + "healthCheck.send-timeout", "healthCheck.statusMatch", "slow-start", - "queue.size", "queue.timeout", - "sessionCookie.name", "sessionCookie.path", - "sessionCookie.expires", "sessionCookie.domain", - "sessionCookie.httpOnly", "sessionCookie.secure" + "queue.size", + "queue.timeout", + "sessionCookie.name", + "sessionCookie.path", + "sessionCookie.expires", + "sessionCookie.domain", + "sessionCookie.httpOnly", + "sessionCookie.secure", ] - config_old = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_old = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) source_yaml = f"{TEST_DATA}/virtual-server-route-upstream-options/plus-route-s-invalid-keys-openapi.yaml" try: - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_s.name, - source_yaml, - v_s_route_setup.route_s.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, v_s_route_setup.route_s.name, source_yaml, v_s_route_setup.route_s.namespace + ) except ApiException as ex: assert ex.status == 422 for item in invalid_fields: @@ -572,9 +868,11 @@ def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisit pytest.fail("Expected an exception but there was none") wait_before_test(2) - config_new = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_new = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert config_old == config_new, "Expected: config doesn't change" diff --git a/tests/suite/test_v_s_route_upstream_tls.py b/tests/suite/test_v_s_route_upstream_tls.py index 2f366c85ac..2cfab23a71 100644 --- a/tests/suite/test_v_s_route_upstream_tls.py +++ b/tests/suite/test_v_s_route_upstream_tls.py @@ -1,13 +1,23 @@ -import requests import pytest +import requests from kubernetes.client.rest import ApiException - from settings import TEST_DATA -from suite.custom_assertions import assert_event_and_get_count, assert_event_count_increased, assert_response_codes, \ - assert_event, assert_no_new_events +from suite.custom_assertions import ( + assert_event, + assert_event_and_get_count, + assert_event_count_increased, + assert_no_new_events, + assert_response_codes, +) +from suite.resources_utils import ( + create_items_from_yaml, + delete_items_from_yaml, + get_events, + get_first_pod_name, + wait_before_test, + wait_until_all_pods_are_ready, +) from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, patch_v_s_route_from_yaml -from suite.resources_utils import create_items_from_yaml, get_first_pod_name, \ - delete_items_from_yaml, wait_until_all_pods_are_ready, wait_before_test, get_events @pytest.fixture(scope="class") @@ -24,55 +34,75 @@ def v_s_route_secure_app_setup(request, kube_apis, v_s_route_setup) -> None: :return: """ print("---------------------- Deploy a VS Route Example Application ----------------------------") - create_items_from_yaml(kube_apis, - f"{TEST_DATA}/common/app/vsr/secure/multiple.yaml", v_s_route_setup.route_m.namespace) + create_items_from_yaml( + kube_apis, f"{TEST_DATA}/common/app/vsr/secure/multiple.yaml", v_s_route_setup.route_m.namespace + ) - create_items_from_yaml(kube_apis, - f"{TEST_DATA}/common/app/vsr/secure/single.yaml", v_s_route_setup.route_s.namespace) + create_items_from_yaml( + kube_apis, f"{TEST_DATA}/common/app/vsr/secure/single.yaml", v_s_route_setup.route_s.namespace + ) wait_until_all_pods_are_ready(kube_apis.v1, v_s_route_setup.route_m.namespace) wait_until_all_pods_are_ready(kube_apis.v1, v_s_route_setup.route_s.namespace) def fin(): print("Clean up the Application:") - delete_items_from_yaml(kube_apis, - f"{TEST_DATA}/common/app/vsr/secure/multiple.yaml", - v_s_route_setup.route_m.namespace) - delete_items_from_yaml(kube_apis, - f"{TEST_DATA}/common/app/vsr/secure/single.yaml", - v_s_route_setup.route_s.namespace) + delete_items_from_yaml( + kube_apis, f"{TEST_DATA}/common/app/vsr/secure/multiple.yaml", v_s_route_setup.route_m.namespace + ) + delete_items_from_yaml( + kube_apis, f"{TEST_DATA}/common/app/vsr/secure/single.yaml", v_s_route_setup.route_s.namespace + ) request.addfinalizer(fin) @pytest.mark.vsr -@pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-route-upstream-tls"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, v_s_route_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-route-upstream-tls"}, + ) + ], + indirect=True, +) class TestVSRouteUpstreamTls: - def test_responses_and_config_after_setup(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, v_s_route_setup, v_s_route_secure_app_setup): + def test_responses_and_config_after_setup( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + v_s_route_setup, + v_s_route_secure_app_setup, + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) vs_line = f"vs_{v_s_route_setup.namespace}_{v_s_route_setup.vs_name}" proxy_host_s = f"{vs_line}_vsr_{v_s_route_setup.route_s.namespace}_{v_s_route_setup.route_s.name}" proxy_host_m = f"{vs_line}_vsr_{v_s_route_setup.route_m.namespace}_{v_s_route_setup.route_m.name}" - assert f'proxy_pass https://{proxy_host_m}' not in config - assert f'proxy_pass https://{proxy_host_s}' in config + assert f"proxy_pass https://{proxy_host_m}" not in config + assert f"proxy_pass https://{proxy_host_s}" in config assert_response_codes(resp_1, resp_2) - def test_events_after_setup(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, v_s_route_setup, v_s_route_secure_app_setup): + def test_events_after_setup( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + v_s_route_setup, + v_s_route_secure_app_setup, + ): text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" text_vs = f"{v_s_route_setup.namespace}/{v_s_route_setup.vs_name}" @@ -85,17 +115,24 @@ def test_events_after_setup(self, kube_apis, ingress_controller_prerequisites, assert_event(vsr_m_event_text, events_ns_m) assert_event(vs_event_text, events_ns_m) - def test_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, - v_s_route_setup, v_s_route_secure_app_setup): + def test_validation_flow( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + v_s_route_setup, + v_s_route_secure_app_setup, + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) initial_events_ns_m = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) initial_events_ns_s = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) try: - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_s.name, - f"{TEST_DATA}/virtual-server-route-upstream-tls/route-single-invalid.yaml", - v_s_route_setup.route_s.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_s.name, + f"{TEST_DATA}/virtual-server-route-upstream-tls/route-single-invalid.yaml", + v_s_route_setup.route_s.namespace, + ) except ApiException as ex: assert ex.status == 422 and "tls.enable" in ex.body except Exception as ex: @@ -104,31 +141,36 @@ def test_validation_flow(self, kube_apis, ingress_controller_prerequisites, pytest.fail("Expected an exception but there was none") wait_before_test(1) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) new_events_ns_m = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) new_events_ns_s = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) vs_line = f"vs_{v_s_route_setup.namespace}_{v_s_route_setup.vs_name}" proxy_host_s = f"{vs_line}_vsr_{v_s_route_setup.route_s.namespace}_{v_s_route_setup.route_s.name}" proxy_host_m = f"{vs_line}_vsr_{v_s_route_setup.route_m.namespace}_{v_s_route_setup.route_m.name}" - assert f'proxy_pass https://{proxy_host_m}' not in config - assert f'proxy_pass https://{proxy_host_s}' in config + assert f"proxy_pass https://{proxy_host_m}" not in config + assert f"proxy_pass https://{proxy_host_s}" in config assert_response_codes(resp_1, resp_2) assert_no_new_events(initial_events_ns_m, new_events_ns_m) assert_no_new_events(initial_events_ns_s, new_events_ns_s) - def test_responses_and_config_after_disable_tls(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, - v_s_route_setup, v_s_route_secure_app_setup): + def test_responses_and_config_after_disable_tls( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + v_s_route_setup, + v_s_route_secure_app_setup, + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" @@ -141,25 +183,27 @@ def test_responses_and_config_after_disable_tls(self, kube_apis, ingress_control initial_count_vsr_m = assert_event_and_get_count(vsr_m_event_text, initial_events_ns_m) initial_count_vsr_s = assert_event_and_get_count(vsr_s_event_text, initial_events_ns_s) initial_count_vs = assert_event_and_get_count(vs_event_text, initial_events_ns_m) - patch_v_s_route_from_yaml(kube_apis.custom_objects, - v_s_route_setup.route_s.name, - f"{TEST_DATA}/virtual-server-route-upstream-tls/route-single-disable-tls.yaml", - v_s_route_setup.route_s.namespace) + patch_v_s_route_from_yaml( + kube_apis.custom_objects, + v_s_route_setup.route_s.name, + f"{TEST_DATA}/virtual-server-route-upstream-tls/route-single-disable-tls.yaml", + v_s_route_setup.route_s.namespace, + ) wait_before_test(1) - config = get_vs_nginx_template_conf(kube_apis.v1, - v_s_route_setup.namespace, - v_s_route_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + v_s_route_setup.namespace, + v_s_route_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" - resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) - resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", - headers={"host": v_s_route_setup.vs_host}) + resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", headers={"host": v_s_route_setup.vs_host}) + resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", headers={"host": v_s_route_setup.vs_host}) new_events_ns_m = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) new_events_ns_s = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) - assert 'proxy_pass https://' not in config + assert "proxy_pass https://" not in config assert_response_codes(resp_1, resp_2, 200, 400) assert_event_count_increased(vsr_m_event_text, initial_count_vsr_m, new_events_ns_m) assert_event_count_increased(vs_event_text, initial_count_vs, new_events_ns_m) diff --git a/tests/suite/test_virtual_server.py b/tests/suite/test_virtual_server.py index 8c5b76439f..34bbbda157 100644 --- a/tests/suite/test_virtual_server.py +++ b/tests/suite/test_virtual_server.py @@ -1,53 +1,67 @@ -import requests import pytest - -from settings import TEST_DATA, DEPLOYMENTS +import requests +from settings import DEPLOYMENTS, TEST_DATA from suite.custom_assertions import wait_and_assert_status_code -from suite.custom_resources_utils import delete_crd, create_crd_from_yaml +from suite.custom_resources_utils import create_crd_from_yaml, delete_crd +from suite.resources_utils import ( + create_service_from_yaml, + delete_service, + patch_rbac, + read_service, + replace_service, + wait_before_test, +) from suite.vs_vsr_resources_utils import ( - delete_virtual_server, create_virtual_server_from_yaml, + delete_virtual_server, patch_virtual_server_from_yaml, ) -from suite.resources_utils import patch_rbac, replace_service, read_service, \ - wait_before_test, delete_service, create_service_from_yaml -from suite.yaml_utils import get_paths_from_vs_yaml, get_first_host_from_yaml, get_name_from_yaml +from suite.yaml_utils import get_first_host_from_yaml, get_name_from_yaml, get_paths_from_vs_yaml @pytest.mark.vs @pytest.mark.smoke -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestVirtualServer: def test_responses_after_setup(self, kube_apis, crd_ingress_controller, virtual_server_setup): print("\nStep 1: initial check") wait_before_test(1) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 def test_responses_after_virtual_server_update(self, kube_apis, crd_ingress_controller, virtual_server_setup): print("Step 2: update host and paths in the VS and check") - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server/standard/virtual-server-updated.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server/standard/virtual-server-updated.yaml", + virtual_server_setup.namespace, + ) new_paths = get_paths_from_vs_yaml(f"{TEST_DATA}/virtual-server/standard/virtual-server-updated.yaml") - new_backend_1_url = f"http://{virtual_server_setup.public_endpoint.public_ip}" \ + new_backend_1_url = ( + f"http://{virtual_server_setup.public_endpoint.public_ip}" f":{virtual_server_setup.public_endpoint.port}/{new_paths[0]}" - new_backend_2_url = f"http://{virtual_server_setup.public_endpoint.public_ip}" \ + ) + new_backend_2_url = ( + f"http://{virtual_server_setup.public_endpoint.public_ip}" f":{virtual_server_setup.public_endpoint.port}/{new_paths[1]}" + ) new_host = get_first_host_from_yaml(f"{TEST_DATA}/virtual-server/standard/virtual-server-updated.yaml") wait_before_test(1) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 404 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 404 resp = requests.get(new_backend_1_url, headers={"host": new_host}) assert resp.status_code == 200 @@ -55,19 +69,20 @@ def test_responses_after_virtual_server_update(self, kube_apis, crd_ingress_cont assert resp.status_code == 200 print("Step 3: restore VS and check") - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server/standard/virtual-server.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server/standard/virtual-server.yaml", + virtual_server_setup.namespace, + ) wait_before_test(1) resp = requests.get(new_backend_1_url, headers={"host": new_host}) assert resp.status_code == 404 resp = requests.get(new_backend_2_url, headers={"host": new_host}) assert resp.status_code == 404 - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 def test_responses_after_backend_update(self, kube_apis, crd_ingress_controller, virtual_server_setup): @@ -76,11 +91,9 @@ def test_responses_after_backend_update(self, kube_apis, crd_ingress_controller, the_service.spec.ports[0].port = 8080 replace_service(kube_apis.v1, "backend1-svc", virtual_server_setup.namespace, the_service) wait_before_test(1) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 502 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 print("Step 5: restore BE and check") @@ -88,77 +101,66 @@ def test_responses_after_backend_update(self, kube_apis, crd_ingress_controller, the_service.spec.ports[0].port = 80 replace_service(kube_apis.v1, "backend1-svc", virtual_server_setup.namespace, the_service) wait_before_test(1) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 def test_responses_after_virtual_server_removal(self, kube_apis, crd_ingress_controller, virtual_server_setup): print("\nStep 6: delete VS and check") delete_virtual_server(kube_apis.custom_objects, virtual_server_setup.vs_name, virtual_server_setup.namespace) wait_before_test(1) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 404 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 404 print("Step 7: restore VS and check") - create_virtual_server_from_yaml(kube_apis.custom_objects, - f"{TEST_DATA}/virtual-server/standard/virtual-server.yaml", - virtual_server_setup.namespace) + create_virtual_server_from_yaml( + kube_apis.custom_objects, + f"{TEST_DATA}/virtual-server/standard/virtual-server.yaml", + virtual_server_setup.namespace, + ) wait_before_test(1) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 def test_responses_after_backend_service_removal(self, kube_apis, crd_ingress_controller, virtual_server_setup): print("\nStep 8: remove one backend service and check") delete_service(kube_apis.v1, "backend1-svc", virtual_server_setup.namespace) wait_before_test(1) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 502 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 print("\nStep 9: restore backend service and check") create_service_from_yaml(kube_apis.v1, virtual_server_setup.namespace, f"{TEST_DATA}/common/backend1-svc.yaml") wait_before_test(3) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 - def test_responses_after_rbac_misconfiguration_on_the_fly(self, kube_apis, crd_ingress_controller, - virtual_server_setup): + def test_responses_after_rbac_misconfiguration_on_the_fly( + self, kube_apis, crd_ingress_controller, virtual_server_setup + ): print("Step 10: remove virtualservers from the ClusterRole and check") patch_rbac(kube_apis.rbac_v1, f"{TEST_DATA}/virtual-server/rbac-without-vs.yaml") wait_before_test(1) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 print("Step 11: restore ClusterRole and check") patch_rbac(kube_apis.rbac_v1, f"{DEPLOYMENTS}/rbac/rbac.yaml") wait_before_test(1) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 def test_responses_after_crd_removal_on_the_fly(self, kube_apis, crd_ingress_controller, virtual_server_setup): @@ -169,30 +171,37 @@ def test_responses_after_crd_removal_on_the_fly(self, kube_apis, crd_ingress_con wait_and_assert_status_code(404, virtual_server_setup.backend_2_url, virtual_server_setup.vs_host) print("Step 13: restore CRD and VS and check") - create_crd_from_yaml(kube_apis.api_extensions_v1, crd_name, - f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_virtualservers.yaml") + create_crd_from_yaml( + kube_apis.api_extensions_v1, crd_name, f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_virtualservers.yaml" + ) wait_before_test(1) - create_virtual_server_from_yaml(kube_apis.custom_objects, - f"{TEST_DATA}/virtual-server/standard/virtual-server.yaml", - virtual_server_setup.namespace) + create_virtual_server_from_yaml( + kube_apis.custom_objects, + f"{TEST_DATA}/virtual-server/standard/virtual-server.yaml", + virtual_server_setup.namespace, + ) wait_and_assert_status_code(200, virtual_server_setup.backend_1_url, virtual_server_setup.vs_host) wait_and_assert_status_code(200, virtual_server_setup.backend_2_url, virtual_server_setup.vs_host) @pytest.mark.vs -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "rbac-without-vs", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "rbac-without-vs", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestVirtualServerInitialRBACMisconfiguration: @pytest.mark.skip(reason="issues with ingressClass") def test_responses_after_rbac_misconfiguration(self, kube_apis, crd_ingress_controller, virtual_server_setup): print("\nStep 1: rbac misconfiguration from the very start") - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 404 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 404 print("Step 2: configure RBAC and check") diff --git a/tests/suite/test_virtual_server_advanced_routing.py b/tests/suite/test_virtual_server_advanced_routing.py index 595b2f5ed7..dfcbb632a0 100644 --- a/tests/suite/test_virtual_server_advanced_routing.py +++ b/tests/suite/test_virtual_server_advanced_routing.py @@ -1,9 +1,8 @@ import pytest import requests - from settings import TEST_DATA +from suite.resources_utils import ensure_response_from_backend, wait_before_test from suite.vs_vsr_resources_utils import patch_virtual_server_from_yaml -from suite.resources_utils import wait_before_test, ensure_response_from_backend def execute_assertions(resp_1, resp_2, resp_3): @@ -23,57 +22,82 @@ def ensure_responses_from_backends(req_url, host) -> None: @pytest.mark.vs @pytest.mark.smoke -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-advanced-routing", "app_type": "advanced-routing"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-advanced-routing", "app_type": "advanced-routing"}, + ) + ], + indirect=True, +) class TestAdvancedRouting: def test_flow_with_header(self, kube_apis, crd_ingress_controller, virtual_server_setup): ensure_responses_from_backends(virtual_server_setup.backend_1_url, virtual_server_setup.vs_host) - resp_1 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host, "x-version": "future"}) - resp_2 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host, "x-version": "deprecated"}) - resp_3 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host, "x-version-invalid": "deprecated"}) + resp_1 = requests.get( + virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host, "x-version": "future"} + ) + resp_2 = requests.get( + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host, "x-version": "deprecated"}, + ) + resp_3 = requests.get( + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host, "x-version-invalid": "deprecated"}, + ) execute_assertions(resp_1, resp_2, resp_3) def test_flow_with_argument(self, kube_apis, crd_ingress_controller, virtual_server_setup): - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-advanced-routing/virtual-server-argument.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-advanced-routing/virtual-server-argument.yaml", + virtual_server_setup.namespace, + ) wait_before_test(1) - resp_1 = requests.get(virtual_server_setup.backend_1_url + "?arg1=v1", - headers={"host": virtual_server_setup.vs_host}) - resp_2 = requests.get(virtual_server_setup.backend_1_url + "?arg1=v2", - headers={"host": virtual_server_setup.vs_host}) - resp_3 = requests.get(virtual_server_setup.backend_1_url + "?argument1=v1", - headers={"host": virtual_server_setup.vs_host}) + resp_1 = requests.get( + virtual_server_setup.backend_1_url + "?arg1=v1", headers={"host": virtual_server_setup.vs_host} + ) + resp_2 = requests.get( + virtual_server_setup.backend_1_url + "?arg1=v2", headers={"host": virtual_server_setup.vs_host} + ) + resp_3 = requests.get( + virtual_server_setup.backend_1_url + "?argument1=v1", headers={"host": virtual_server_setup.vs_host} + ) execute_assertions(resp_1, resp_2, resp_3) def test_flow_with_cookie(self, kube_apis, crd_ingress_controller, virtual_server_setup): - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-advanced-routing/virtual-server-cookie.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-advanced-routing/virtual-server-cookie.yaml", + virtual_server_setup.namespace, + ) wait_before_test(1) - resp_1 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}, cookies={"user": "some"}) - resp_2 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}, cookies={"user": "bad"}) - resp_3 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}, cookies={"user": "anonymous"}) + resp_1 = requests.get( + virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, cookies={"user": "some"} + ) + resp_2 = requests.get( + virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, cookies={"user": "bad"} + ) + resp_3 = requests.get( + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host}, + cookies={"user": "anonymous"}, + ) execute_assertions(resp_1, resp_2, resp_3) def test_flow_with_variable(self, kube_apis, crd_ingress_controller, virtual_server_setup): - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-advanced-routing/virtual-server-variable.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-advanced-routing/virtual-server-variable.yaml", + virtual_server_setup.namespace, + ) wait_before_test(1) resp_1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) @@ -82,19 +106,27 @@ def test_flow_with_variable(self, kube_apis, crd_ingress_controller, virtual_ser execute_assertions(resp_1, resp_2, resp_3) def test_flow_with_complex_conditions(self, kube_apis, crd_ingress_controller, virtual_server_setup): - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-advanced-routing/virtual-server-complex.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-advanced-routing/virtual-server-complex.yaml", + virtual_server_setup.namespace, + ) wait_before_test(1) - resp_1 = requests.get(virtual_server_setup.backend_1_url + "?arg1=v1", - headers={"host": virtual_server_setup.vs_host, - "x-version": "future"}, cookies={"user": "some"}) - resp_2 = requests.post(virtual_server_setup.backend_1_url + "?arg1=v2", - headers={"host": virtual_server_setup.vs_host, - "x-version": "deprecated"}, cookies={"user": "bad"}) - resp_3 = requests.get(virtual_server_setup.backend_1_url + "?arg1=v2", - headers={"host": virtual_server_setup.vs_host, - "x-version": "deprecated"}, cookies={"user": "bad"}) + resp_1 = requests.get( + virtual_server_setup.backend_1_url + "?arg1=v1", + headers={"host": virtual_server_setup.vs_host, "x-version": "future"}, + cookies={"user": "some"}, + ) + resp_2 = requests.post( + virtual_server_setup.backend_1_url + "?arg1=v2", + headers={"host": virtual_server_setup.vs_host, "x-version": "deprecated"}, + cookies={"user": "bad"}, + ) + resp_3 = requests.get( + virtual_server_setup.backend_1_url + "?arg1=v2", + headers={"host": virtual_server_setup.vs_host, "x-version": "deprecated"}, + cookies={"user": "bad"}, + ) execute_assertions(resp_1, resp_2, resp_3) diff --git a/tests/suite/test_virtual_server_api.py b/tests/suite/test_virtual_server_api.py index e209614d90..ee040301aa 100644 --- a/tests/suite/test_virtual_server_api.py +++ b/tests/suite/test_virtual_server_api.py @@ -1,23 +1,31 @@ -import pytest -import requests import json +import pytest +import requests from settings import NGINX_API_VERSION - -from suite.nginx_api_utils import wait_for_empty_array, wait_for_non_empty_array, get_nginx_generation_value +from suite.nginx_api_utils import get_nginx_generation_value, wait_for_empty_array, wait_for_non_empty_array from suite.resources_utils import scale_deployment @pytest.mark.vs @pytest.mark.skip_for_nginx_oss -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": ["-enable-custom-resources", - "-nginx-status-allow-cidrs=0.0.0.0/0,::/0"]}, - {"example": "virtual-server-dynamic-configuration", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + { + "type": "complete", + "extra_args": ["-enable-custom-resources", "-nginx-status-allow-cidrs=0.0.0.0/0,::/0"], + }, + {"example": "virtual-server-dynamic-configuration", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestVSNginxPlusApi: - def test_dynamic_configuration(self, kube_apis, ingress_controller_endpoint, - crd_ingress_controller, virtual_server_setup): + def test_dynamic_configuration( + self, kube_apis, ingress_controller_endpoint, crd_ingress_controller, virtual_server_setup + ): req_url = f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.api_port}" vs_upstream = f"vs_{virtual_server_setup.namespace}_{virtual_server_setup.vs_name}_backend2" initial_reloads_count = get_nginx_generation_value(req_url) @@ -32,14 +40,16 @@ def test_dynamic_configuration(self, kube_apis, ingress_controller_endpoint, resp = json.loads(requests.get(upstream_servers_url).text) new_reloads_count = get_nginx_generation_value(req_url) assert new_reloads_count == initial_reloads_count, "Expected: no new reloads" - assert resp[0]['max_conns'] == 32 - assert resp[0]['max_fails'] == 25 - assert resp[0]['fail_timeout'] == '15s' - assert resp[0]['slow_start'] == '10s' + assert resp[0]["max_conns"] == 32 + assert resp[0]["max_fails"] == 25 + assert resp[0]["fail_timeout"] == "15s" + assert resp[0]["slow_start"] == "10s" def test_status_zone_support(self, kube_apis, crd_ingress_controller, virtual_server_setup): - req_url = f"http://" \ + req_url = ( + f"http://" f"{virtual_server_setup.public_endpoint.public_ip}:{virtual_server_setup.public_endpoint.api_port}" + ) status_zone_url = f"{req_url}/api/{NGINX_API_VERSION}/http/server_zones" resp = json.loads(requests.get(status_zone_url).text) assert resp[f"{virtual_server_setup.vs_host}"] diff --git a/tests/suite/test_virtual_server_canned_responses.py b/tests/suite/test_virtual_server_canned_responses.py index 8b4d894424..6698dd67e5 100644 --- a/tests/suite/test_virtual_server_canned_responses.py +++ b/tests/suite/test_virtual_server_canned_responses.py @@ -1,29 +1,40 @@ -import pytest -import requests import json +import pytest +import requests from kubernetes.client.rest import ApiException - from settings import TEST_DATA -from suite.custom_assertions import wait_and_assert_status_code, assert_event_and_get_count, \ - assert_event_count_increased, assert_event_starts_with_text_and_contains_errors -from suite.vs_vsr_resources_utils import patch_virtual_server_from_yaml, get_vs_nginx_template_conf -from suite.resources_utils import get_first_pod_name, get_events, wait_before_test +from suite.custom_assertions import ( + assert_event_and_get_count, + assert_event_count_increased, + assert_event_starts_with_text_and_contains_errors, + wait_and_assert_status_code, +) +from suite.resources_utils import get_events, get_first_pod_name, wait_before_test +from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, patch_virtual_server_from_yaml @pytest.mark.vs -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-canned-responses", "app_type": None})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-canned-responses", "app_type": None}, + ) + ], + indirect=True, +) class TestVSCannedResponse: def test_config(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert "error_page 418 =407" in config and "error_page 418 =200" in config def test_custom_canned_response(self, kube_apis, crd_ingress_controller, virtual_server_setup): @@ -31,36 +42,38 @@ def test_custom_canned_response(self, kube_apis, crd_ingress_controller, virtual wait_and_assert_status_code(407, req_url, virtual_server_setup.vs_host) resp = requests.get(req_url, headers={"host": virtual_server_setup.vs_host}) resp_content = json.loads(resp.content) - assert resp.headers['content-type'] == 'application/json' \ - and resp_content['host'] == virtual_server_setup.vs_host \ - and resp_content['request_time'] != "" \ - and resp_content['pid'] != "" \ - and resp_content['server_protocol'] == "HTTP/1.1" \ - and resp_content['connections_active'] != "" \ - and resp_content['connections_writing'] != "" \ - and resp_content['request_uri'] == "/canned-response?arg1=arg" \ - and resp_content['remote_addr'] != "" \ - and resp_content['remote_port'] != "" \ - and resp_content['server_addr'] != "" \ - and resp_content['request_method'] == "GET" \ - and resp_content['scheme'] == "http" \ - and resp_content['request_length'] != "" \ - and resp_content['nginx_version'] != "" \ - and resp_content['connection'] != "" \ - and resp_content['time_local'] != "" \ - and resp_content['server_port'] != "" \ - and resp_content['server_name'] == virtual_server_setup.vs_host \ - and resp_content['connections_waiting'] != "" \ - and resp_content['request_body'] == "" \ - and resp_content['args'] == "arg1=arg" \ - and resp_content['time_iso8601'] != "" \ - and resp_content['connections_reading'] != "" + assert ( + resp.headers["content-type"] == "application/json" + and resp_content["host"] == virtual_server_setup.vs_host + and resp_content["request_time"] != "" + and resp_content["pid"] != "" + and resp_content["server_protocol"] == "HTTP/1.1" + and resp_content["connections_active"] != "" + and resp_content["connections_writing"] != "" + and resp_content["request_uri"] == "/canned-response?arg1=arg" + and resp_content["remote_addr"] != "" + and resp_content["remote_port"] != "" + and resp_content["server_addr"] != "" + and resp_content["request_method"] == "GET" + and resp_content["scheme"] == "http" + and resp_content["request_length"] != "" + and resp_content["nginx_version"] != "" + and resp_content["connection"] != "" + and resp_content["time_local"] != "" + and resp_content["server_port"] != "" + and resp_content["server_name"] == virtual_server_setup.vs_host + and resp_content["connections_waiting"] != "" + and resp_content["request_body"] == "" + and resp_content["args"] == "arg1=arg" + and resp_content["time_iso8601"] != "" + and resp_content["connections_reading"] != "" + ) def test_default_canned_response(self, kube_apis, crd_ingress_controller, virtual_server_setup): wait_and_assert_status_code(200, virtual_server_setup.backend_2_url, virtual_server_setup.vs_host) resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) - resp_content = resp.content.decode('utf-8') - assert resp.headers['content-type'] == 'text/plain' and resp_content == "line1\nline2\nline3" + resp_content = resp.content.decode("utf-8") + assert resp.headers["content-type"] == "text/plain" and resp_content == "line1\nline2\nline3" def test_update(self, kube_apis, crd_ingress_controller, virtual_server_setup): wait_before_test(1) @@ -69,62 +82,70 @@ def test_update(self, kube_apis, crd_ingress_controller, virtual_server_setup): events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) initial_count = assert_event_and_get_count(vs_event_text, events_vs) vs_src = f"{TEST_DATA}/virtual-server-canned-responses/virtual-server-updated.yaml" - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace + ) wait_and_assert_status_code(501, virtual_server_setup.backend_1_url, virtual_server_setup.vs_host) resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) - resp_content = resp.content.decode('utf-8') - assert resp.headers['content-type'] == 'some/type' and resp_content == "{}" + resp_content = resp.content.decode("utf-8") + assert resp.headers["content-type"] == "some/type" and resp_content == "{}" wait_and_assert_status_code(201, virtual_server_setup.backend_2_url, virtual_server_setup.vs_host) resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) - resp_content = resp.content.decode('utf-8') - assert resp.headers['content-type'] == 'user-type' and resp_content == "line1\nline2" + resp_content = resp.content.decode("utf-8") + assert resp.headers["content-type"] == "user-type" and resp_content == "line1\nline2" vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_count_increased(vs_event_text, initial_count, vs_events) def test_validation_flow(self, kube_apis, crd_ingress_controller, virtual_server_setup): - invalid_fields = [ - "spec.routes[0].action.return.code", "spec.routes[0].action.return.body" - ] + invalid_fields = ["spec.routes[0].action.return.code", "spec.routes[0].action.return.body"] text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"VirtualServer {text} was rejected with error:" vs_src = f"{TEST_DATA}/virtual-server-canned-responses/virtual-server-invalid.yaml" - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace + ) wait_before_test(1) wait_and_assert_status_code(404, virtual_server_setup.backend_1_url, virtual_server_setup.vs_host) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_starts_with_text_and_contains_errors(vs_event_text, vs_events, invalid_fields) - def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): + def test_openapi_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config_old = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_old = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) vs_src = f"{TEST_DATA}/virtual-server-canned-responses/virtual-server-invalid-openapi.yaml" try: - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace + ) except ApiException as ex: - assert ex.status == 422 \ - and "action.return.type in body must be of type" in ex.body \ - and "action.return.body in body must be of type" in ex.body \ - and "action.return.code in body must be of type" in ex.body + assert ( + ex.status == 422 + and "action.return.type in body must be of type" in ex.body + and "action.return.body in body must be of type" in ex.body + and "action.return.code in body must be of type" in ex.body + ) except Exception as ex: pytest.fail(f"An unexpected exception is raised: {ex}") else: pytest.fail("Expected an exception but there was none") wait_before_test(1) - config_new = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_new = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert config_old == config_new, "Expected: config doesn't change" diff --git a/tests/suite/test_virtual_server_certmanager.py b/tests/suite/test_virtual_server_certmanager.py index 8f474d9eba..9e166d920a 100644 --- a/tests/suite/test_virtual_server_certmanager.py +++ b/tests/suite/test_virtual_server_certmanager.py @@ -1,53 +1,69 @@ -import requests import pytest - +import requests from settings import TEST_DATA -from suite.resources_utils import wait_before_test, is_secret_present, create_secret_from_yaml +from suite.resources_utils import create_secret_from_yaml, is_secret_present, wait_before_test from suite.vs_vsr_resources_utils import patch_virtual_server_from_yaml from suite.yaml_utils import get_secret_name_from_vs_yaml @pytest.mark.vs @pytest.mark.smoke -@pytest.mark.parametrize('crd_ingress_controller, create_certmanager, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources", f"-enable-cert-manager"]}, - {"issuer_name": "self-signed"}, - {"example": "virtual-server-certmanager", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, create_certmanager, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources", f"-enable-cert-manager"]}, + {"issuer_name": "self-signed"}, + {"example": "virtual-server-certmanager", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestCertManagerVirtualServer: def test_responses_after_setup(self, kube_apis, crd_ingress_controller, create_certmanager, virtual_server_setup): print("\nStep 1: Verify secret exists") wait_before_test(10) - secret_name = get_secret_name_from_vs_yaml(f"{TEST_DATA}/virtual-server-certmanager/standard/virtual-server.yaml") + secret_name = get_secret_name_from_vs_yaml( + f"{TEST_DATA}/virtual-server-certmanager/standard/virtual-server.yaml" + ) sec = is_secret_present(kube_apis.v1, secret_name, virtual_server_setup.namespace) assert sec is True print("\nStep 2: verify connectivity") - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 @pytest.mark.vs @pytest.mark.smoke -@pytest.mark.parametrize('crd_ingress_controller, create_certmanager, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources", f"-enable-cert-manager"]}, - {"issuer_name": "ca-issuer"}, - {"example": "virtual-server-certmanager", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, create_certmanager, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources", f"-enable-cert-manager"]}, + {"issuer_name": "ca-issuer"}, + {"example": "virtual-server-certmanager", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestCertManagerVirtualServerCA: def test_responses_after_setup(self, kube_apis, crd_ingress_controller, create_certmanager, virtual_server_setup): vs_src = f"{TEST_DATA}/virtual-server-certmanager/virtual-server-updated.yaml" print("\nStep 1: Verify no secret exists with bad issuer name") - secret_name = get_secret_name_from_vs_yaml(f"{TEST_DATA}/virtual-server-certmanager/standard/virtual-server.yaml") + secret_name = get_secret_name_from_vs_yaml( + f"{TEST_DATA}/virtual-server-certmanager/standard/virtual-server.yaml" + ) sec = is_secret_present(kube_apis.v1, secret_name, virtual_server_setup.namespace) assert sec is False - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace + ) print("\nStep 2: Verify secret exists with updated issuer name") - secret_name = get_secret_name_from_vs_yaml(f"{TEST_DATA}/virtual-server-certmanager/virtual-server-updated.yaml") + secret_name = get_secret_name_from_vs_yaml( + f"{TEST_DATA}/virtual-server-certmanager/virtual-server-updated.yaml" + ) sec = is_secret_present(kube_apis.v1, secret_name, virtual_server_setup.namespace) retry = 0 while not sec and retry <= 30: @@ -56,34 +72,30 @@ def test_responses_after_setup(self, kube_apis, crd_ingress_controller, create_c wait_before_test(5) print(f"Secret not found yet, retrying... #{retry}") print("\nStep 3: verify connectivity") - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 def test_virtual_server_no_cm(self, kube_apis, crd_ingress_controller, create_certmanager, virtual_server_setup): vs_src = f"{TEST_DATA}/virtual-server-certmanager/virtual-server-no-tls.yaml" - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace + ) print("\nStep 1: verify connectivity with no TLS block") - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 print("\nStep 2: verify connectivity with TLS block but no cert-manager") vs_src = f"{TEST_DATA}/virtual-server-certmanager/virtual-server-no-cm.yaml" secret_src = f"{TEST_DATA}/virtual-server-certmanager/tls-secret.yaml" create_secret_from_yaml(kube_apis.v1, virtual_server_setup.namespace, secret_src) - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, - virtual_server_setup.namespace) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace + ) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) assert resp.status_code == 200 diff --git a/tests/suite/test_virtual_server_configmap_keys.py b/tests/suite/test_virtual_server_configmap_keys.py index ca1e6fafee..c42eee0dce 100644 --- a/tests/suite/test_virtual_server_configmap_keys.py +++ b/tests/suite/test_virtual_server_configmap_keys.py @@ -1,8 +1,13 @@ import pytest - -from settings import TEST_DATA, DEPLOYMENTS -from suite.resources_utils import wait_before_test, replace_configmap_from_yaml, get_events, get_first_pod_name, \ - get_file_contents, get_pods_amount +from settings import DEPLOYMENTS, TEST_DATA +from suite.resources_utils import ( + get_events, + get_file_contents, + get_first_pod_name, + get_pods_amount, + replace_configmap_from_yaml, + wait_before_test, +) from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf from suite.yaml_utils import get_configmap_fields_from_yaml @@ -28,7 +33,7 @@ def assert_update_event_count_increased(virtual_server_setup, new_list, previous item_name = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" text_valid = f"Configuration for {item_name} was added or updated" text_invalid = "but was not applied" - for i in range(len(previous_list)-1, 0, -1): + for i in range(len(previous_list) - 1, 0, -1): if text_valid in previous_list[i].message and text_invalid not in previous_list[i].message: assert new_list[i].count - previous_list[i].count == 1, "We expect the counter to increase" @@ -67,34 +72,35 @@ def assert_keys_with_validation_in_main_config(config, expected_values): def assert_specific_keys_for_nginx_plus(config, expected_values): # based on f"{TEST_DATA}/virtual-server-configmap-keys/configmap-validation-keys.yaml" assert f"server_tokens \"{expected_values['server-tokens']}\";" in config - assert "random two least_conn;" not in config \ - and expected_values['lb-method'] in config + assert "random two least_conn;" not in config and expected_values["lb-method"] in config assert "zone " in config and " 512k;" in config def assert_specific_keys_for_nginx_oss(config, expected_values): # based on f"{TEST_DATA}/virtual-server-configmap-keys/configmap-validation-keys-oss.yaml" - assert "server_tokens \"off\"" in config - assert "random two least_conn;" not in config \ - and expected_values['lb-method'] in config + assert 'server_tokens "off"' in config + assert "random two least_conn;" not in config and expected_values["lb-method"] in config assert "zone " not in config and " 256k;" not in config + def assert_defaults_of_keys_with_validation_for_nginx_plus(config, unexpected_values): assert_common_defaults_of_keys_with_validation(config, unexpected_values) assert "zone " in config and " 512k;" in config + def assert_defaults_of_keys_with_validation_for_nginx_oss(config, unexpected_values): assert_common_defaults_of_keys_with_validation(config, unexpected_values) assert "zone " in config and " 256k;" in config + def assert_common_defaults_of_keys_with_validation(config, unexpected_values): assert "proxy_buffering on;" in config assert "real_ip_recursive" not in config assert "max_fails=1" in config assert "keepalive" not in config assert "listen 80;" in config - assert "server_tokens \"on\"" in config - assert "random two least_conn;" in config and unexpected_values['lb-method'] not in config + assert 'server_tokens "on"' in config + assert "random two least_conn;" in config and unexpected_values["lb-method"] not in config assert f"proxy_send_timeout 60s;" in config @@ -130,63 +136,88 @@ def clean_up(request, kube_apis, ingress_controller_prerequisites, test_namespac """ def fin(): - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - f"{DEPLOYMENTS}/common/nginx-config.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + f"{DEPLOYMENTS}/common/nginx-config.yaml", + ) request.addfinalizer(fin) @pytest.mark.vs -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-configmap-keys", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-configmap-keys", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestVirtualServerConfigMapNoTls: - def test_keys(self, cli_arguments, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup, clean_up): + def test_keys( + self, + cli_arguments, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + virtual_server_setup, + clean_up, + ): ic_pods_amount = get_pods_amount(kube_apis.v1, ingress_controller_prerequisites.namespace) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) initial_list = get_events(kube_apis.v1, virtual_server_setup.namespace) print("Step 1: update ConfigMap with valid keys without validation rules") - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - f"{TEST_DATA}/virtual-server-configmap-keys/configmap-no-validation-keys.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + f"{TEST_DATA}/virtual-server-configmap-keys/configmap-no-validation-keys.yaml", + ) expected_values = get_configmap_fields_from_yaml( - f"{TEST_DATA}/virtual-server-configmap-keys/configmap-no-validation-keys.yaml") + f"{TEST_DATA}/virtual-server-configmap-keys/configmap-no-validation-keys.yaml" + ) wait_before_test(1) step_1_events = get_events(kube_apis.v1, virtual_server_setup.namespace) - step_1_config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + step_1_config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert_update_event_count_increased(virtual_server_setup, step_1_events, initial_list) assert_keys_without_validation(step_1_config, expected_values) print("Step 2: update ConfigMap with invalid keys without validation rules") cm_src = f"{TEST_DATA}/virtual-server-configmap-keys/configmap-no-validation-keys-invalid.yaml" - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - cm_src) + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + cm_src, + ) expected_values = get_configmap_fields_from_yaml( - f"{TEST_DATA}/virtual-server-configmap-keys/configmap-no-validation-keys-invalid.yaml") + f"{TEST_DATA}/virtual-server-configmap-keys/configmap-no-validation-keys-invalid.yaml" + ) wait_before_test(1) step_2_events = get_events(kube_apis.v1, virtual_server_setup.namespace) - step_2_config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + step_2_config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert_not_applied_events_emitted(virtual_server_setup, step_2_events, step_1_events, ic_pods_amount) assert_keys_without_validation(step_2_config, expected_values) # to cover the OSS case, this will be changed in the future - if cli_arguments['ic-type'] == "nginx-ingress": + if cli_arguments["ic-type"] == "nginx-ingress": data_file = f"{TEST_DATA}/virtual-server-configmap-keys/configmap-validation-keys-oss.yaml" data_file_invalid = f"{TEST_DATA}/virtual-server-configmap-keys/configmap-validation-keys-invalid-oss.yaml" else: @@ -194,47 +225,62 @@ def test_keys(self, cli_arguments, kube_apis, ingress_controller_prerequisites, data_file_invalid = f"{TEST_DATA}/virtual-server-configmap-keys/configmap-validation-keys-invalid.yaml" print("Step 3: update ConfigMap with valid keys with validation rules") - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - data_file) + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + data_file, + ) expected_values = get_configmap_fields_from_yaml(data_file) wait_before_test(1) - step_3_config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + step_3_config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) step_3_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_update_event_count_increased(virtual_server_setup, step_3_events, step_2_events) assert_keys_with_validation(step_3_config, expected_values) # to cover the OSS case, this will be changed in the future - if cli_arguments['ic-type'] == "nginx-ingress": + if cli_arguments["ic-type"] == "nginx-ingress": assert_specific_keys_for_nginx_oss(step_3_config, expected_values) else: assert_specific_keys_for_nginx_plus(step_3_config, expected_values) print("Step 4: update ConfigMap with invalid keys") - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - data_file_invalid) + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + data_file_invalid, + ) expected_values = get_configmap_fields_from_yaml(data_file_invalid) wait_before_test(1) - step_4_config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + step_4_config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) step_4_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_update_event_count_increased(virtual_server_setup, step_4_events, step_3_events) - if cli_arguments['ic-type'] == "nginx-ingress": + if cli_arguments["ic-type"] == "nginx-ingress": assert_defaults_of_keys_with_validation_for_nginx_oss(step_4_config, expected_values) else: assert_defaults_of_keys_with_validation_for_nginx_plus(step_4_config, expected_values) - def test_keys_in_main_config(self, cli_arguments, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup, clean_up): + def test_keys_in_main_config( + self, + cli_arguments, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + virtual_server_setup, + clean_up, + ): wait_before_test(1) ic_pods_amount = get_pods_amount(kube_apis.v1, ingress_controller_prerequisites.namespace) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) @@ -244,27 +290,33 @@ def test_keys_in_main_config(self, cli_arguments, kube_apis, ingress_controller_ config_path = "/etc/nginx/nginx.conf" print("Step 5: main config: update ConfigMap with valid keys with validation rules") - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - data_file) + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + data_file, + ) expected_values = get_configmap_fields_from_yaml(data_file) wait_before_test(1) - step_5_config = get_file_contents(kube_apis.v1, - config_path, ic_pod_name, ingress_controller_prerequisites.namespace) + step_5_config = get_file_contents( + kube_apis.v1, config_path, ic_pod_name, ingress_controller_prerequisites.namespace + ) step_5_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_update_event_count_increased(virtual_server_setup, step_5_events, initial_list) assert_keys_with_validation_in_main_config(step_5_config, expected_values) print("Step 6: main config: update ConfigMap with invalid keys") - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - data_file_invalid) + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + data_file_invalid, + ) unexpected_values = get_configmap_fields_from_yaml(data_file_invalid) wait_before_test(1) - step_6_config = get_file_contents(kube_apis.v1, - config_path, ic_pod_name, ingress_controller_prerequisites.namespace) + step_6_config = get_file_contents( + kube_apis.v1, config_path, ic_pod_name, ingress_controller_prerequisites.namespace + ) step_6_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_update_event_count_increased(virtual_server_setup, step_6_events, step_5_events) assert_defaults_of_keys_with_validation_in_main_config(step_6_config, unexpected_values) @@ -272,56 +324,80 @@ def test_keys_in_main_config(self, cli_arguments, kube_apis, ingress_controller_ print("Step 7: main config: special case for hash variables") data_file = f"{TEST_DATA}/virtual-server-configmap-keys/configmap-global-variables.yaml" expected_values = get_configmap_fields_from_yaml(data_file) - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - data_file) + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + data_file, + ) wait_before_test(1) - step_7_config = get_file_contents(kube_apis.v1, - config_path, ic_pod_name, ingress_controller_prerequisites.namespace) + step_7_config = get_file_contents( + kube_apis.v1, config_path, ic_pod_name, ingress_controller_prerequisites.namespace + ) step_7_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_not_applied_events_emitted(virtual_server_setup, step_7_events, step_6_events, ic_pods_amount) assert_keys_with_validation_in_main_config(step_7_config, expected_values) @pytest.mark.vs -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-tls", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-tls", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestVirtualServerConfigMapWithTls: - def test_ssl_keys(self, cli_arguments, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - virtual_server_setup, clean_up): + def test_ssl_keys( + self, + cli_arguments, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + virtual_server_setup, + clean_up, + ): ic_pods_amount = get_pods_amount(kube_apis.v1, ingress_controller_prerequisites.namespace) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) initial_list = get_events(kube_apis.v1, virtual_server_setup.namespace) print("Step 1: update ConfigMap with valid ssl keys") - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - f"{TEST_DATA}/virtual-server-configmap-keys/configmap-ssl-keys.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + f"{TEST_DATA}/virtual-server-configmap-keys/configmap-ssl-keys.yaml", + ) wait_before_test(1) step_1_events = get_events(kube_apis.v1, virtual_server_setup.namespace) - step_1_config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + step_1_config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert_update_event_count_increased(virtual_server_setup, step_1_events, initial_list) assert_ssl_keys(step_1_config) print("Step 2: update ConfigMap with invalid ssl keys") - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - f"{TEST_DATA}/virtual-server-configmap-keys/configmap-ssl-keys-invalid.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + f"{TEST_DATA}/virtual-server-configmap-keys/configmap-ssl-keys-invalid.yaml", + ) wait_before_test(1) step_2_events = get_events(kube_apis.v1, virtual_server_setup.namespace) - step_2_config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + step_2_config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert_update_event_count_increased(virtual_server_setup, step_2_events, step_1_events) assert_defaults_of_ssl_keys(step_2_config) diff --git a/tests/suite/test_virtual_server_dos.py b/tests/suite/test_virtual_server_dos.py index 615d59a9aa..b522621e75 100644 --- a/tests/suite/test_virtual_server_dos.py +++ b/tests/suite/test_virtual_server_dos.py @@ -5,7 +5,6 @@ import pytest import requests - from settings import TEST_DATA from suite.custom_resources_utils import ( create_dos_logconf_from_yaml, diff --git a/tests/suite/test_virtual_server_error_pages.py b/tests/suite/test_virtual_server_error_pages.py index 71b0f08d45..508a76f3b1 100644 --- a/tests/suite/test_virtual_server_error_pages.py +++ b/tests/suite/test_virtual_server_error_pages.py @@ -1,123 +1,160 @@ -import pytest import json + +import pytest import requests from kubernetes.client.rest import ApiException - -from suite.custom_assertions import wait_and_assert_status_code, assert_vs_conf_not_exists, \ - assert_event_starts_with_text_and_contains_errors from settings import TEST_DATA -from suite.vs_vsr_resources_utils import patch_virtual_server_from_yaml, get_vs_nginx_template_conf -from suite.resources_utils import wait_before_test, get_first_pod_name, get_events +from suite.custom_assertions import ( + assert_event_starts_with_text_and_contains_errors, + assert_vs_conf_not_exists, + wait_and_assert_status_code, +) +from suite.resources_utils import get_events, get_first_pod_name, wait_before_test +from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, patch_virtual_server_from_yaml @pytest.mark.vs -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-error-pages", "app_type": None})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-error-pages", "app_type": None}, + ) + ], + indirect=True, +) class TestVSErrorPages: def test_redirect_strategy(self, kube_apis, crd_ingress_controller, virtual_server_setup): - wait_and_assert_status_code(307, virtual_server_setup.backend_1_url, - virtual_server_setup.vs_host, allow_redirects=False) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}, allow_redirects=False) - assert f'http://{virtual_server_setup.vs_host}/error.html' in resp.next.url + wait_and_assert_status_code( + 307, virtual_server_setup.backend_1_url, virtual_server_setup.vs_host, allow_redirects=False + ) + resp = requests.get( + virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False + ) + assert f"http://{virtual_server_setup.vs_host}/error.html" in resp.next.url def test_return_strategy(self, kube_apis, crd_ingress_controller, virtual_server_setup): wait_and_assert_status_code(207, virtual_server_setup.backend_2_url, virtual_server_setup.vs_host) - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) resp_content = json.loads(resp.content) - assert resp_content['status'] == '502' \ - and resp_content['message'] == 'Forbidden' \ - and resp.headers.get('x-debug-original-status') == '502' + assert ( + resp_content["status"] == "502" + and resp_content["message"] == "Forbidden" + and resp.headers.get("x-debug-original-status") == "502" + ) def test_virtual_server_after_update(self, kube_apis, crd_ingress_controller, virtual_server_setup): - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-error-pages/virtual-server-updated.yaml", - virtual_server_setup.namespace) - wait_and_assert_status_code(301, virtual_server_setup.backend_1_url, - virtual_server_setup.vs_host, allow_redirects=False) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, - allow_redirects=False) - assert f'http://{virtual_server_setup.vs_host}/error_http.html' in resp.next.url + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-error-pages/virtual-server-updated.yaml", + virtual_server_setup.namespace, + ) + wait_and_assert_status_code( + 301, virtual_server_setup.backend_1_url, virtual_server_setup.vs_host, allow_redirects=False + ) + resp = requests.get( + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, + allow_redirects=False, + ) + assert f"http://{virtual_server_setup.vs_host}/error_http.html" in resp.next.url wait_and_assert_status_code(502, virtual_server_setup.backend_2_url, virtual_server_setup.vs_host) - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) - resp_content = resp.content.decode('utf-8') - assert resp_content == 'Hello World!\n' + resp = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) + resp_content = resp.content.decode("utf-8") + assert resp_content == "Hello World!\n" - def test_validation_event_flow(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - virtual_server_setup): + def test_validation_event_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): invalid_fields = [ "spec.routes[0].errorPages[0].redirect.url: Invalid value", "spec.routes[0].errorPages[0].redirect.code: Invalid value: 101", - "spec.routes[1].errorPages[0].return.body: Invalid value: \"status\"", + 'spec.routes[1].errorPages[0].return.body: Invalid value: "status"', "spec.routes[1].errorPages[0].return.code: Invalid value: 100", - "spec.routes[1].errorPages[0].return.headers[0].value: Invalid value: \"schema\"" + 'spec.routes[1].errorPages[0].return.headers[0].value: Invalid value: "schema"', ] text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"VirtualServer {text} was rejected with error:" vs_file = f"{TEST_DATA}/virtual-server-error-pages/virtual-server-invalid.yaml" - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - vs_file, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_file, virtual_server_setup.namespace + ) wait_before_test(2) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_starts_with_text_and_contains_errors(vs_event_text, vs_events, invalid_fields) - assert_vs_conf_not_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, - virtual_server_setup) + assert_vs_conf_not_exists( + kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, virtual_server_setup + ) - def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): + def test_openapi_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config_old = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_old = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) vs_file = f"{TEST_DATA}/virtual-server-error-pages/virtual-server-invalid-openapi.yaml" try: - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_file, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_file, virtual_server_setup.namespace + ) except ApiException as ex: - assert ex.status == 422 \ - and "codes in body must be of type" in ex.body \ - and "redirect.code in body must be of type" in ex.body \ - and "redirect.url in body must be of type" in ex.body \ - and "return.code in body must be of type" in ex.body \ - and "return.type in body must be of type" in ex.body \ - and "return.body in body must be of type" in ex.body \ - and "name in body must be of type" in ex.body \ - and "value in body must be of type" in ex.body + assert ( + ex.status == 422 + and "codes in body must be of type" in ex.body + and "redirect.code in body must be of type" in ex.body + and "redirect.url in body must be of type" in ex.body + and "return.code in body must be of type" in ex.body + and "return.type in body must be of type" in ex.body + and "return.body in body must be of type" in ex.body + and "name in body must be of type" in ex.body + and "value in body must be of type" in ex.body + ) except Exception as ex: pytest.fail(f"An unexpected exception is raised: {ex}") else: pytest.fail("Expected an exception but there was none") wait_before_test(1) - config_new = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_new = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert config_old == config_new, "Expected: config doesn't change" - @pytest.mark.parametrize('v_s_data', [ - {"src": "virtual-server-splits.yaml", "expected_code": 308}, - {"src": "virtual-server-matches.yaml", "expected_code": 307} - ]) + @pytest.mark.parametrize( + "v_s_data", + [ + {"src": "virtual-server-splits.yaml", "expected_code": 308}, + {"src": "virtual-server-matches.yaml", "expected_code": 307}, + ], + ) def test_splits_and_matches(self, kube_apis, crd_ingress_controller, virtual_server_setup, v_s_data): - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-error-pages/{v_s_data['src']}", - virtual_server_setup.namespace) - wait_and_assert_status_code(v_s_data['expected_code'], virtual_server_setup.backend_1_url, - virtual_server_setup.vs_host, allow_redirects=False) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}, allow_redirects=False) - assert f'http://{virtual_server_setup.vs_host}/error.html' in resp.next.url + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-error-pages/{v_s_data['src']}", + virtual_server_setup.namespace, + ) + wait_and_assert_status_code( + v_s_data["expected_code"], + virtual_server_setup.backend_1_url, + virtual_server_setup.vs_host, + allow_redirects=False, + ) + resp = requests.get( + virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False + ) + assert f"http://{virtual_server_setup.vs_host}/error.html" in resp.next.url diff --git a/tests/suite/test_virtual_server_external_name.py b/tests/suite/test_virtual_server_external_name.py index 0759208738..db47055085 100644 --- a/tests/suite/test_virtual_server_external_name.py +++ b/tests/suite/test_virtual_server_external_name.py @@ -1,13 +1,29 @@ import pytest - from settings import TEST_DATA -from suite.custom_assertions import assert_event_and_count, assert_event_and_get_count, wait_and_assert_status_code, \ - wait_for_event_count_increases, assert_event_with_full_equality_and_count +from suite.custom_assertions import ( + assert_event_and_count, + assert_event_and_get_count, + assert_event_with_full_equality_and_count, + wait_and_assert_status_code, + wait_for_event_count_increases, +) +from suite.resources_utils import ( + create_deployment_with_name, + create_namespace_with_name_from_yaml, + create_service_from_yaml, + create_service_with_name, + delete_namespace, + ensure_connection_to_public_endpoint, + ensure_response_from_backend, + get_events, + get_first_pod_name, + read_service, + replace_configmap, + replace_configmap_from_yaml, + replace_service, + wait_before_test, +) from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf -from suite.resources_utils import replace_configmap_from_yaml, \ - ensure_connection_to_public_endpoint, replace_configmap, create_service_from_yaml, get_first_pod_name, get_events, \ - read_service, replace_service, wait_before_test, delete_namespace, create_service_with_name, \ - create_deployment_with_name, create_namespace_with_name_from_yaml, ensure_response_from_backend class ExternalNameSetup: @@ -17,6 +33,7 @@ class ExternalNameSetup: ic_pod_name: external_host: external service host """ + def __init__(self, ic_pod_name, external_svc, external_host): self.ic_pod_name = ic_pod_name self.external_svc = external_svc @@ -24,10 +41,9 @@ def __init__(self, ic_pod_name, external_svc, external_host): @pytest.fixture(scope="class") -def vs_externalname_setup(request, - kube_apis, - ingress_controller_prerequisites, - virtual_server_setup) -> ExternalNameSetup: +def vs_externalname_setup( + request, kube_apis, ingress_controller_prerequisites, virtual_server_setup +) -> ExternalNameSetup: print("------------------------- Deploy External-Backend -----------------------------------") external_ns = create_namespace_with_name_from_yaml(kube_apis.v1, "external-ns", f"{TEST_DATA}/common/ns.yaml") external_svc_name = create_service_with_name(kube_apis.v1, external_ns, "external-backend-svc") @@ -36,23 +52,31 @@ def vs_externalname_setup(request, external_svc_src = f"{TEST_DATA}/virtual-server-externalname/externalname-svc.yaml" external_svc_host = f"{external_svc_name}.{external_ns}.svc.cluster.local" config_map_name = ingress_controller_prerequisites.config_map["metadata"]["name"] - replace_configmap_from_yaml(kube_apis.v1, config_map_name, - ingress_controller_prerequisites.namespace, - f"{TEST_DATA}/virtual-server-externalname/nginx-config.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + config_map_name, + ingress_controller_prerequisites.namespace, + f"{TEST_DATA}/virtual-server-externalname/nginx-config.yaml", + ) external_svc = create_service_from_yaml(kube_apis.v1, virtual_server_setup.namespace, external_svc_src) wait_before_test(2) - ensure_connection_to_public_endpoint(virtual_server_setup.public_endpoint.public_ip, - virtual_server_setup.public_endpoint.port, - virtual_server_setup.public_endpoint.port_ssl) + ensure_connection_to_public_endpoint( + virtual_server_setup.public_endpoint.public_ip, + virtual_server_setup.public_endpoint.port, + virtual_server_setup.public_endpoint.port_ssl, + ) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) ensure_response_from_backend(virtual_server_setup.backend_1_url, virtual_server_setup.vs_host) def fin(): print("Clean up ExternalName Setup:") delete_namespace(kube_apis.v1, external_ns) - replace_configmap(kube_apis.v1, config_map_name, - ingress_controller_prerequisites.namespace, - ingress_controller_prerequisites.config_map) + replace_configmap( + kube_apis.v1, + config_map_name, + ingress_controller_prerequisites.namespace, + ingress_controller_prerequisites.config_map, + ) request.addfinalizer(fin) @@ -61,31 +85,51 @@ def fin(): @pytest.mark.vs @pytest.mark.skip_for_nginx_oss -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources", "-v=3"]}, - {"example": "virtual-server-externalname", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources", "-v=3"]}, + {"example": "virtual-server-externalname", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestVSWithExternalNameService: def test_response(self, kube_apis, crd_ingress_controller, virtual_server_setup, vs_externalname_setup): - wait_and_assert_status_code(200, virtual_server_setup.backend_1_url, - virtual_server_setup.vs_host) - - def test_template_config(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, - virtual_server_setup, vs_externalname_setup): - result_conf = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - vs_externalname_setup.ic_pod_name, - ingress_controller_prerequisites.namespace) + wait_and_assert_status_code(200, virtual_server_setup.backend_1_url, virtual_server_setup.vs_host) + + def test_template_config( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + virtual_server_setup, + vs_externalname_setup, + ): + result_conf = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + vs_externalname_setup.ic_pod_name, + ingress_controller_prerequisites.namespace, + ) line = f"zone vs_{virtual_server_setup.namespace}_{virtual_server_setup.vs_name}_backend1 512k;" assert line in result_conf assert "random two least_conn;" in result_conf - assert f"server {vs_externalname_setup.external_host}:80 max_fails=1 fail_timeout=10s max_conns=0 resolve;"\ - in result_conf - - def test_events_flows(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup, vs_externalname_setup): + assert ( + f"server {vs_externalname_setup.external_host}:80 max_fails=1 fail_timeout=10s max_conns=0 resolve;" + in result_conf + ) + + def test_events_flows( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + virtual_server_setup, + vs_externalname_setup, + ): text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"Configuration for {text} was added or updated" wait_before_test(10) @@ -105,9 +149,12 @@ def test_events_flows(self, kube_apis, ingress_controller_prerequisites, print("Step 2: Remove resolver from ConfigMap to trigger an error") config_map_name = ingress_controller_prerequisites.config_map["metadata"]["name"] vs_event_warning_text = f"Configuration for {text} was added or updated ; with warning(s):" - replace_configmap(kube_apis.v1, config_map_name, - ingress_controller_prerequisites.namespace, - ingress_controller_prerequisites.config_map) + replace_configmap( + kube_apis.v1, + config_map_name, + ingress_controller_prerequisites.namespace, + ingress_controller_prerequisites.config_map, + ) wait_before_test(10) events_step_2 = get_events(kube_apis.v1, virtual_server_setup.namespace) diff --git a/tests/suite/test_virtual_server_externaldns.py b/tests/suite/test_virtual_server_externaldns.py index 574a92c6f2..a674afd23b 100644 --- a/tests/suite/test_virtual_server_externaldns.py +++ b/tests/suite/test_virtual_server_externaldns.py @@ -1,33 +1,41 @@ import pytest - from settings import TEST_DATA from suite.custom_assertions import assert_event from suite.custom_resources_utils import is_dnsendpoint_present -from suite.resources_utils import wait_before_test, get_events +from suite.resources_utils import get_events, wait_before_test from suite.vs_vsr_resources_utils import patch_virtual_server_from_yaml from suite.yaml_utils import get_first_host_from_yaml, get_namespace_from_yaml - VS_YAML = f"{TEST_DATA}/virtual-server-external-dns/standard/virtual-server.yaml" + @pytest.mark.vs @pytest.mark.smoke -@pytest.mark.parametrize('crd_ingress_controller_with_ed, create_externaldns, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources", f"-enable-external-dns"]}, - {}, {"example": "virtual-server-external-dns", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller_with_ed, create_externaldns, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources", f"-enable-external-dns"]}, + {}, + {"example": "virtual-server-external-dns", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestExternalDNSVirtualServer: - def test_responses_after_setup(self, kube_apis, crd_ingress_controller_with_ed, create_externaldns, virtual_server_setup): + def test_responses_after_setup( + self, kube_apis, crd_ingress_controller_with_ed, create_externaldns, virtual_server_setup + ): print("\nStep 1: Verify DNSEndpoint exists") dns_name = get_first_host_from_yaml(VS_YAML) retry = 0 - dep = is_dnsendpoint_present(kube_apis.custom_objects, dns_name, virtual_server_setup.namespace) + dep = is_dnsendpoint_present(kube_apis.custom_objects, dns_name, virtual_server_setup.namespace) while dep == False and retry <= 60: dep = is_dnsendpoint_present(kube_apis.custom_objects, dns_name, virtual_server_setup.namespace) retry += 1 wait_before_test(1) print(f"DNSEndpoint not created, retrying... #{retry}") - assert(dep is True) + assert dep is True print("\nStep 2: Verify external-dns picked up the record") pod_ns = get_namespace_from_yaml(f"{TEST_DATA}/virtual-server-external-dns/external-dns.yaml") pod_name = kube_apis.v1.list_namespaced_pod(pod_ns).items[0].metadata.name @@ -39,9 +47,11 @@ def test_responses_after_setup(self, kube_apis, crd_ingress_controller_with_ed, retry += 1 wait_before_test(1) print(f"External DNS not updated, retrying... #{retry}") - assert(wanted_string in log_contents) + assert wanted_string in log_contents - def test_update_to_ed_in_vs(self, kube_apis, crd_ingress_controller_with_ed, create_externaldns, virtual_server_setup): + def test_update_to_ed_in_vs( + self, kube_apis, crd_ingress_controller_with_ed, create_externaldns, virtual_server_setup + ): print("\nStep 1: Update VirtualServer") patch_src = f"{TEST_DATA}/virtual-server-external-dns/virtual-server-updated.yaml" patch_virtual_server_from_yaml( diff --git a/tests/suite/test_virtual_server_focused_canary.py b/tests/suite/test_virtual_server_focused_canary.py index 14a16066a7..5c7f7ecb7c 100644 --- a/tests/suite/test_virtual_server_focused_canary.py +++ b/tests/suite/test_virtual_server_focused_canary.py @@ -1,8 +1,6 @@ import pytest - import requests import yaml - from settings import TEST_DATA @@ -17,8 +15,8 @@ def get_weights_of_splitting(file) -> []: with open(file) as f: docs = yaml.safe_load_all(f) for dep in docs: - for item in dep['spec']['routes'][0]['matches'][0]['splits']: - weights.append(item['weight']) + for item in dep["spec"]["routes"][0]["matches"][0]["splits"]: + weights.append(item["weight"]) return weights @@ -33,29 +31,37 @@ def get_upstreams_of_splitting(file) -> []: with open(file) as f: docs = yaml.safe_load_all(f) for dep in docs: - for item in dep['spec']['routes'][0]['matches'][0]['splits']: - upstreams.append(item['action']['pass']) + for item in dep["spec"]["routes"][0]["matches"][0]["splits"]: + upstreams.append(item["action"]["pass"]) return upstreams @pytest.mark.vs -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-focused-canary", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-focused-canary", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestVSFocusedCanaryRelease: def test_several_requests(self, kube_apis, crd_ingress_controller, virtual_server_setup): - weights = get_weights_of_splitting( - f"{TEST_DATA}/virtual-server-focused-canary/standard/virtual-server.yaml") + weights = get_weights_of_splitting(f"{TEST_DATA}/virtual-server-focused-canary/standard/virtual-server.yaml") upstreams = get_upstreams_of_splitting( - f"{TEST_DATA}/virtual-server-focused-canary/standard/virtual-server.yaml") + f"{TEST_DATA}/virtual-server-focused-canary/standard/virtual-server.yaml" + ) sum_weights = sum(weights) - ratios = [round(i/sum_weights, 1) for i in weights] + ratios = [round(i / sum_weights, 1) for i in weights] counter_v1, counter_v2 = 0, 0 for _ in range(100): - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host, "x-version": "canary"}) + resp = requests.get( + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host, "x-version": "canary"}, + ) if upstreams[0] in resp.text in resp.text: counter_v1 = counter_v1 + 1 elif upstreams[1] in resp.text in resp.text: @@ -63,5 +69,5 @@ def test_several_requests(self, kube_apis, crd_ingress_controller, virtual_serve else: pytest.fail(f"An unexpected backend in response: {resp.text}") - assert abs(round(counter_v1/(counter_v1 + counter_v2), 1) - ratios[0]) <= 0.2 - assert abs(round(counter_v2/(counter_v1 + counter_v2), 1) - ratios[1]) <= 0.2 + assert abs(round(counter_v1 / (counter_v1 + counter_v2), 1) - ratios[0]) <= 0.2 + assert abs(round(counter_v2 / (counter_v1 + counter_v2), 1) - ratios[1]) <= 0.2 diff --git a/tests/suite/test_virtual_server_grpc.py b/tests/suite/test_virtual_server_grpc.py index 667d24cc55..289c2ffb16 100644 --- a/tests/suite/test_virtual_server_grpc.py +++ b/tests/suite/test_virtual_server_grpc.py @@ -1,19 +1,30 @@ import grpc import pytest - -from settings import TEST_DATA, DEPLOYMENTS -from suite.custom_assertions import assert_event_starts_with_text_and_contains_errors, \ - assert_grpc_entries_exist, assert_proxy_entries_do_not_exist, \ - assert_vs_conf_not_exists, assert_event +from settings import DEPLOYMENTS, TEST_DATA +from suite.custom_assertions import ( + assert_event, + assert_event_starts_with_text_and_contains_errors, + assert_grpc_entries_exist, + assert_proxy_entries_do_not_exist, + assert_vs_conf_not_exists, +) from suite.grpc.helloworld_pb2 import HelloRequest from suite.grpc.helloworld_pb2_grpc import GreeterStub -from suite.resources_utils import create_example_app, wait_until_all_pods_are_ready, \ - delete_common_app, create_secret_from_yaml, replace_configmap_from_yaml, \ - delete_items_from_yaml, get_first_pod_name, get_events, wait_before_test, \ - scale_deployment, get_last_log_entry +from suite.resources_utils import ( + create_example_app, + create_secret_from_yaml, + delete_common_app, + delete_items_from_yaml, + get_events, + get_first_pod_name, + get_last_log_entry, + replace_configmap_from_yaml, + scale_deployment, + wait_before_test, + wait_until_all_pods_are_ready, +) from suite.ssl_utils import get_certificate -from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, \ - patch_virtual_server_from_yaml +from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, patch_virtual_server_from_yaml @pytest.fixture(scope="function") @@ -29,10 +40,12 @@ def backend_setup(request, kube_apis, ingress_controller_prerequisites, test_nam try: print("------------------------- Replace ConfigMap with HTTP2 -------------------------") cm_source = f"{TEST_DATA}/virtual-server-grpc/nginx-config.yaml" - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - cm_source) + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + cm_source, + ) print("------------------------- Deploy Secret -----------------------------") src_sec_yaml = f"{TEST_DATA}/virtual-server-grpc/tls-secret.yaml" create_secret_from_yaml(kube_apis.v1, test_namespace, src_sec_yaml) @@ -43,32 +56,37 @@ def backend_setup(request, kube_apis, ingress_controller_prerequisites, test_nam except Exception as ex: print("Failed to complete setup, cleaning up..") delete_items_from_yaml(kube_apis, src_sec_yaml, test_namespace) - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - f"{DEPLOYMENTS}/common/nginx-config.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + f"{DEPLOYMENTS}/common/nginx-config.yaml", + ) delete_common_app(kube_apis, app_name, test_namespace) pytest.fail(f"VS GRPC setup failed") def fin(): print("Clean up:") delete_items_from_yaml(kube_apis, src_sec_yaml, test_namespace) - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - f"{DEPLOYMENTS}/common/nginx-config.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + f"{DEPLOYMENTS}/common/nginx-config.yaml", + ) delete_common_app(kube_apis, app_name, test_namespace) request.addfinalizer(fin) + @pytest.mark.vs @pytest.mark.smoke -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-grpc"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, {"example": "virtual-server-grpc"})], + indirect=True, +) class TestVirtualServerGrpc: - def patch_valid_vs(self, kube_apis, virtual_server_setup) -> None: """ Function to revert vs deployment to valid state @@ -82,27 +100,33 @@ def patch_valid_vs(self, kube_apis, virtual_server_setup) -> None: ) @pytest.mark.parametrize("backend_setup", [{"app_type": "grpc-vs"}], indirect=True) - def test_config_after_setup(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - backend_setup, virtual_server_setup): + def test_config_after_setup( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, virtual_server_setup + ): print("\nStep 1: assert config") ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert_grpc_entries_exist(config) assert_proxy_entries_do_not_exist(config) @pytest.mark.parametrize("backend_setup", [{"app_type": "grpc-vs"}], indirect=True) - def test_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, backend_setup, virtual_server_setup): + def test_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, virtual_server_setup + ): print("\nTest 1: Wrong type") - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-grpc/virtual-server-invalid-type.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-grpc/virtual-server-invalid-type.yaml", + virtual_server_setup.namespace, + ) wait_before_test() text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" event_text1 = f"VirtualServer {text} was rejected with error:" @@ -115,14 +139,17 @@ def test_validation_flow(self, kube_apis, ingress_controller_prerequisites, @pytest.mark.flaky(max_runs=3) @pytest.mark.parametrize("backend_setup", [{"app_type": "grpc-vs"}], indirect=True) - def test_connect_grpc_backend(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - backend_setup, virtual_server_setup) -> None: - cert = get_certificate(virtual_server_setup.public_endpoint.public_ip, - virtual_server_setup.vs_host, - virtual_server_setup.public_endpoint.port_ssl) - target = f'{virtual_server_setup.public_endpoint.public_ip}:{virtual_server_setup.public_endpoint.port_ssl}' + def test_connect_grpc_backend( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, virtual_server_setup + ) -> None: + cert = get_certificate( + virtual_server_setup.public_endpoint.public_ip, + virtual_server_setup.vs_host, + virtual_server_setup.public_endpoint.port_ssl, + ) + target = f"{virtual_server_setup.public_endpoint.public_ip}:{virtual_server_setup.public_endpoint.port_ssl}" credentials = grpc.ssl_channel_credentials(root_certificates=cert.encode()) - options = (('grpc.ssl_target_name_override', virtual_server_setup.vs_host),) + options = (("grpc.ssl_target_name_override", virtual_server_setup.vs_host),) with grpc.secure_channel(target, credentials, options) as channel: stub = GreeterStub(channel) @@ -137,14 +164,17 @@ def test_connect_grpc_backend(self, kube_apis, ingress_controller_prerequisites, @pytest.mark.flaky(max_runs=3) @pytest.mark.parametrize("backend_setup", [{"app_type": "grpc-vs"}], indirect=True) - def test_grpc_error_intercept(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - backend_setup, virtual_server_setup): - cert = get_certificate(virtual_server_setup.public_endpoint.public_ip, - virtual_server_setup.vs_host, - virtual_server_setup.public_endpoint.port_ssl) - target = f'{virtual_server_setup.public_endpoint.public_ip}:{virtual_server_setup.public_endpoint.port_ssl}' + def test_grpc_error_intercept( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, virtual_server_setup + ): + cert = get_certificate( + virtual_server_setup.public_endpoint.public_ip, + virtual_server_setup.vs_host, + virtual_server_setup.public_endpoint.port_ssl, + ) + target = f"{virtual_server_setup.public_endpoint.public_ip}:{virtual_server_setup.public_endpoint.port_ssl}" credentials = grpc.ssl_channel_credentials(root_certificates=cert.encode()) - options = (('grpc.ssl_target_name_override', virtual_server_setup.vs_host),) + options = (("grpc.ssl_target_name_override", virtual_server_setup.vs_host),) with grpc.secure_channel(target, credentials, options) as channel: stub = GreeterStub(channel) @@ -162,8 +192,7 @@ def test_grpc_error_intercept(self, kube_apis, ingress_controller_prerequisites, log_contents = kube_apis.v1.read_namespaced_pod_log(ic_pod_name, ingress_controller_prerequisites.namespace) retry = 0 while '"POST /helloworld.Greeter/SayHello HTTP/2.0" 200 0' not in log_contents and retry <= 60: - log_contents = kube_apis.v1.read_namespaced_pod_log( - ic_pod_name, ingress_controller_prerequisites.namespace) + log_contents = kube_apis.v1.read_namespaced_pod_log(ic_pod_name, ingress_controller_prerequisites.namespace) retry += 1 wait_before_test(1) print(f"Logs not yet updated, retrying... #{retry}") @@ -189,21 +218,23 @@ def test_grpc_error_intercept(self, kube_apis, ingress_controller_prerequisites, log_contents = kube_apis.v1.read_namespaced_pod_log(ic_pod_name, ingress_controller_prerequisites.namespace) retry = 0 while '"POST /helloworld.Greeter/SayHello HTTP/2.0" 204 14' not in log_contents and retry <= 60: - log_contents = kube_apis.v1.read_namespaced_pod_log( - ic_pod_name, ingress_controller_prerequisites.namespace) + log_contents = kube_apis.v1.read_namespaced_pod_log(ic_pod_name, ingress_controller_prerequisites.namespace) retry += 1 wait_before_test(1) print(f"Logs not yet updated, retrying... #{retry}") @pytest.mark.parametrize("backend_setup", [{"app_type": "grpc-vs"}], indirect=True) - def test_config_error_page_warning(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - backend_setup, virtual_server_setup): + def test_config_error_page_warning( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, virtual_server_setup + ): text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_warning_text = f"Configuration for {text} was added or updated ; with warning(s): " - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-grpc/virtual-server-error-page.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-grpc/virtual-server-error-page.yaml", + virtual_server_setup.namespace, + ) wait_before_test(5) events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event(vs_event_warning_text, events) @@ -211,64 +242,85 @@ def test_config_error_page_warning(self, kube_apis, ingress_controller_prerequis wait_before_test() @pytest.mark.parametrize("backend_setup", [{"app_type": "grpc-vs"}], indirect=True) - def test_config_after_enable_tls(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, backend_setup, virtual_server_setup): + def test_config_after_enable_tls( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, virtual_server_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-grpc/virtual-server-updated.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-grpc/virtual-server-updated.yaml", + virtual_server_setup.namespace, + ) wait_before_test() - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - assert 'grpc_pass grpcs://' in config + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + assert "grpc_pass grpcs://" in config @pytest.mark.vs @pytest.mark.smoke @pytest.mark.skip_for_nginx_oss -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-grpc"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, {"example": "virtual-server-grpc"})], + indirect=True, +) class TestVirtualServerGrpcHealthCheck: - @pytest.mark.parametrize("backend_setup", [{"app_type": "grpc-vs"}], indirect=True) - def test_config_after_enable_healthcheck(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, backend_setup, virtual_server_setup): + def test_config_after_enable_healthcheck( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, virtual_server_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-grpc/virtual-server-healthcheck.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-grpc/virtual-server-healthcheck.yaml", + virtual_server_setup.namespace, + ) wait_before_test() - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - param_list = ["health_check port=50051 interval=1s jitter=2s", "type=grpc grpc_status=12", "grpc_service=helloworld.Greeter;"] + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + param_list = [ + "health_check port=50051 interval=1s jitter=2s", + "type=grpc grpc_status=12", + "grpc_service=helloworld.Greeter;", + ] for p in param_list: assert p in config @pytest.mark.parametrize("backend_setup", [{"app_type": "grpc-vs"}], indirect=True) - def test_grpc_healthcheck_validation(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, backend_setup, virtual_server_setup): + def test_grpc_healthcheck_validation( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, virtual_server_setup + ): invalid_fields = [ - "upstreams[0].healthCheck.path", "upstreams[0].healthCheck.statusMatch", - "upstreams[0].healthCheck.grpcStatus", "upstreams[0].healthCheck.grpcService"] + "upstreams[0].healthCheck.path", + "upstreams[0].healthCheck.statusMatch", + "upstreams[0].healthCheck.grpcStatus", + "upstreams[0].healthCheck.grpcService", + ] text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"VirtualServer {text} was rejected with error:" - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-grpc/virtual-server-healthcheck-invalid.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-grpc/virtual-server-healthcheck-invalid.yaml", + virtual_server_setup.namespace, + ) wait_before_test(2) - ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) + ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_starts_with_text_and_contains_errors(vs_event_text, vs_events, invalid_fields) - assert_vs_conf_not_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, - virtual_server_setup) + assert_vs_conf_not_exists( + kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, virtual_server_setup + ) diff --git a/tests/suite/test_virtual_server_mixed_grpc.py b/tests/suite/test_virtual_server_mixed_grpc.py index 68fddd128a..c93a7a9df3 100644 --- a/tests/suite/test_virtual_server_mixed_grpc.py +++ b/tests/suite/test_virtual_server_mixed_grpc.py @@ -1,16 +1,21 @@ import grpc import pytest import requests - -from settings import TEST_DATA, DEPLOYMENTS +from settings import DEPLOYMENTS, TEST_DATA +from suite.custom_assertions import assert_grpc_entries_exist, assert_proxy_entries_exist from suite.grpc.helloworld_pb2 import HelloRequest from suite.grpc.helloworld_pb2_grpc import GreeterStub -from suite.resources_utils import create_example_app, wait_until_all_pods_are_ready, \ - delete_common_app, create_secret_from_yaml, replace_configmap_from_yaml, \ - delete_items_from_yaml, get_first_pod_name +from suite.resources_utils import ( + create_example_app, + create_secret_from_yaml, + delete_common_app, + delete_items_from_yaml, + get_first_pod_name, + replace_configmap_from_yaml, + wait_until_all_pods_are_ready, +) from suite.ssl_utils import get_certificate from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf -from suite.custom_assertions import assert_grpc_entries_exist, assert_proxy_entries_exist @pytest.fixture(scope="function") @@ -26,10 +31,12 @@ def backend_setup(request, kube_apis, ingress_controller_prerequisites, test_nam try: print("------------------------- Replace ConfigMap with HTTP2 -------------------------") cm_source = f"{TEST_DATA}/virtual-server-grpc/nginx-config.yaml" - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - cm_source) + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + cm_source, + ) print("------------------------- Deploy Secret -----------------------------") src_sec_yaml = f"{TEST_DATA}/virtual-server-grpc/tls-secret.yaml" create_secret_from_yaml(kube_apis.v1, test_namespace, src_sec_yaml) @@ -40,42 +47,51 @@ def backend_setup(request, kube_apis, ingress_controller_prerequisites, test_nam except Exception as ex: print("Failed to complete setup, cleaning up..") delete_items_from_yaml(kube_apis, src_sec_yaml, test_namespace) - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - f"{DEPLOYMENTS}/common/nginx-config.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + f"{DEPLOYMENTS}/common/nginx-config.yaml", + ) delete_common_app(kube_apis, app_name, test_namespace) pytest.fail(f"VS GRPC setup failed") def fin(): print("Clean up:") delete_items_from_yaml(kube_apis, src_sec_yaml, test_namespace) - replace_configmap_from_yaml(kube_apis.v1, - ingress_controller_prerequisites.config_map['metadata']['name'], - ingress_controller_prerequisites.namespace, - f"{DEPLOYMENTS}/common/nginx-config.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.config_map["metadata"]["name"], + ingress_controller_prerequisites.namespace, + f"{DEPLOYMENTS}/common/nginx-config.yaml", + ) delete_common_app(kube_apis, app_name, test_namespace) request.addfinalizer(fin) + @pytest.mark.vs @pytest.mark.smoke @pytest.mark.flaky(max_runs=3) -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-grpc-mixed"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, {"example": "virtual-server-grpc-mixed"})], + indirect=True, +) class TestVirtualServerMixedUpstreamType: @pytest.mark.parametrize("backend_setup", [{"app_type": "grpc-vs-mixed"}], indirect=True) - def test_config_after_setup(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, - backend_setup, virtual_server_setup): + def test_config_after_setup( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, backend_setup, virtual_server_setup + ): print("\nStep 1: assert config") ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert_grpc_entries_exist(config) assert_proxy_entries_exist(config) @@ -87,12 +103,14 @@ def test_config_after_setup(self, kube_apis, ingress_controller_prerequisites, c assert resp.status_code == 200 print("\nStep 3: Check connection to app") - cert = get_certificate(virtual_server_setup.public_endpoint.public_ip, - virtual_server_setup.vs_host, - virtual_server_setup.public_endpoint.port_ssl) - target = f'{virtual_server_setup.public_endpoint.public_ip}:{virtual_server_setup.public_endpoint.port_ssl}' + cert = get_certificate( + virtual_server_setup.public_endpoint.public_ip, + virtual_server_setup.vs_host, + virtual_server_setup.public_endpoint.port_ssl, + ) + target = f"{virtual_server_setup.public_endpoint.public_ip}:{virtual_server_setup.public_endpoint.port_ssl}" credentials = grpc.ssl_channel_credentials(root_certificates=cert.encode()) - options = (('grpc.ssl_target_name_override', virtual_server_setup.vs_host),) + options = (("grpc.ssl_target_name_override", virtual_server_setup.vs_host),) with grpc.secure_channel(target, credentials, options) as channel: stub = GreeterStub(channel) diff --git a/tests/suite/test_virtual_server_redirects.py b/tests/suite/test_virtual_server_redirects.py index 9210554eca..6ec225f50f 100644 --- a/tests/suite/test_virtual_server_redirects.py +++ b/tests/suite/test_virtual_server_redirects.py @@ -1,41 +1,54 @@ import pytest import requests from kubernetes.client.rest import ApiException - from settings import TEST_DATA -from suite.custom_assertions import wait_and_assert_status_code, assert_event_and_get_count, \ - assert_event_count_increased, assert_event_starts_with_text_and_contains_errors -from suite.vs_vsr_resources_utils import patch_virtual_server_from_yaml, get_vs_nginx_template_conf -from suite.resources_utils import get_first_pod_name, get_events, wait_before_test +from suite.custom_assertions import ( + assert_event_and_get_count, + assert_event_count_increased, + assert_event_starts_with_text_and_contains_errors, + wait_and_assert_status_code, +) +from suite.resources_utils import get_events, get_first_pod_name, wait_before_test +from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, patch_virtual_server_from_yaml @pytest.mark.vs -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-redirects", "app_type": None})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-redirects", "app_type": None}, + ) + ], + indirect=True, +) class TestVSRedirects: def test_config(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - assert 'error_page 418 =307' in config and 'error_page 418 =301' in config + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + assert "error_page 418 =307" in config and "error_page 418 =301" in config def test_custom_redirect(self, kube_apis, crd_ingress_controller, virtual_server_setup): req_url = f"{virtual_server_setup.backend_1_url}" wait_and_assert_status_code(307, req_url, virtual_server_setup.vs_host, allow_redirects=False) resp = requests.get(req_url, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False) - assert resp.headers['location'] == "http://example.com" + assert resp.headers["location"] == "http://example.com" def test_default_redirect(self, kube_apis, crd_ingress_controller, virtual_server_setup): - wait_and_assert_status_code(301, virtual_server_setup.backend_2_url, - virtual_server_setup.vs_host, allow_redirects=False) - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}, allow_redirects=False) - assert resp.headers['location'] == f"http://{virtual_server_setup.vs_host}/default-redirect?arg=" + wait_and_assert_status_code( + 301, virtual_server_setup.backend_2_url, virtual_server_setup.vs_host, allow_redirects=False + ) + resp = requests.get( + virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False + ) + assert resp.headers["location"] == f"http://{virtual_server_setup.vs_host}/default-redirect?arg=" def test_update(self, kube_apis, crd_ingress_controller, virtual_server_setup): wait_before_test(1) @@ -44,18 +57,23 @@ def test_update(self, kube_apis, crd_ingress_controller, virtual_server_setup): events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) initial_count = assert_event_and_get_count(vs_event_text, events_vs) vs_src = f"{TEST_DATA}/virtual-server-redirects/virtual-server-updated.yaml" - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, - virtual_server_setup.namespace) - wait_and_assert_status_code(301, virtual_server_setup.backend_1_url, - virtual_server_setup.vs_host, allow_redirects=False) - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}, allow_redirects=False) - assert resp.headers['location'] == "http://demo.nginx.com" - wait_and_assert_status_code(302, virtual_server_setup.backend_2_url, - virtual_server_setup.vs_host, allow_redirects=False) - resp = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}, allow_redirects=False) - assert resp.headers['location'] == "http://demo.nginx.com" + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace + ) + wait_and_assert_status_code( + 301, virtual_server_setup.backend_1_url, virtual_server_setup.vs_host, allow_redirects=False + ) + resp = requests.get( + virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False + ) + assert resp.headers["location"] == "http://demo.nginx.com" + wait_and_assert_status_code( + 302, virtual_server_setup.backend_2_url, virtual_server_setup.vs_host, allow_redirects=False + ) + resp = requests.get( + virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False + ) + assert resp.headers["location"] == "http://demo.nginx.com" vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_count_increased(vs_event_text, initial_count, vs_events) @@ -65,40 +83,50 @@ def test_validation_flow(self, kube_apis, crd_ingress_controller, virtual_server event_text = f"VirtualServer {text} was rejected with error:" invalid_fields = ["spec.routes[0].action.redirect.code", "spec.routes[1].action.redirect.url"] vs_src = f"{TEST_DATA}/virtual-server-redirects/virtual-server-invalid.yaml" - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace + ) wait_before_test(2) - wait_and_assert_status_code(404, virtual_server_setup.backend_1_url, - virtual_server_setup.vs_host, allow_redirects=False) + wait_and_assert_status_code( + 404, virtual_server_setup.backend_1_url, virtual_server_setup.vs_host, allow_redirects=False + ) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_starts_with_text_and_contains_errors(event_text, vs_events, invalid_fields) - def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): + def test_openapi_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config_old = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_old = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) vs_src = f"{TEST_DATA}/virtual-server-redirects/virtual-server-invalid-openapi.yaml" try: - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_src, virtual_server_setup.namespace + ) except ApiException as ex: - assert ex.status == 422 \ - and "action.redirect.url in body must be of type" in ex.body \ - and "action.redirect.code in body must be of type" in ex.body + assert ( + ex.status == 422 + and "action.redirect.url in body must be of type" in ex.body + and "action.redirect.code in body must be of type" in ex.body + ) except Exception as ex: pytest.fail(f"An unexpected exception is raised: {ex}") else: pytest.fail("Expected an exception but there was none") wait_before_test(1) - config_new = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_new = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert config_old == config_new, "Expected: config doesn't change" diff --git a/tests/suite/test_virtual_server_split_traffic.py b/tests/suite/test_virtual_server_split_traffic.py index 686af1a0f2..d93c78b3a6 100644 --- a/tests/suite/test_virtual_server_split_traffic.py +++ b/tests/suite/test_virtual_server_split_traffic.py @@ -1,8 +1,6 @@ import pytest - import requests import yaml - from settings import TEST_DATA from suite.resources_utils import ensure_response_from_backend @@ -18,8 +16,8 @@ def get_weights_of_splitting(file) -> []: with open(file) as f: docs = yaml.safe_load_all(f) for dep in docs: - for item in dep['spec']['routes'][0]['splits']: - weights.append(item['weight']) + for item in dep["spec"]["routes"][0]["splits"]: + weights.append(item["weight"]) return weights @@ -34,31 +32,34 @@ def get_upstreams_of_splitting(file) -> []: with open(file) as f: docs = yaml.safe_load_all(f) for dep in docs: - for item in dep['spec']['routes'][0]['splits']: - upstreams.append(item['action']['pass']) + for item in dep["spec"]["routes"][0]["splits"]: + upstreams.append(item["action"]["pass"]) return upstreams @pytest.mark.vs @pytest.mark.smoke -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-split-traffic", "app_type": "split"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-split-traffic", "app_type": "split"}, + ) + ], + indirect=True, +) class TestTrafficSplitting: def test_several_requests(self, kube_apis, crd_ingress_controller, virtual_server_setup): ensure_response_from_backend(virtual_server_setup.backend_1_url, virtual_server_setup.vs_host) - weights = get_weights_of_splitting( - f"{TEST_DATA}/virtual-server-split-traffic/standard/virtual-server.yaml") - upstreams = get_upstreams_of_splitting( - f"{TEST_DATA}/virtual-server-split-traffic/standard/virtual-server.yaml") + weights = get_weights_of_splitting(f"{TEST_DATA}/virtual-server-split-traffic/standard/virtual-server.yaml") + upstreams = get_upstreams_of_splitting(f"{TEST_DATA}/virtual-server-split-traffic/standard/virtual-server.yaml") sum_weights = sum(weights) - ratios = [round(i/sum_weights, 1) for i in weights] + ratios = [round(i / sum_weights, 1) for i in weights] counter_v1, counter_v2 = 0, 0 for _ in range(100): - resp = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) + resp = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) if resp.status_code == 502: print("Backend is not ready yet, skip.") if upstreams[0] in resp.text in resp.text: @@ -68,5 +69,5 @@ def test_several_requests(self, kube_apis, crd_ingress_controller, virtual_serve else: pytest.fail(f"An unexpected response: {resp.text}") - assert abs(round(counter_v1/(counter_v1 + counter_v2), 1) - ratios[0]) <= 0.2 - assert abs(round(counter_v2/(counter_v1 + counter_v2), 1) - ratios[1]) <= 0.2 + assert abs(round(counter_v1 / (counter_v1 + counter_v2), 1) - ratios[0]) <= 0.2 + assert abs(round(counter_v2 / (counter_v1 + counter_v2), 1) - ratios[1]) <= 0.2 diff --git a/tests/suite/test_virtual_server_status.py b/tests/suite/test_virtual_server_status.py index 598a736c7d..bd62069cbf 100644 --- a/tests/suite/test_virtual_server_status.py +++ b/tests/suite/test_virtual_server_status.py @@ -1,27 +1,29 @@ import pytest from kubernetes.client.rest import ApiException -from suite.resources_utils import wait_before_test -from suite.vs_vsr_resources_utils import ( - patch_virtual_server_from_yaml, -) -from suite.custom_resources_utils import ( - read_custom_resource, -) from settings import TEST_DATA +from suite.custom_resources_utils import read_custom_resource +from suite.resources_utils import wait_before_test +from suite.vs_vsr_resources_utils import patch_virtual_server_from_yaml + @pytest.mark.vs @pytest.mark.parametrize( "crd_ingress_controller, virtual_server_setup", [ ( - {"type": "complete", "extra_args": [f"-enable-custom-resources", f"-enable-leader-election=false"],}, - {"example": "virtual-server-status", "app_type": "simple",}, + { + "type": "complete", + "extra_args": [f"-enable-custom-resources", f"-enable-leader-election=false"], + }, + { + "example": "virtual-server-status", + "app_type": "simple", + }, ) ], indirect=True, ) class TestVirtualServerStatus: - def patch_valid_vs(self, kube_apis, virtual_server_setup) -> None: """ Function to revert vs deployment to valid state @@ -36,7 +38,10 @@ def patch_valid_vs(self, kube_apis, virtual_server_setup) -> None: @pytest.mark.smoke def test_status_valid( - self, kube_apis, crd_ingress_controller, virtual_server_setup, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, ): """ Test VirtualServer status with a valid fields in yaml @@ -54,7 +59,10 @@ def test_status_valid( ) def test_status_invalid( - self, kube_apis, crd_ingress_controller, virtual_server_setup, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, ): """ Test VirtualServer status with a invalid path pattern @@ -82,7 +90,10 @@ def test_status_invalid( @pytest.mark.skip_for_nginx_oss def test_status_warning( - self, kube_apis, crd_ingress_controller, virtual_server_setup, + self, + kube_apis, + crd_ingress_controller, + virtual_server_setup, ): """ Test VirtualServer status with conflicting Upstream fields diff --git a/tests/suite/test_virtual_server_tls.py b/tests/suite/test_virtual_server_tls.py index 7b192110bc..89b5e7d139 100644 --- a/tests/suite/test_virtual_server_tls.py +++ b/tests/suite/test_virtual_server_tls.py @@ -1,10 +1,13 @@ import pytest - from _ssl import SSLError - from settings import TEST_DATA -from suite.resources_utils import create_secret_from_yaml, wait_before_test, delete_secret, is_secret_present, \ - replace_secret +from suite.resources_utils import ( + create_secret_from_yaml, + delete_secret, + is_secret_present, + replace_secret, + wait_before_test, +) from suite.ssl_utils import get_server_certificate_subject from suite.yaml_utils import get_name_from_yaml @@ -31,9 +34,11 @@ def fin(): def assert_unrecognized_name_error(virtual_server_setup): try: - get_server_certificate_subject(virtual_server_setup.public_endpoint.public_ip, - virtual_server_setup.vs_host, - virtual_server_setup.public_endpoint.port_ssl) + get_server_certificate_subject( + virtual_server_setup.public_endpoint.public_ip, + virtual_server_setup.vs_host, + virtual_server_setup.public_endpoint.port_ssl, + ) pytest.fail("We expected an SSLError here, but didn't get it or got another error. Exiting...") except SSLError as e: assert "SSL" in e.library @@ -41,39 +46,50 @@ def assert_unrecognized_name_error(virtual_server_setup): def assert_us_subject(virtual_server_setup): - subject_dict = get_server_certificate_subject(virtual_server_setup.public_endpoint.public_ip, - virtual_server_setup.vs_host, - virtual_server_setup.public_endpoint.port_ssl) - assert subject_dict[b'C'] == b'US' - assert subject_dict[b'ST'] == b'CA' - assert subject_dict[b'O'] == b'Internet Widgits Pty Ltd' - assert subject_dict[b'CN'] == b'cafe.example.com' + subject_dict = get_server_certificate_subject( + virtual_server_setup.public_endpoint.public_ip, + virtual_server_setup.vs_host, + virtual_server_setup.public_endpoint.port_ssl, + ) + assert subject_dict[b"C"] == b"US" + assert subject_dict[b"ST"] == b"CA" + assert subject_dict[b"O"] == b"Internet Widgits Pty Ltd" + assert subject_dict[b"CN"] == b"cafe.example.com" def assert_gb_subject(virtual_server_setup): - subject_dict = get_server_certificate_subject(virtual_server_setup.public_endpoint.public_ip, - virtual_server_setup.vs_host, - virtual_server_setup.public_endpoint.port_ssl) - assert subject_dict[b'C'] == b'GB' - assert subject_dict[b'ST'] == b'Cambridgeshire' - assert subject_dict[b'O'] == b'nginx' - assert subject_dict[b'CN'] == b'cafe.example.com' + subject_dict = get_server_certificate_subject( + virtual_server_setup.public_endpoint.public_ip, + virtual_server_setup.vs_host, + virtual_server_setup.public_endpoint.port_ssl, + ) + assert subject_dict[b"C"] == b"GB" + assert subject_dict[b"ST"] == b"Cambridgeshire" + assert subject_dict[b"O"] == b"nginx" + assert subject_dict[b"CN"] == b"cafe.example.com" @pytest.mark.vs @pytest.mark.smoke -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-tls", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-tls", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestVirtualServerTLS: def test_tls_termination(self, kube_apis, crd_ingress_controller, virtual_server_setup, clean_up): print("\nStep 1: no secret") assert_unrecognized_name_error(virtual_server_setup) print("\nStep 2: deploy secret and check") - secret_name = create_secret_from_yaml(kube_apis.v1, virtual_server_setup.namespace, - f"{TEST_DATA}/virtual-server-tls/tls-secret.yaml") + secret_name = create_secret_from_yaml( + kube_apis.v1, virtual_server_setup.namespace, f"{TEST_DATA}/virtual-server-tls/tls-secret.yaml" + ) wait_before_test(1) assert_us_subject(virtual_server_setup) @@ -83,27 +99,34 @@ def test_tls_termination(self, kube_apis, crd_ingress_controller, virtual_server assert_unrecognized_name_error(virtual_server_setup) print("\nStep 4: restore secret and check") - create_secret_from_yaml(kube_apis.v1, virtual_server_setup.namespace, - f"{TEST_DATA}/virtual-server-tls/tls-secret.yaml") + create_secret_from_yaml( + kube_apis.v1, virtual_server_setup.namespace, f"{TEST_DATA}/virtual-server-tls/tls-secret.yaml" + ) wait_before_test(1) assert_us_subject(virtual_server_setup) print("\nStep 5: deploy invalid secret and check") delete_secret(kube_apis.v1, secret_name, virtual_server_setup.namespace) - create_secret_from_yaml(kube_apis.v1, virtual_server_setup.namespace, - f"{TEST_DATA}/virtual-server-tls/invalid-tls-secret.yaml") + create_secret_from_yaml( + kube_apis.v1, virtual_server_setup.namespace, f"{TEST_DATA}/virtual-server-tls/invalid-tls-secret.yaml" + ) wait_before_test(1) assert_unrecognized_name_error(virtual_server_setup) print("\nStep 6: restore secret and check") delete_secret(kube_apis.v1, secret_name, virtual_server_setup.namespace) - create_secret_from_yaml(kube_apis.v1, virtual_server_setup.namespace, - f"{TEST_DATA}/virtual-server-tls/tls-secret.yaml") + create_secret_from_yaml( + kube_apis.v1, virtual_server_setup.namespace, f"{TEST_DATA}/virtual-server-tls/tls-secret.yaml" + ) wait_before_test(1) assert_us_subject(virtual_server_setup) print("\nStep 7: update secret and check") - replace_secret(kube_apis.v1, secret_name, virtual_server_setup.namespace, - f"{TEST_DATA}/virtual-server-tls/new-tls-secret.yaml") + replace_secret( + kube_apis.v1, + secret_name, + virtual_server_setup.namespace, + f"{TEST_DATA}/virtual-server-tls/new-tls-secret.yaml", + ) wait_before_test(1) assert_gb_subject(virtual_server_setup) diff --git a/tests/suite/test_virtual_server_tls_redirect.py b/tests/suite/test_virtual_server_tls_redirect.py index 6bf0e39fcd..4d1ec60d6a 100644 --- a/tests/suite/test_virtual_server_tls_redirect.py +++ b/tests/suite/test_virtual_server_tls_redirect.py @@ -1,217 +1,297 @@ import pytest import requests from kubernetes.client.rest import ApiException - from settings import TEST_DATA -from suite.vs_vsr_resources_utils import patch_virtual_server_from_yaml, get_vs_nginx_template_conf -from suite.resources_utils import wait_before_test, get_first_pod_name +from suite.resources_utils import get_first_pod_name, wait_before_test +from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, patch_virtual_server_from_yaml @pytest.mark.vs -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-tls-redirect", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-tls-redirect", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestVirtualServerTLSRedirect: - def test_tls_redirect_defaults(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-tls-redirect/virtual-server-default-redirect.yaml", - virtual_server_setup.namespace) + def test_tls_redirect_defaults( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-tls-redirect/virtual-server-default-redirect.yaml", + virtual_server_setup.namespace, + ) wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert "proxy_set_header X-Forwarded-Proto $scheme;" in config - resp_1 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}, - allow_redirects=False) - resp_2 = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}, - allow_redirects=False) + resp_1 = requests.get( + virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False + ) + resp_2 = requests.get( + virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False + ) assert resp_1.status_code == 301, "Expected: a redirect for scheme=http" assert resp_2.status_code == 301, "Expected: a redirect for scheme=http" - resp_3 = requests.get(virtual_server_setup.backend_1_url_ssl, - headers={"host": virtual_server_setup.vs_host}, - allow_redirects=False, verify=False) - resp_4 = requests.get(virtual_server_setup.backend_2_url_ssl, - headers={"host": virtual_server_setup.vs_host}, - allow_redirects=False, verify=False) + resp_3 = requests.get( + virtual_server_setup.backend_1_url_ssl, + headers={"host": virtual_server_setup.vs_host}, + allow_redirects=False, + verify=False, + ) + resp_4 = requests.get( + virtual_server_setup.backend_2_url_ssl, + headers={"host": virtual_server_setup.vs_host}, + allow_redirects=False, + verify=False, + ) assert resp_3.status_code == 200, "Expected: no redirect for scheme=https" assert resp_4.status_code == 200, "Expected: no redirect for scheme=https" - def test_tls_redirect_based_on_header(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-tls-redirect/virtual-server-header-redirect.yaml", - virtual_server_setup.namespace) + def test_tls_redirect_based_on_header( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-tls-redirect/virtual-server-header-redirect.yaml", + virtual_server_setup.namespace, + ) wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert "proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;" in config - resp_1 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, - allow_redirects=False) - resp_2 = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, - allow_redirects=False) + resp_1 = requests.get( + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, + allow_redirects=False, + ) + resp_2 = requests.get( + virtual_server_setup.backend_2_url, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, + allow_redirects=False, + ) assert resp_1.status_code == 308, "Expected: a redirect for x-forwarded-proto=http" assert resp_2.status_code == 308, "Expected: a redirect for x-forwarded-proto=http" - resp_3 = requests.get(virtual_server_setup.backend_1_url_ssl, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, - allow_redirects=False, verify=False) - resp_4 = requests.get(virtual_server_setup.backend_2_url_ssl, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, - allow_redirects=False, verify=False) + resp_3 = requests.get( + virtual_server_setup.backend_1_url_ssl, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, + allow_redirects=False, + verify=False, + ) + resp_4 = requests.get( + virtual_server_setup.backend_2_url_ssl, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, + allow_redirects=False, + verify=False, + ) assert resp_3.status_code == 308, "Expected: a redirect for x-forwarded-proto=http" assert resp_4.status_code == 308, "Expected: a redirect for x-forwarded-proto=http" - resp_5 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, - allow_redirects=False) - resp_6 = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, - allow_redirects=False) + resp_5 = requests.get( + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, + allow_redirects=False, + ) + resp_6 = requests.get( + virtual_server_setup.backend_2_url, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, + allow_redirects=False, + ) assert resp_5.status_code == 200, "Expected: no redirect for x-forwarded-proto=https" assert resp_6.status_code == 200, "Expected: no redirect for x-forwarded-proto=https" - resp_7 = requests.get(virtual_server_setup.backend_1_url_ssl, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, - allow_redirects=False, verify=False) - resp_8 = requests.get(virtual_server_setup.backend_2_url_ssl, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, - allow_redirects=False, verify=False) + resp_7 = requests.get( + virtual_server_setup.backend_1_url_ssl, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, + allow_redirects=False, + verify=False, + ) + resp_8 = requests.get( + virtual_server_setup.backend_2_url_ssl, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, + allow_redirects=False, + verify=False, + ) assert resp_7.status_code == 200, "Expected: no redirect for x-forwarded-proto=https" assert resp_8.status_code == 200, "Expected: no redirect for x-forwarded-proto=https" - def test_tls_redirect_based_on_scheme(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-tls-redirect/virtual-server-scheme-redirect.yaml", - virtual_server_setup.namespace) + def test_tls_redirect_based_on_scheme( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-tls-redirect/virtual-server-scheme-redirect.yaml", + virtual_server_setup.namespace, + ) wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert "proxy_set_header X-Forwarded-Proto $scheme;" in config - resp_1 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}, - allow_redirects=False) - resp_2 = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}, - allow_redirects=False) + resp_1 = requests.get( + virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False + ) + resp_2 = requests.get( + virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}, allow_redirects=False + ) assert resp_1.status_code == 302, "Expected: a redirect for scheme=http" assert resp_2.status_code == 302, "Expected: a redirect for scheme=http" - resp_3 = requests.get(virtual_server_setup.backend_1_url_ssl, - headers={"host": virtual_server_setup.vs_host}, - allow_redirects=False, verify=False) - resp_4 = requests.get(virtual_server_setup.backend_2_url_ssl, - headers={"host": virtual_server_setup.vs_host}, - allow_redirects=False, verify=False) + resp_3 = requests.get( + virtual_server_setup.backend_1_url_ssl, + headers={"host": virtual_server_setup.vs_host}, + allow_redirects=False, + verify=False, + ) + resp_4 = requests.get( + virtual_server_setup.backend_2_url_ssl, + headers={"host": virtual_server_setup.vs_host}, + allow_redirects=False, + verify=False, + ) assert resp_3.status_code == 200, "Expected: no redirect for scheme=https" assert resp_4.status_code == 200, "Expected: no redirect for scheme=https" - def test_tls_redirect_without_tls_termination(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): + def test_tls_redirect_without_tls_termination( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): source_yaml = f"{TEST_DATA}/virtual-server-tls-redirect/virtual-server-no-tls-termination-redirect.yaml" - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - source_yaml, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, source_yaml, virtual_server_setup.namespace + ) wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert "proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;" in config - resp_1 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, - allow_redirects=False) - resp_2 = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, - allow_redirects=False) + resp_1 = requests.get( + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, + allow_redirects=False, + ) + resp_2 = requests.get( + virtual_server_setup.backend_2_url, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, + allow_redirects=False, + ) assert resp_1.status_code == 308, "Expected: a redirect for x-forwarded-proto=http" assert resp_2.status_code == 308, "Expected: a redirect for x-forwarded-proto=http" - resp_3 = requests.get(virtual_server_setup.backend_1_url_ssl, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, - allow_redirects=False, verify=False) - resp_4 = requests.get(virtual_server_setup.backend_2_url_ssl, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, - allow_redirects=False, verify=False) + resp_3 = requests.get( + virtual_server_setup.backend_1_url_ssl, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, + allow_redirects=False, + verify=False, + ) + resp_4 = requests.get( + virtual_server_setup.backend_2_url_ssl, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "http"}, + allow_redirects=False, + verify=False, + ) assert resp_3.status_code == 404, "Expected: 404 for x-forwarded-proto=http and scheme=https" assert resp_4.status_code == 404, "Expected: 404 for x-forwarded-proto=http and scheme=https" - resp_5 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, - allow_redirects=False) - resp_6 = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, - allow_redirects=False) + resp_5 = requests.get( + virtual_server_setup.backend_1_url, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, + allow_redirects=False, + ) + resp_6 = requests.get( + virtual_server_setup.backend_2_url, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, + allow_redirects=False, + ) assert resp_5.status_code == 200, "Expected: no redirect for x-forwarded-proto=https" assert resp_6.status_code == 200, "Expected: no redirect for x-forwarded-proto=https" - resp_7 = requests.get(virtual_server_setup.backend_1_url_ssl, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, - allow_redirects=False, verify=False) - resp_8 = requests.get(virtual_server_setup.backend_2_url_ssl, - headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, - allow_redirects=False, verify=False) + resp_7 = requests.get( + virtual_server_setup.backend_1_url_ssl, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, + allow_redirects=False, + verify=False, + ) + resp_8 = requests.get( + virtual_server_setup.backend_2_url_ssl, + headers={"host": virtual_server_setup.vs_host, "x-forwarded-proto": "https"}, + allow_redirects=False, + verify=False, + ) assert resp_7.status_code == 404, "Expected: no redirect for x-forwarded-proto=https and scheme=https" assert resp_8.status_code == 404, "Expected: no redirect for x-forwarded-proto=https and scheme=https" - def test_tls_redirect_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): + def test_tls_redirect_openapi_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config_old = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_old = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) source_yaml = f"{TEST_DATA}/virtual-server-tls-redirect/virtual-server-invalid.yaml" try: - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - source_yaml, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, source_yaml, virtual_server_setup.namespace + ) except ApiException as ex: - assert ex.status == 422 \ - and "spec.tls.redirect.enable" in ex.body \ - and "spec.tls.redirect.code" in ex.body \ - and "spec.tls.redirect.basedOn" in ex.body \ - and "spec.tls.secret" in ex.body + assert ( + ex.status == 422 + and "spec.tls.redirect.enable" in ex.body + and "spec.tls.redirect.code" in ex.body + and "spec.tls.redirect.basedOn" in ex.body + and "spec.tls.secret" in ex.body + ) except Exception as ex: pytest.fail(f"An unexpected exception is raised: {ex}") else: pytest.fail("Expected an exception but there was none") wait_before_test(1) - config_new = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_new = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert config_old == config_new, "Expected: config doesn't change" diff --git a/tests/suite/test_virtual_server_upstream_options.py b/tests/suite/test_virtual_server_upstream_options.py index bffaa40b15..69d211adbc 100644 --- a/tests/suite/test_virtual_server_upstream_options.py +++ b/tests/suite/test_virtual_server_upstream_options.py @@ -1,33 +1,48 @@ -import requests import pytest +import requests from kubernetes.client.rest import ApiException - from settings import TEST_DATA -from suite.custom_assertions import assert_event_and_get_count, assert_event_count_increased, assert_response_codes, \ - assert_event, assert_event_starts_with_text_and_contains_errors, assert_vs_conf_not_exists -from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, patch_virtual_server_from_yaml, \ - patch_virtual_server -from suite.custom_resources_utils import ( - generate_item_with_upstream_options, +from suite.custom_assertions import ( + assert_event, + assert_event_and_get_count, + assert_event_count_increased, + assert_event_starts_with_text_and_contains_errors, + assert_response_codes, + assert_vs_conf_not_exists, +) +from suite.custom_resources_utils import generate_item_with_upstream_options +from suite.resources_utils import get_events, get_first_pod_name, replace_configmap_from_yaml, wait_before_test +from suite.vs_vsr_resources_utils import ( + get_vs_nginx_template_conf, + patch_virtual_server, + patch_virtual_server_from_yaml, ) -from suite.resources_utils import get_first_pod_name, wait_before_test, replace_configmap_from_yaml, get_events @pytest.mark.vs -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-upstream-options", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-upstream-options", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestVirtualServerUpstreamOptions: - def test_nginx_config_defaults(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): + def test_nginx_config_defaults( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): print("Case 1: no ConfigMap key, no options in VS") ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert "random two least_conn;" in config assert "ip_hash;" not in config @@ -43,7 +58,7 @@ def test_nginx_config_defaults(self, kube_apis, ingress_controller_prerequisites assert "keepalive" not in config assert 'set $default_connection_header "";' not in config - assert 'set $default_connection_header close;' in config + assert "set $default_connection_header close;" in config assert "proxy_set_header Upgrade $http_upgrade;" in config assert "proxy_set_header Connection $vs_connection_header;" in config assert "proxy_http_version 1.1;" in config @@ -60,48 +75,93 @@ def test_nginx_config_defaults(self, kube_apis, ingress_controller_prerequisites assert "sticky cookie" not in config - @pytest.mark.parametrize('options, expected_strings', [ - ({"lb-method": "least_conn", "max-fails": 8, - "fail-timeout": "13s", "connect-timeout": "55s", "read-timeout": "1s", "send-timeout": "1h", - "keepalive": 54, "max-conns": 1048, "client-max-body-size": "1048K", - "buffering": True, "buffer-size": "2k", "buffers": {"number": 4, "size": "2k"}}, - ["least_conn;", "max_fails=8 ", - "fail_timeout=13s ", "proxy_connect_timeout 55s;", "proxy_read_timeout 1s;", - "proxy_send_timeout 1h;", "keepalive 54;", 'set $default_connection_header "";', "max_conns=1048;", - "client_max_body_size 1048K;", - "proxy_buffering on;", "proxy_buffer_size 2k;", "proxy_buffers 4 2k;"]), - ({"lb-method": "ip_hash", "connect-timeout": "75", "read-timeout": "15", "send-timeout": "1h"}, - ["ip_hash;", "proxy_connect_timeout 75s;", "proxy_read_timeout 15s;", "proxy_send_timeout 1h;"]), - ({"connect-timeout": "1m", "read-timeout": "1m", "send-timeout": "1s"}, - ["proxy_connect_timeout 1m;", "proxy_read_timeout 1m;", "proxy_send_timeout 1s;"]), - ({"next-upstream": "error timeout non_idempotent", "next-upstream-timeout": "5s", "next-upstream-tries": 10}, - ["proxy_next_upstream error timeout non_idempotent;", - "proxy_next_upstream_timeout 5s;", "proxy_next_upstream_tries 10;"]) - ]) - def test_when_option_in_v_s_only(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup, - options, expected_strings): + @pytest.mark.parametrize( + "options, expected_strings", + [ + ( + { + "lb-method": "least_conn", + "max-fails": 8, + "fail-timeout": "13s", + "connect-timeout": "55s", + "read-timeout": "1s", + "send-timeout": "1h", + "keepalive": 54, + "max-conns": 1048, + "client-max-body-size": "1048K", + "buffering": True, + "buffer-size": "2k", + "buffers": {"number": 4, "size": "2k"}, + }, + [ + "least_conn;", + "max_fails=8 ", + "fail_timeout=13s ", + "proxy_connect_timeout 55s;", + "proxy_read_timeout 1s;", + "proxy_send_timeout 1h;", + "keepalive 54;", + 'set $default_connection_header "";', + "max_conns=1048;", + "client_max_body_size 1048K;", + "proxy_buffering on;", + "proxy_buffer_size 2k;", + "proxy_buffers 4 2k;", + ], + ), + ( + {"lb-method": "ip_hash", "connect-timeout": "75", "read-timeout": "15", "send-timeout": "1h"}, + ["ip_hash;", "proxy_connect_timeout 75s;", "proxy_read_timeout 15s;", "proxy_send_timeout 1h;"], + ), + ( + {"connect-timeout": "1m", "read-timeout": "1m", "send-timeout": "1s"}, + ["proxy_connect_timeout 1m;", "proxy_read_timeout 1m;", "proxy_send_timeout 1s;"], + ), + ( + { + "next-upstream": "error timeout non_idempotent", + "next-upstream-timeout": "5s", + "next-upstream-tries": 10, + }, + [ + "proxy_next_upstream error timeout non_idempotent;", + "proxy_next_upstream_timeout 5s;", + "proxy_next_upstream_tries 10;", + ], + ), + ], + ) + def test_when_option_in_v_s_only( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + virtual_server_setup, + options, + expected_strings, + ): text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"Configuration for {text} was added or updated" events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) initial_count = assert_event_and_get_count(vs_event_text, events_vs) print(f"Case 2: no key in ConfigMap , option specified in VS") new_body = generate_item_with_upstream_options( - f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml", - options) - patch_virtual_server(kube_apis.custom_objects, - virtual_server_setup.vs_name, virtual_server_setup.namespace, new_body) + f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml", options + ) + patch_virtual_server( + kube_apis.custom_objects, virtual_server_setup.vs_name, virtual_server_setup.namespace, new_body + ) wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - resp_1 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) - resp_2 = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + resp_1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) + resp_2 = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_count_increased(vs_event_text, initial_count, vs_events) @@ -109,43 +169,79 @@ def test_when_option_in_v_s_only(self, kube_apis, ingress_controller_prerequisit assert _ in config assert_response_codes(resp_1, resp_2) - @pytest.mark.parametrize('config_map_file, expected_strings, unexpected_strings', [ - (f"{TEST_DATA}/virtual-server-upstream-options/configmap-with-keys.yaml", - ["max_fails=3 ", "fail_timeout=33s ", "max_conns=0;", - "proxy_connect_timeout 44s;", "proxy_read_timeout 22s;", "proxy_send_timeout 55s;", - "keepalive 1024;", 'set $default_connection_header "";', - "client_max_body_size 3m;", - "proxy_buffering off;", "proxy_buffer_size 1k;", "proxy_buffers 8 1k;"], - ["ip_hash;", "least_conn;", "random ", "hash", "least_time ", - "max_fails=1 ", "fail_timeout=10s ", "max_conns=1000;", - "proxy_connect_timeout 60s;", "proxy_read_timeout 60s;", "proxy_send_timeout 60s;", - "client_max_body_size 1m;", "slow_start=0s", - "proxy_buffering on;"]), - ]) - def test_when_option_in_config_map_only(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup, restore_configmap, - config_map_file, expected_strings, unexpected_strings): + @pytest.mark.parametrize( + "config_map_file, expected_strings, unexpected_strings", + [ + ( + f"{TEST_DATA}/virtual-server-upstream-options/configmap-with-keys.yaml", + [ + "max_fails=3 ", + "fail_timeout=33s ", + "max_conns=0;", + "proxy_connect_timeout 44s;", + "proxy_read_timeout 22s;", + "proxy_send_timeout 55s;", + "keepalive 1024;", + 'set $default_connection_header "";', + "client_max_body_size 3m;", + "proxy_buffering off;", + "proxy_buffer_size 1k;", + "proxy_buffers 8 1k;", + ], + [ + "ip_hash;", + "least_conn;", + "random ", + "hash", + "least_time ", + "max_fails=1 ", + "fail_timeout=10s ", + "max_conns=1000;", + "proxy_connect_timeout 60s;", + "proxy_read_timeout 60s;", + "proxy_send_timeout 60s;", + "client_max_body_size 1m;", + "slow_start=0s", + "proxy_buffering on;", + ], + ), + ], + ) + def test_when_option_in_config_map_only( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + virtual_server_setup, + restore_configmap, + config_map_file, + expected_strings, + unexpected_strings, + ): text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"Configuration for {text} was added or updated" print(f"Case 3: key specified in ConfigMap, no option in VS") - patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml", + virtual_server_setup.namespace, + ) config_map_name = ingress_controller_prerequisites.config_map["metadata"]["name"] - replace_configmap_from_yaml(kube_apis.v1, config_map_name, - ingress_controller_prerequisites.namespace, - config_map_file) + replace_configmap_from_yaml( + kube_apis.v1, config_map_name, ingress_controller_prerequisites.namespace, config_map_file + ) wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - resp_1 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) - resp_2 = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + resp_1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) + resp_2 = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event(vs_event_text, vs_events) @@ -155,50 +251,98 @@ def test_when_option_in_config_map_only(self, kube_apis, ingress_controller_prer assert _ not in config assert_response_codes(resp_1, resp_2) - @pytest.mark.parametrize('options, expected_strings, unexpected_strings', [ - ({"lb-method": "least_conn", "max-fails": 12, - "fail-timeout": "1m", "connect-timeout": "1m", "read-timeout": "77s", "send-timeout": "23s", - "keepalive": 48, "client-max-body-size": "0", - "buffering": True, "buffer-size": "2k", "buffers": {"number": 4, "size": "2k"}}, - ["least_conn;", "max_fails=12 ", - "fail_timeout=1m ", "max_conns=0;", "proxy_connect_timeout 1m;", "proxy_read_timeout 77s;", - "proxy_send_timeout 23s;", "keepalive 48;", 'set $default_connection_header "";', - "client_max_body_size 0;", - "proxy_buffering on;", "proxy_buffer_size 2k;", "proxy_buffers 4 2k;"], - ["ip_hash;", "random ", "hash", "least_time ", "max_fails=1 ", - "fail_timeout=10s ", "proxy_connect_timeout 44s;", "proxy_read_timeout 22s;", - "proxy_send_timeout 55s;", "keepalive 1024;", - "client_max_body_size 3m;", "client_max_body_size 1m;", - "proxy_buffering off;", "proxy_buffer_size 1k;", "proxy_buffers 8 1k;"]) - ]) - def test_v_s_overrides_config_map(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup, restore_configmap, - options, expected_strings, unexpected_strings): + @pytest.mark.parametrize( + "options, expected_strings, unexpected_strings", + [ + ( + { + "lb-method": "least_conn", + "max-fails": 12, + "fail-timeout": "1m", + "connect-timeout": "1m", + "read-timeout": "77s", + "send-timeout": "23s", + "keepalive": 48, + "client-max-body-size": "0", + "buffering": True, + "buffer-size": "2k", + "buffers": {"number": 4, "size": "2k"}, + }, + [ + "least_conn;", + "max_fails=12 ", + "fail_timeout=1m ", + "max_conns=0;", + "proxy_connect_timeout 1m;", + "proxy_read_timeout 77s;", + "proxy_send_timeout 23s;", + "keepalive 48;", + 'set $default_connection_header "";', + "client_max_body_size 0;", + "proxy_buffering on;", + "proxy_buffer_size 2k;", + "proxy_buffers 4 2k;", + ], + [ + "ip_hash;", + "random ", + "hash", + "least_time ", + "max_fails=1 ", + "fail_timeout=10s ", + "proxy_connect_timeout 44s;", + "proxy_read_timeout 22s;", + "proxy_send_timeout 55s;", + "keepalive 1024;", + "client_max_body_size 3m;", + "client_max_body_size 1m;", + "proxy_buffering off;", + "proxy_buffer_size 1k;", + "proxy_buffers 8 1k;", + ], + ) + ], + ) + def test_v_s_overrides_config_map( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + virtual_server_setup, + restore_configmap, + options, + expected_strings, + unexpected_strings, + ): text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"Configuration for {text} was added or updated" events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) initial_count = assert_event_and_get_count(vs_event_text, events_vs) print(f"Case 4: key in ConfigMap, option specified in VS") new_body = generate_item_with_upstream_options( - f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml", - options) - patch_virtual_server(kube_apis.custom_objects, - virtual_server_setup.vs_name, virtual_server_setup.namespace, new_body) + f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml", options + ) + patch_virtual_server( + kube_apis.custom_objects, virtual_server_setup.vs_name, virtual_server_setup.namespace, new_body + ) config_map_name = ingress_controller_prerequisites.config_map["metadata"]["name"] - replace_configmap_from_yaml(kube_apis.v1, config_map_name, - ingress_controller_prerequisites.namespace, - f"{TEST_DATA}/virtual-server-upstream-options/configmap-with-keys.yaml") + replace_configmap_from_yaml( + kube_apis.v1, + config_map_name, + ingress_controller_prerequisites.namespace, + f"{TEST_DATA}/virtual-server-upstream-options/configmap-with-keys.yaml", + ) wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - resp_1 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) - resp_2 = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + resp_1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) + resp_2 = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_count_increased(vs_event_text, initial_count, vs_events) @@ -210,71 +354,102 @@ def test_v_s_overrides_config_map(self, kube_apis, ingress_controller_prerequisi @pytest.mark.vs -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-upstream-options", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-upstream-options", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestVirtualServerUpstreamOptionValidation: - def test_event_message_and_config(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): + def test_event_message_and_config( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): invalid_fields = [ - "upstreams[0].lb-method", "upstreams[0].fail-timeout", - "upstreams[0].max-fails", "upstreams[0].connect-timeout", - "upstreams[0].read-timeout", "upstreams[0].send-timeout", - "upstreams[0].keepalive", "upstreams[0].max-conns", + "upstreams[0].lb-method", + "upstreams[0].fail-timeout", + "upstreams[0].max-fails", + "upstreams[0].connect-timeout", + "upstreams[0].read-timeout", + "upstreams[0].send-timeout", + "upstreams[0].keepalive", + "upstreams[0].max-conns", "upstreams[0].next-upstream", - "upstreams[0].next-upstream-timeout", "upstreams[0].next-upstream-tries", + "upstreams[0].next-upstream-timeout", + "upstreams[0].next-upstream-tries", "upstreams[0].client-max-body-size", - "upstreams[0].buffers.number", "upstreams[0].buffers.size", "upstreams[0].buffer-size", - "upstreams[1].lb-method", "upstreams[1].fail-timeout", - "upstreams[1].max-fails", "upstreams[1].connect-timeout", - "upstreams[1].read-timeout", "upstreams[1].send-timeout", - "upstreams[1].keepalive", "upstreams[1].max-conns", + "upstreams[0].buffers.number", + "upstreams[0].buffers.size", + "upstreams[0].buffer-size", + "upstreams[1].lb-method", + "upstreams[1].fail-timeout", + "upstreams[1].max-fails", + "upstreams[1].connect-timeout", + "upstreams[1].read-timeout", + "upstreams[1].send-timeout", + "upstreams[1].keepalive", + "upstreams[1].max-conns", "upstreams[1].next-upstream", - "upstreams[1].next-upstream-timeout", "upstreams[1].next-upstream-tries", + "upstreams[1].next-upstream-timeout", + "upstreams[1].next-upstream-tries", "upstreams[1].client-max-body-size", - "upstreams[1].buffers.number", "upstreams[1].buffers.size", "upstreams[1].buffer-size" + "upstreams[1].buffers.number", + "upstreams[1].buffers.size", + "upstreams[1].buffer-size", ] text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"VirtualServer {text} was rejected with error:" vs_file = f"{TEST_DATA}/virtual-server-upstream-options/virtual-server-with-invalid-keys.yaml" - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - vs_file, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_file, virtual_server_setup.namespace + ) wait_before_test(2) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_starts_with_text_and_contains_errors(vs_event_text, vs_events, invalid_fields) - assert_vs_conf_not_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, - virtual_server_setup) + assert_vs_conf_not_exists( + kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, virtual_server_setup + ) - def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): + def test_openapi_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) invalid_fields = [ - "lb-method", "fail-timeout", - "max-fails", "connect-timeout", - "read-timeout", "send-timeout", - "keepalive", "max-conns", + "lb-method", + "fail-timeout", + "max-fails", + "connect-timeout", + "read-timeout", + "send-timeout", + "keepalive", + "max-conns", "next-upstream", - "next-upstream-timeout", "next-upstream-tries", + "next-upstream-timeout", + "next-upstream-tries", "client-max-body-size", - "buffers.number", "buffers.size", "buffer-size", - "buffering", "tls" + "buffers.number", + "buffers.size", + "buffer-size", + "buffering", + "tls", ] - config_old = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_old = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) vs_file = f"{TEST_DATA}/virtual-server-upstream-options/virtual-server-with-invalid-keys-openapi.yaml" try: - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - vs_file, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_file, virtual_server_setup.namespace + ) except ApiException as ex: assert ex.status == 422 for item in invalid_fields: @@ -285,79 +460,135 @@ def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisit pytest.fail("Expected an exception but there was none") wait_before_test(2) - config_new = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_new = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert config_old == config_new, "Expected: config doesn't change" @pytest.mark.vs @pytest.mark.skip_for_nginx_oss -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-upstream-options", "app_type": "simple"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-upstream-options", "app_type": "simple"}, + ) + ], + indirect=True, +) class TestOptionsSpecificForPlus: - @pytest.mark.parametrize('options, expected_strings', [ - ({"lb-method": "least_conn", - "healthCheck": {"enable": True, "mandatory": True, "persistent": True}, - "slow-start": "3h", - "queue": {"size": 100}, - "ntlm": True, - "sessionCookie": {"enable": True, - "name": "TestCookie", - "path": "/some-valid/path", - "expires": "max", - "domain": "virtual-server-route.example.com", "httpOnly": True, "secure": True}}, - ["health_check uri=/ interval=5s jitter=0s", "fails=1 passes=1", "mandatory persistent", ";", - "slow_start=3h", "queue 100 timeout=60s;", "ntlm;", - "sticky cookie TestCookie expires=max domain=virtual-server-route.example.com httponly secure path=/some-valid/path;"]), - ({"lb-method": "least_conn", - "healthCheck": {"enable": True, "path": "/health", - "interval": "15s", "jitter": "3", - "fails": 2, "passes": 2, "port": 8080, - "tls": {"enable": True}, "statusMatch": "200", - "connect-timeout": "35s", "read-timeout": "45s", "send-timeout": "55s", - "headers": [{"name": "Host", "value": "virtual-server.example.com"}]}, - "queue": {"size": 1000, "timeout": "66s"}, - "slow-start": "0s", "ntlm": True}, - ["health_check uri=/health port=8080 interval=15s jitter=3", "fails=2 passes=2 match=", - "proxy_pass https://vs", "status 200;", - "proxy_connect_timeout 35s;", "proxy_read_timeout 45s;", "proxy_send_timeout 55s;", - 'proxy_set_header Host "virtual-server.example.com";', - "slow_start=0s", "queue 1000 timeout=66s;", "ntlm;"]) - - ]) - def test_config_and_events(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup, - options, expected_strings): - expected_strings.append(f"location @hc-vs_" - f"{virtual_server_setup.namespace}_{virtual_server_setup.vs_name}_backend1") - expected_strings.append(f"location @hc-vs_" - f"{virtual_server_setup.namespace}_{virtual_server_setup.vs_name}_backend2") + @pytest.mark.parametrize( + "options, expected_strings", + [ + ( + { + "lb-method": "least_conn", + "healthCheck": {"enable": True, "mandatory": True, "persistent": True}, + "slow-start": "3h", + "queue": {"size": 100}, + "ntlm": True, + "sessionCookie": { + "enable": True, + "name": "TestCookie", + "path": "/some-valid/path", + "expires": "max", + "domain": "virtual-server-route.example.com", + "httpOnly": True, + "secure": True, + }, + }, + [ + "health_check uri=/ interval=5s jitter=0s", + "fails=1 passes=1", + "mandatory persistent", + ";", + "slow_start=3h", + "queue 100 timeout=60s;", + "ntlm;", + "sticky cookie TestCookie expires=max domain=virtual-server-route.example.com httponly secure path=/some-valid/path;", + ], + ), + ( + { + "lb-method": "least_conn", + "healthCheck": { + "enable": True, + "path": "/health", + "interval": "15s", + "jitter": "3", + "fails": 2, + "passes": 2, + "port": 8080, + "tls": {"enable": True}, + "statusMatch": "200", + "connect-timeout": "35s", + "read-timeout": "45s", + "send-timeout": "55s", + "headers": [{"name": "Host", "value": "virtual-server.example.com"}], + }, + "queue": {"size": 1000, "timeout": "66s"}, + "slow-start": "0s", + "ntlm": True, + }, + [ + "health_check uri=/health port=8080 interval=15s jitter=3", + "fails=2 passes=2 match=", + "proxy_pass https://vs", + "status 200;", + "proxy_connect_timeout 35s;", + "proxy_read_timeout 45s;", + "proxy_send_timeout 55s;", + 'proxy_set_header Host "virtual-server.example.com";', + "slow_start=0s", + "queue 1000 timeout=66s;", + "ntlm;", + ], + ), + ], + ) + def test_config_and_events( + self, + kube_apis, + ingress_controller_prerequisites, + crd_ingress_controller, + virtual_server_setup, + options, + expected_strings, + ): + expected_strings.append( + f"location @hc-vs_" f"{virtual_server_setup.namespace}_{virtual_server_setup.vs_name}_backend1" + ) + expected_strings.append( + f"location @hc-vs_" f"{virtual_server_setup.namespace}_{virtual_server_setup.vs_name}_backend2" + ) text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"Configuration for {text} was added or updated" events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) initial_count = assert_event_and_get_count(vs_event_text, events_vs) print(f"Case 1: option specified in VS") new_body = generate_item_with_upstream_options( - f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml", - options) - patch_virtual_server(kube_apis.custom_objects, - virtual_server_setup.vs_name, virtual_server_setup.namespace, new_body) + f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml", options + ) + patch_virtual_server( + kube_apis.custom_objects, virtual_server_setup.vs_name, virtual_server_setup.namespace, new_body + ) wait_before_test(1) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - resp_1 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) - resp_2 = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + resp_1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) + resp_2 = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_count_increased(vs_event_text, initial_count, vs_events) @@ -365,97 +596,131 @@ def test_config_and_events(self, kube_apis, ingress_controller_prerequisites, assert _ in config assert_response_codes(resp_1, resp_2) - @pytest.mark.parametrize('options', [{"slow-start": "0s"}]) - def test_slow_start_warning(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup, options): + @pytest.mark.parametrize("options", [{"slow-start": "0s"}]) + def test_slow_start_warning( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup, options + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"Configuration for {text} was added or updated ; with warning(s): Slow start will be disabled" print(f"Case 0: verify a warning") new_body = generate_item_with_upstream_options( - f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml", - options) - patch_virtual_server(kube_apis.custom_objects, - virtual_server_setup.vs_name, virtual_server_setup.namespace, new_body) + f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml", options + ) + patch_virtual_server( + kube_apis.custom_objects, virtual_server_setup.vs_name, virtual_server_setup.namespace, new_body + ) wait_before_test(1) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event(vs_event_text, vs_events) assert "slow_start" not in config - def test_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): + def test_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): invalid_fields = [ - "upstreams[0].healthCheck.path", "upstreams[0].healthCheck.interval", "upstreams[0].healthCheck.jitter", - "upstreams[0].healthCheck.fails", "upstreams[0].healthCheck.passes", + "upstreams[0].healthCheck.path", + "upstreams[0].healthCheck.interval", + "upstreams[0].healthCheck.jitter", + "upstreams[0].healthCheck.fails", + "upstreams[0].healthCheck.passes", "upstreams[0].healthCheck.connect-timeout", - "upstreams[0].healthCheck.read-timeout", "upstreams[0].healthCheck.send-timeout", - "upstreams[0].healthCheck.headers[0].name", "upstreams[0].healthCheck.headers[0].value", - "upstreams[0].healthCheck.statusMatch", "upstreams[0].healthCheck.grpcStatus", - "upstreams[0].healthCheck.grpcService", "upstreams[0].healthCheck.mandatory", + "upstreams[0].healthCheck.read-timeout", + "upstreams[0].healthCheck.send-timeout", + "upstreams[0].healthCheck.headers[0].name", + "upstreams[0].healthCheck.headers[0].value", + "upstreams[0].healthCheck.statusMatch", + "upstreams[0].healthCheck.grpcStatus", + "upstreams[0].healthCheck.grpcService", + "upstreams[0].healthCheck.mandatory", "upstreams[0].slow-start", - "upstreams[0].queue.size", "upstreams[0].queue.timeout", - "upstreams[0].sessionCookie.name", "upstreams[0].sessionCookie.path", - "upstreams[0].sessionCookie.expires", "upstreams[0].sessionCookie.domain", - "upstreams[1].healthCheck.path", "upstreams[1].healthCheck.interval", "upstreams[1].healthCheck.jitter", - "upstreams[1].healthCheck.fails", "upstreams[1].healthCheck.passes", + "upstreams[0].queue.size", + "upstreams[0].queue.timeout", + "upstreams[0].sessionCookie.name", + "upstreams[0].sessionCookie.path", + "upstreams[0].sessionCookie.expires", + "upstreams[0].sessionCookie.domain", + "upstreams[1].healthCheck.path", + "upstreams[1].healthCheck.interval", + "upstreams[1].healthCheck.jitter", + "upstreams[1].healthCheck.fails", + "upstreams[1].healthCheck.passes", "upstreams[1].healthCheck.connect-timeout", - "upstreams[1].healthCheck.read-timeout", "upstreams[1].healthCheck.send-timeout", - "upstreams[1].healthCheck.headers[0].name", "upstreams[1].healthCheck.headers[0].value", + "upstreams[1].healthCheck.read-timeout", + "upstreams[1].healthCheck.send-timeout", + "upstreams[1].healthCheck.headers[0].name", + "upstreams[1].healthCheck.headers[0].value", "upstreams[1].healthCheck.statusMatch", "upstreams[1].slow-start", - "upstreams[1].queue.size", "upstreams[1].queue.timeout", - "upstreams[1].sessionCookie.name", "upstreams[1].sessionCookie.path", - "upstreams[1].sessionCookie.expires", "upstreams[1].sessionCookie.domain" + "upstreams[1].queue.size", + "upstreams[1].queue.timeout", + "upstreams[1].sessionCookie.name", + "upstreams[1].sessionCookie.path", + "upstreams[1].sessionCookie.expires", + "upstreams[1].sessionCookie.domain", ] text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"VirtualServer {text} was rejected with error:" vs_file = f"{TEST_DATA}/virtual-server-upstream-options/plus-virtual-server-with-invalid-keys.yaml" - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - vs_file, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_file, virtual_server_setup.namespace + ) wait_before_test(2) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event_starts_with_text_and_contains_errors(vs_event_text, vs_events, invalid_fields) - assert_vs_conf_not_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, - virtual_server_setup) + assert_vs_conf_not_exists( + kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, virtual_server_setup + ) - def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): + def test_openapi_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) invalid_fields = [ - "healthCheck.enable", "healthCheck.path", - "healthCheck.interval", "healthCheck.jitter", - "healthCheck.fails", "healthCheck.passes", - "healthCheck.port", "healthCheck.connect-timeout", - "healthCheck.read-timeout", "healthCheck.send-timeout", + "healthCheck.enable", + "healthCheck.path", + "healthCheck.interval", + "healthCheck.jitter", + "healthCheck.fails", + "healthCheck.passes", + "healthCheck.port", + "healthCheck.connect-timeout", + "healthCheck.read-timeout", + "healthCheck.send-timeout", "healthCheck.statusMatch", "slow-start", - "queue.size", "queue.timeout", - "sessionCookie.name", "sessionCookie.path", - "sessionCookie.expires", "sessionCookie.domain", - "sessionCookie.httpOnly", "sessionCookie.secure" + "queue.size", + "queue.timeout", + "sessionCookie.name", + "sessionCookie.path", + "sessionCookie.expires", + "sessionCookie.domain", + "sessionCookie.httpOnly", + "sessionCookie.secure", ] - config_old = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_old = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) vs_file = f"{TEST_DATA}/virtual-server-upstream-options/plus-virtual-server-with-invalid-keys-openapi.yaml" try: - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - vs_file, - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, virtual_server_setup.vs_name, vs_file, virtual_server_setup.namespace + ) except ApiException as ex: assert ex.status == 422 for item in invalid_fields: @@ -466,9 +731,11 @@ def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisit pytest.fail("Expected an exception but there was none") wait_before_test(2) - config_new = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) + config_new = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) assert config_old == config_new, "Expected: config doesn't change" diff --git a/tests/suite/test_virtual_server_upstream_tls.py b/tests/suite/test_virtual_server_upstream_tls.py index b870112a9b..222066b6ac 100644 --- a/tests/suite/test_virtual_server_upstream_tls.py +++ b/tests/suite/test_virtual_server_upstream_tls.py @@ -1,55 +1,70 @@ -import requests import pytest +import requests from kubernetes.client.rest import ApiException - from settings import TEST_DATA -from suite.custom_assertions import assert_event_and_get_count, assert_event_count_increased, assert_response_codes, \ - assert_event, assert_no_new_events +from suite.custom_assertions import ( + assert_event, + assert_event_and_get_count, + assert_event_count_increased, + assert_no_new_events, + assert_response_codes, +) +from suite.resources_utils import get_events, get_first_pod_name, wait_before_test from suite.vs_vsr_resources_utils import get_vs_nginx_template_conf, patch_virtual_server_from_yaml -from suite.resources_utils import get_first_pod_name, wait_before_test, get_events @pytest.mark.flaky(max_runs=3) @pytest.mark.vs -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-upstream-tls", "app_type": "secure"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-upstream-tls", "app_type": "secure"}, + ) + ], + indirect=True, +) class TestVirtualServerUpstreamTls: - def test_responses_and_config_after_setup(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): + def test_responses_and_config_after_setup( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - resp_1 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) - resp_2 = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + resp_1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) + resp_2 = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) proxy_host = f"vs_{virtual_server_setup.namespace}_{virtual_server_setup.vs_name}" - assert f'proxy_pass https://{proxy_host}_backend1' not in config - assert f'proxy_pass https://{proxy_host}_backend2' in config + assert f"proxy_pass https://{proxy_host}_backend1" not in config + assert f"proxy_pass https://{proxy_host}_backend2" in config assert_response_codes(resp_1, resp_2) - def test_event_after_setup(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): + def test_event_after_setup( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"Configuration for {text} was added or updated" events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_event(vs_event_text, events_vs) - def test_validation_flow(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): + def test_validation_flow( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) initial_events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) try: - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-upstream-tls/virtual-server-invalid.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-upstream-tls/virtual-server-invalid.yaml", + virtual_server_setup.namespace, + ) except ApiException as ex: assert ex.status == 422 and "tls.enable" in ex.body except Exception as ex: @@ -58,46 +73,49 @@ def test_validation_flow(self, kube_apis, ingress_controller_prerequisites, pytest.fail("Expected an exception but there was none") wait_before_test(1) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - resp_1 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) - resp_2 = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + resp_1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) + resp_2 = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) new_events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) proxy_host = f"vs_{virtual_server_setup.namespace}_{virtual_server_setup.vs_name}" - assert f'proxy_pass https://{proxy_host}_backend1' not in config - assert f'proxy_pass https://{proxy_host}_backend2' in config + assert f"proxy_pass https://{proxy_host}_backend1" not in config + assert f"proxy_pass https://{proxy_host}_backend2" in config assert_response_codes(resp_1, resp_2) assert_no_new_events(initial_events_vs, new_events_vs) - def test_responses_and_config_after_disable_tls(self, kube_apis, ingress_controller_prerequisites, - crd_ingress_controller, virtual_server_setup): + def test_responses_and_config_after_disable_tls( + self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" vs_event_text = f"Configuration for {text} was added or updated" initial_events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) initial_count = assert_event_and_get_count(vs_event_text, initial_events_vs) - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-upstream-tls/virtual-server-disable-tls.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-upstream-tls/virtual-server-disable-tls.yaml", + virtual_server_setup.namespace, + ) wait_before_test(1) - config = get_vs_nginx_template_conf(kube_apis.v1, - virtual_server_setup.namespace, - virtual_server_setup.vs_name, - ic_pod_name, - ingress_controller_prerequisites.namespace) - resp_1 = requests.get(virtual_server_setup.backend_1_url, - headers={"host": virtual_server_setup.vs_host}) - resp_2 = requests.get(virtual_server_setup.backend_2_url, - headers={"host": virtual_server_setup.vs_host}) + config = get_vs_nginx_template_conf( + kube_apis.v1, + virtual_server_setup.namespace, + virtual_server_setup.vs_name, + ic_pod_name, + ingress_controller_prerequisites.namespace, + ) + resp_1 = requests.get(virtual_server_setup.backend_1_url, headers={"host": virtual_server_setup.vs_host}) + resp_2 = requests.get(virtual_server_setup.backend_2_url, headers={"host": virtual_server_setup.vs_host}) new_events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace) - assert 'proxy_pass https://' not in config + assert "proxy_pass https://" not in config assert_response_codes(resp_1, resp_2, 200, 400) assert_event_count_increased(vs_event_text, initial_count, new_events_vs) diff --git a/tests/suite/test_virtual_server_validation.py b/tests/suite/test_virtual_server_validation.py index eb6483e09a..9e6094ee83 100644 --- a/tests/suite/test_virtual_server_validation.py +++ b/tests/suite/test_virtual_server_validation.py @@ -1,11 +1,13 @@ import pytest import requests - from settings import TEST_DATA -from suite.custom_assertions import assert_vs_conf_not_exists, assert_vs_conf_exists -from suite.vs_vsr_resources_utils import patch_virtual_server_from_yaml,\ - delete_virtual_server, create_virtual_server_from_yaml -from suite.resources_utils import wait_before_test, get_events, get_first_pod_name, get_pods_amount +from suite.custom_assertions import assert_vs_conf_exists, assert_vs_conf_not_exists +from suite.resources_utils import get_events, get_first_pod_name, get_pods_amount, wait_before_test +from suite.vs_vsr_resources_utils import ( + create_virtual_server_from_yaml, + delete_virtual_server, + patch_virtual_server_from_yaml, +) def assert_reject_events_emitted(virtual_server_setup, new_list, previous_list, expected_amount): @@ -19,7 +21,7 @@ def assert_reject_events_emitted(virtual_server_setup, new_list, previous_list, def assert_event_count_increased_in_list(virtual_server_setup, new_list, previous_list): item_name = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}" text_valid = f"Configuration for {item_name} was added or updated" - for i in range(len(previous_list)-1, 0, -1): + for i in range(len(previous_list) - 1, 0, -1): if text_valid in previous_list[i].message: assert new_list[i].count - previous_list[i].count == 1, "We expect the counter to increase" @@ -39,69 +41,82 @@ def assert_response_404(virtual_server_setup): @pytest.mark.vs -@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup', - [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, - {"example": "virtual-server-validation", "app_type": "advanced-routing"})], - indirect=True) +@pytest.mark.parametrize( + "crd_ingress_controller, virtual_server_setup", + [ + ( + {"type": "complete", "extra_args": [f"-enable-custom-resources"]}, + {"example": "virtual-server-validation", "app_type": "advanced-routing"}, + ) + ], + indirect=True, +) class TestVirtualServerValidation: - def test_virtual_server_behavior(self, - kube_apis, cli_arguments, - ingress_controller_prerequisites, - crd_ingress_controller, - virtual_server_setup): + def test_virtual_server_behavior( + self, kube_apis, cli_arguments, ingress_controller_prerequisites, crd_ingress_controller, virtual_server_setup + ): ic_pods_amount = get_pods_amount(kube_apis.v1, ingress_controller_prerequisites.namespace) ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) print("Step 1: initial check") step_1_list = get_events(kube_apis.v1, virtual_server_setup.namespace) - assert_vs_conf_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, - virtual_server_setup) + assert_vs_conf_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, virtual_server_setup) assert_response_200(virtual_server_setup) print("Step 2: make a valid VirtualServer invalid and check") - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-validation/virtual-server-invalid-cookie.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-validation/virtual-server-invalid-cookie.yaml", + virtual_server_setup.namespace, + ) wait_before_test(1) step_2_list = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_reject_events_emitted(virtual_server_setup, step_2_list, step_1_list, ic_pods_amount) - assert_vs_conf_not_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, - virtual_server_setup) + assert_vs_conf_not_exists( + kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, virtual_server_setup + ) assert_response_404(virtual_server_setup) print("Step 3: update an invalid VirtualServer with another invalid and check") - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-validation/virtual-server-no-default-action.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-validation/virtual-server-no-default-action.yaml", + virtual_server_setup.namespace, + ) wait_before_test(1) step_3_list = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_reject_events_emitted(virtual_server_setup, step_3_list, step_2_list, ic_pods_amount) - assert_vs_conf_not_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, - virtual_server_setup) + assert_vs_conf_not_exists( + kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, virtual_server_setup + ) assert_response_404(virtual_server_setup) print("Step 4: make an invalid VirtualServer valid and check") - patch_virtual_server_from_yaml(kube_apis.custom_objects, - virtual_server_setup.vs_name, - f"{TEST_DATA}/virtual-server-validation/standard/virtual-server.yaml", - virtual_server_setup.namespace) + patch_virtual_server_from_yaml( + kube_apis.custom_objects, + virtual_server_setup.vs_name, + f"{TEST_DATA}/virtual-server-validation/standard/virtual-server.yaml", + virtual_server_setup.namespace, + ) wait_before_test(1) step_4_list = get_events(kube_apis.v1, virtual_server_setup.namespace) - assert_vs_conf_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, - virtual_server_setup) + assert_vs_conf_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, virtual_server_setup) assert_event_count_increased_in_list(virtual_server_setup, step_4_list, step_3_list) assert_response_200(virtual_server_setup) print("Step 5: delete VS and then create an invalid and check") delete_virtual_server(kube_apis.custom_objects, virtual_server_setup.vs_name, virtual_server_setup.namespace) - create_virtual_server_from_yaml(kube_apis.custom_objects, - f"{TEST_DATA}/virtual-server-validation/virtual-server-invalid-cookie.yaml", - virtual_server_setup.namespace) + create_virtual_server_from_yaml( + kube_apis.custom_objects, + f"{TEST_DATA}/virtual-server-validation/virtual-server-invalid-cookie.yaml", + virtual_server_setup.namespace, + ) wait_before_test(1) step_5_list = get_events(kube_apis.v1, virtual_server_setup.namespace) assert_reject_events_emitted(virtual_server_setup, step_5_list, step_4_list, ic_pods_amount) - assert_vs_conf_not_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, - virtual_server_setup) + assert_vs_conf_not_exists( + kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace, virtual_server_setup + ) assert_response_404(virtual_server_setup) diff --git a/tests/suite/test_watch_namespace.py b/tests/suite/test_watch_namespace.py index b832c323c2..edc27b978a 100644 --- a/tests/suite/test_watch_namespace.py +++ b/tests/suite/test_watch_namespace.py @@ -1,10 +1,16 @@ -import requests import pytest - -from suite.resources_utils import ensure_connection_to_public_endpoint, create_items_from_yaml, create_example_app, \ - wait_until_all_pods_are_ready, ensure_response_from_backend, create_namespace_with_name_from_yaml, delete_namespace -from suite.yaml_utils import get_first_ingress_host_from_yaml +import requests from settings import TEST_DATA +from suite.resources_utils import ( + create_example_app, + create_items_from_yaml, + create_namespace_with_name_from_yaml, + delete_namespace, + ensure_connection_to_public_endpoint, + ensure_response_from_backend, + wait_until_all_pods_are_ready, +) +from suite.yaml_utils import get_first_ingress_host_from_yaml class BackendSetup: @@ -31,12 +37,12 @@ def backend_setup(request, kube_apis, ingress_controller_endpoint) -> BackendSet :param ingress_controller_endpoint: public endpoint :return: BackendSetup """ - watched_namespace = create_namespace_with_name_from_yaml(kube_apis.v1, - f"watched-ns", f"{TEST_DATA}/common/ns.yaml") - foreign_namespace = create_namespace_with_name_from_yaml(kube_apis.v1, - f"foreign-ns", f"{TEST_DATA}/common/ns.yaml") - watched_namespace2 = create_namespace_with_name_from_yaml(kube_apis.v1, - f"watched-ns2", f"{TEST_DATA}/common/ns.yaml") + watched_namespace = create_namespace_with_name_from_yaml(kube_apis.v1, f"watched-ns", f"{TEST_DATA}/common/ns.yaml") + foreign_namespace = create_namespace_with_name_from_yaml(kube_apis.v1, f"foreign-ns", f"{TEST_DATA}/common/ns.yaml") + watched_namespace2 = create_namespace_with_name_from_yaml( + kube_apis.v1, f"watched-ns2", f"{TEST_DATA}/common/ns.yaml" + ) + ingress_hosts = {} for ns in [watched_namespace, foreign_namespace, watched_namespace2]: print(f"------------------------- Deploy the backend in {ns} -----------------------------------") @@ -47,9 +53,11 @@ def backend_setup(request, kube_apis, ingress_controller_endpoint) -> BackendSet ingress_hosts[f"{ns}-ingress"] = ingress_host req_url = f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.port}/backend1" wait_until_all_pods_are_ready(kube_apis.v1, ns) - ensure_connection_to_public_endpoint(ingress_controller_endpoint.public_ip, - ingress_controller_endpoint.port, - ingress_controller_endpoint.port_ssl) + ensure_connection_to_public_endpoint( + ingress_controller_endpoint.public_ip, + ingress_controller_endpoint.port, + ingress_controller_endpoint.port_ssl, + ) def fin(): print("Clean up:") @@ -63,31 +71,41 @@ def fin(): @pytest.mark.ingresses -@pytest.mark.parametrize('ingress_controller, expected_responses', - [ - pytest.param({"extra_args": ["-watch-namespace=watched-ns"]}, - {"watched-ns-ingress": 200, "foreign-ns-ingress": 404}) - ], - indirect=["ingress_controller"]) +@pytest.mark.parametrize( + "ingress_controller, expected_responses", + [ + pytest.param( + {"extra_args": ["-watch-namespace=watched-ns"]}, {"watched-ns-ingress": 200, "foreign-ns-ingress": 404} + ) + ], + indirect=["ingress_controller"], +) class TestWatchNamespace: def test_response_codes(self, ingress_controller, backend_setup, expected_responses): for ing in ["watched-ns-ingress", "foreign-ns-ingress"]: ensure_response_from_backend(backend_setup.req_url, backend_setup.ingress_hosts[ing]) resp = requests.get(backend_setup.req_url, headers={"host": backend_setup.ingress_hosts[ing]}) - assert resp.status_code == expected_responses[ing],\ - f"Expected: {expected_responses[ing]} response code for {backend_setup.ingress_hosts[ing]}" + assert ( + resp.status_code == expected_responses[ing] + ), f"Expected: {expected_responses[ing]} response code for {backend_setup.ingress_hosts[ing]}" + @pytest.mark.ingresses -@pytest.mark.parametrize('ingress_controller, expected_responses', - [ - pytest.param({"extra_args": ["-watch-namespace=watched-ns,watched-ns2"]}, - {"watched-ns-ingress": 200, "watched-ns2-ingress": 200, "foreign-ns-ingress": 404}) - ], - indirect=["ingress_controller"]) +@pytest.mark.parametrize( + "ingress_controller, expected_responses", + [ + pytest.param( + {"extra_args": ["-watch-namespace=watched-ns,watched-ns2"]}, + {"watched-ns-ingress": 200, "watched-ns2-ingress": 200, "foreign-ns-ingress": 404}, + ) + ], + indirect=["ingress_controller"], +) class TestWatchMultipleNamespaces: def test_response_codes(self, ingress_controller, backend_setup, expected_responses): for ing in ["watched-ns-ingress", "watched-ns2-ingress", "foreign-ns-ingress"]: ensure_response_from_backend(backend_setup.req_url, backend_setup.ingress_hosts[ing]) resp = requests.get(backend_setup.req_url, headers={"host": backend_setup.ingress_hosts[ing]}) - assert resp.status_code == expected_responses[ing],\ - f"Expected: {expected_responses[ing]} response code for {backend_setup.ingress_hosts[ing]}" + assert ( + resp.status_code == expected_responses[ing] + ), f"Expected: {expected_responses[ing]} response code for {backend_setup.ingress_hosts[ing]}" diff --git a/tests/suite/test_wildcard_tls_secret.py b/tests/suite/test_wildcard_tls_secret.py index b5779dcc85..f1394d8eef 100644 --- a/tests/suite/test_wildcard_tls_secret.py +++ b/tests/suite/test_wildcard_tls_secret.py @@ -1,12 +1,22 @@ -import requests import pytest +import requests from settings import TEST_DATA from suite.fixtures import PublicEndpoint +from suite.resources_utils import ( + create_example_app, + create_ingress_controller, + create_items_from_yaml, + create_secret_from_yaml, + delete_common_app, + delete_ingress_controller, + delete_items_from_yaml, + delete_secret, + ensure_connection_to_public_endpoint, + is_secret_present, + wait_before_test, + wait_until_all_pods_are_ready, +) from suite.ssl_utils import get_server_certificate_subject -from suite.resources_utils import create_items_from_yaml, delete_items_from_yaml,\ - create_secret_from_yaml, delete_secret, create_example_app, delete_common_app,\ - is_secret_present, wait_until_all_pods_are_ready, create_ingress_controller,\ - delete_ingress_controller, wait_before_test, ensure_connection_to_public_endpoint from suite.yaml_utils import get_first_ingress_host_from_yaml paths = ["backend1", "backend2"] @@ -21,6 +31,7 @@ class WildcardTLSSecretSetup: namespace (str): ingress_host (str): """ + def __init__(self, public_endpoint: PublicEndpoint, namespace, ingress_host): self.public_endpoint = public_endpoint self.namespace = namespace @@ -34,26 +45,29 @@ class IngressControllerWithSecret: Attributes: secret_name (str): """ + def __init__(self, secret_name): self.secret_name = secret_name @pytest.fixture(scope="class", params=["standard", "mergeable"]) -def wildcard_tls_secret_setup(request, kube_apis, - ingress_controller_endpoint, test_namespace) -> WildcardTLSSecretSetup: +def wildcard_tls_secret_setup( + request, kube_apis, ingress_controller_endpoint, test_namespace +) -> WildcardTLSSecretSetup: ing_type = request.param print("------------------------- Deploy Wildcard-Tls-Secret-Example -----------------------------------") - create_items_from_yaml(kube_apis, - f"{TEST_DATA}/wildcard-tls-secret/{ing_type}/wildcard-secret-ingress.yaml", test_namespace) + create_items_from_yaml( + kube_apis, f"{TEST_DATA}/wildcard-tls-secret/{ing_type}/wildcard-secret-ingress.yaml", test_namespace + ) host = get_first_ingress_host_from_yaml(f"{TEST_DATA}/wildcard-tls-secret/{ing_type}/wildcard-secret-ingress.yaml") create_example_app(kube_apis, "simple", test_namespace) wait_until_all_pods_are_ready(kube_apis.v1, test_namespace) def fin(): print("Clean up Wildcard-Tls-Secret-Example:") - delete_items_from_yaml(kube_apis, - f"{TEST_DATA}/wildcard-tls-secret/{ing_type}/wildcard-secret-ingress.yaml", - test_namespace) + delete_items_from_yaml( + kube_apis, f"{TEST_DATA}/wildcard-tls-secret/{ing_type}/wildcard-secret-ingress.yaml", test_namespace + ) delete_common_app(kube_apis, "simple", test_namespace) request.addfinalizer(fin) @@ -62,8 +76,9 @@ def fin(): @pytest.fixture(scope="class") -def wildcard_tls_secret_ingress_controller(cli_arguments, kube_apis, ingress_controller_prerequisites, - wildcard_tls_secret_setup, request) -> IngressControllerWithSecret: +def wildcard_tls_secret_ingress_controller( + cli_arguments, kube_apis, ingress_controller_prerequisites, wildcard_tls_secret_setup, request +) -> IngressControllerWithSecret: """ Create a Wildcard Ingress Controller according to the installation type :param cli_arguments: pytest context @@ -75,17 +90,20 @@ def wildcard_tls_secret_ingress_controller(cli_arguments, kube_apis, ingress_con """ namespace = ingress_controller_prerequisites.namespace print("------------------------- Create IC and wildcard secret -----------------------------------") - secret_name = create_secret_from_yaml(kube_apis.v1, namespace, - f"{TEST_DATA}/wildcard-tls-secret/wildcard-tls-secret.yaml") + secret_name = create_secret_from_yaml( + kube_apis.v1, namespace, f"{TEST_DATA}/wildcard-tls-secret/wildcard-tls-secret.yaml" + ) extra_args = [f"-wildcard-tls-secret={namespace}/{secret_name}", "-enable-custom-resources=false"] name = create_ingress_controller(kube_apis.v1, kube_apis.apps_v1_api, cli_arguments, namespace, extra_args) - ensure_connection_to_public_endpoint(wildcard_tls_secret_setup.public_endpoint.public_ip, - wildcard_tls_secret_setup.public_endpoint.port, - wildcard_tls_secret_setup.public_endpoint.port_ssl) + ensure_connection_to_public_endpoint( + wildcard_tls_secret_setup.public_endpoint.public_ip, + wildcard_tls_secret_setup.public_endpoint.port, + wildcard_tls_secret_setup.public_endpoint.port_ssl, + ) def fin(): print("Remove IC and wildcard secret:") - delete_ingress_controller(kube_apis.apps_v1_api, name, cli_arguments['deployment-type'], namespace) + delete_ingress_controller(kube_apis.apps_v1_api, name, cli_arguments["deployment-type"], namespace) if is_secret_present(kube_apis.v1, secret_name, namespace): delete_secret(kube_apis.v1, secret_name, namespace) @@ -98,64 +116,97 @@ def fin(): class TestTLSWildcardSecrets: @pytest.mark.parametrize("path", paths) def test_response_code_200(self, wildcard_tls_secret_ingress_controller, wildcard_tls_secret_setup, path): - req_url = f"https://{wildcard_tls_secret_setup.public_endpoint.public_ip}:" \ - f"{wildcard_tls_secret_setup.public_endpoint.port_ssl}/{path}" + req_url = ( + f"https://{wildcard_tls_secret_setup.public_endpoint.public_ip}:" + f"{wildcard_tls_secret_setup.public_endpoint.port_ssl}/{path}" + ) resp = requests.get(req_url, headers={"host": wildcard_tls_secret_setup.ingress_host}, verify=False) assert resp.status_code == 200 def test_certificate_subject(self, wildcard_tls_secret_ingress_controller, wildcard_tls_secret_setup): - subject_dict = get_server_certificate_subject(wildcard_tls_secret_setup.public_endpoint.public_ip, - wildcard_tls_secret_setup.ingress_host, - wildcard_tls_secret_setup.public_endpoint.port_ssl) - assert subject_dict[b'C'] == b'ES' - assert subject_dict[b'ST'] == b'CanaryIslands' - assert subject_dict[b'O'] == b'nginx' - assert subject_dict[b'OU'] == b'example.com' - assert subject_dict[b'CN'] == b'example.com' - - def test_certificate_subject_remains_with_invalid_secret(self, kube_apis, ingress_controller_prerequisites, - wildcard_tls_secret_ingress_controller, - wildcard_tls_secret_setup): - delete_secret(kube_apis.v1, wildcard_tls_secret_ingress_controller.secret_name, - ingress_controller_prerequisites.namespace) - create_secret_from_yaml(kube_apis.v1, ingress_controller_prerequisites.namespace, - f"{TEST_DATA}/wildcard-tls-secret/invalid-wildcard-tls-secret.yaml") + subject_dict = get_server_certificate_subject( + wildcard_tls_secret_setup.public_endpoint.public_ip, + wildcard_tls_secret_setup.ingress_host, + wildcard_tls_secret_setup.public_endpoint.port_ssl, + ) + assert subject_dict[b"C"] == b"ES" + assert subject_dict[b"ST"] == b"CanaryIslands" + assert subject_dict[b"O"] == b"nginx" + assert subject_dict[b"OU"] == b"example.com" + assert subject_dict[b"CN"] == b"example.com" + + def test_certificate_subject_remains_with_invalid_secret( + self, + kube_apis, + ingress_controller_prerequisites, + wildcard_tls_secret_ingress_controller, + wildcard_tls_secret_setup, + ): + delete_secret( + kube_apis.v1, wildcard_tls_secret_ingress_controller.secret_name, ingress_controller_prerequisites.namespace + ) + create_secret_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.namespace, + f"{TEST_DATA}/wildcard-tls-secret/invalid-wildcard-tls-secret.yaml", + ) wait_before_test(1) - subject_dict = get_server_certificate_subject(wildcard_tls_secret_setup.public_endpoint.public_ip, - wildcard_tls_secret_setup.ingress_host, - wildcard_tls_secret_setup.public_endpoint.port_ssl) - assert subject_dict[b'C'] == b'ES' - assert subject_dict[b'ST'] == b'CanaryIslands' - assert subject_dict[b'CN'] == b'example.com' - - def test_certificate_subject_updates_after_secret_update(self, kube_apis, ingress_controller_prerequisites, - wildcard_tls_secret_ingress_controller, - wildcard_tls_secret_setup): - delete_secret(kube_apis.v1, wildcard_tls_secret_ingress_controller.secret_name, - ingress_controller_prerequisites.namespace) - create_secret_from_yaml(kube_apis.v1, ingress_controller_prerequisites.namespace, - f"{TEST_DATA}/wildcard-tls-secret/gb-wildcard-tls-secret.yaml") + subject_dict = get_server_certificate_subject( + wildcard_tls_secret_setup.public_endpoint.public_ip, + wildcard_tls_secret_setup.ingress_host, + wildcard_tls_secret_setup.public_endpoint.port_ssl, + ) + assert subject_dict[b"C"] == b"ES" + assert subject_dict[b"ST"] == b"CanaryIslands" + assert subject_dict[b"CN"] == b"example.com" + + def test_certificate_subject_updates_after_secret_update( + self, + kube_apis, + ingress_controller_prerequisites, + wildcard_tls_secret_ingress_controller, + wildcard_tls_secret_setup, + ): + delete_secret( + kube_apis.v1, wildcard_tls_secret_ingress_controller.secret_name, ingress_controller_prerequisites.namespace + ) + create_secret_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.namespace, + f"{TEST_DATA}/wildcard-tls-secret/gb-wildcard-tls-secret.yaml", + ) wait_before_test(1) - subject_dict = get_server_certificate_subject(wildcard_tls_secret_setup.public_endpoint.public_ip, - wildcard_tls_secret_setup.ingress_host, - wildcard_tls_secret_setup.public_endpoint.port_ssl) - assert subject_dict[b'C'] == b'GB' - assert subject_dict[b'ST'] == b'Cambridgeshire' - assert subject_dict[b'CN'] == b'cafe.example.com' - - def test_response_and_subject_remains_after_secret_delete(self, kube_apis, ingress_controller_prerequisites, - wildcard_tls_secret_ingress_controller, - wildcard_tls_secret_setup): - delete_secret(kube_apis.v1, wildcard_tls_secret_ingress_controller.secret_name, - ingress_controller_prerequisites.namespace) + subject_dict = get_server_certificate_subject( + wildcard_tls_secret_setup.public_endpoint.public_ip, + wildcard_tls_secret_setup.ingress_host, + wildcard_tls_secret_setup.public_endpoint.port_ssl, + ) + assert subject_dict[b"C"] == b"GB" + assert subject_dict[b"ST"] == b"Cambridgeshire" + assert subject_dict[b"CN"] == b"cafe.example.com" + + def test_response_and_subject_remains_after_secret_delete( + self, + kube_apis, + ingress_controller_prerequisites, + wildcard_tls_secret_ingress_controller, + wildcard_tls_secret_setup, + ): + delete_secret( + kube_apis.v1, wildcard_tls_secret_ingress_controller.secret_name, ingress_controller_prerequisites.namespace + ) wait_before_test(1) - req_url = f"https://{wildcard_tls_secret_setup.public_endpoint.public_ip}:" \ - f"{wildcard_tls_secret_setup.public_endpoint.port_ssl}/backend1" + req_url = ( + f"https://{wildcard_tls_secret_setup.public_endpoint.public_ip}:" + f"{wildcard_tls_secret_setup.public_endpoint.port_ssl}/backend1" + ) resp = requests.get(req_url, headers={"host": wildcard_tls_secret_setup.ingress_host}, verify=False) assert resp.status_code == 200 - subject_dict = get_server_certificate_subject(wildcard_tls_secret_setup.public_endpoint.public_ip, - wildcard_tls_secret_setup.ingress_host, - wildcard_tls_secret_setup.public_endpoint.port_ssl) - assert subject_dict[b'C'] == b'GB' - assert subject_dict[b'ST'] == b'Cambridgeshire' - assert subject_dict[b'CN'] == b'cafe.example.com' + subject_dict = get_server_certificate_subject( + wildcard_tls_secret_setup.public_endpoint.public_ip, + wildcard_tls_secret_setup.ingress_host, + wildcard_tls_secret_setup.public_endpoint.port_ssl, + ) + assert subject_dict[b"C"] == b"GB" + assert subject_dict[b"ST"] == b"Cambridgeshire" + assert subject_dict[b"CN"] == b"cafe.example.com" diff --git a/tests/suite/vs_vsr_resources_utils.py b/tests/suite/vs_vsr_resources_utils.py index 5b772e1053..cda34430b0 100644 --- a/tests/suite/vs_vsr_resources_utils.py +++ b/tests/suite/vs_vsr_resources_utils.py @@ -23,9 +23,7 @@ def read_vsr(custom_objects: CustomObjectsApi, namespace, name) -> object: return read_custom_resource(custom_objects, namespace, "virtualserverroutes", name) -def create_virtual_server_from_yaml( - custom_objects: CustomObjectsApi, yaml_manifest, namespace -) -> str: +def create_virtual_server_from_yaml(custom_objects: CustomObjectsApi, yaml_manifest, namespace) -> str: """ Create a VirtualServer based on yaml file. @@ -52,15 +50,11 @@ def create_virtual_server(custom_objects: CustomObjectsApi, vs, namespace) -> st """ print("Create a VirtualServer:") try: - custom_objects.create_namespaced_custom_object( - "k8s.nginx.org", "v1", namespace, "virtualservers", vs - ) + custom_objects.create_namespaced_custom_object("k8s.nginx.org", "v1", namespace, "virtualservers", vs) print(f"VirtualServer created with name '{vs['metadata']['name']}'") return vs["metadata"]["name"] except ApiException as ex: - logging.exception( - f"Exception: {ex} occurred while creating VirtualServer: {vs['metadata']['name']}" - ) + logging.exception(f"Exception: {ex} occurred while creating VirtualServer: {vs['metadata']['name']}") raise @@ -75,9 +69,7 @@ def delete_virtual_server(custom_objects: CustomObjectsApi, name, namespace) -> """ print(f"Delete a VirtualServer: {name}") - custom_objects.delete_namespaced_custom_object( - "k8s.nginx.org", "v1", namespace, "virtualservers", name - ) + custom_objects.delete_namespaced_custom_object("k8s.nginx.org", "v1", namespace, "virtualservers", name) ensure_item_removal( custom_objects.get_namespaced_custom_object, "k8s.nginx.org", @@ -89,9 +81,7 @@ def delete_virtual_server(custom_objects: CustomObjectsApi, name, namespace) -> print(f"VirtualServer was removed with name '{name}'") -def patch_virtual_server_from_yaml( - custom_objects: CustomObjectsApi, name, yaml_manifest, namespace -) -> None: +def patch_virtual_server_from_yaml(custom_objects: CustomObjectsApi, name, yaml_manifest, namespace) -> None: """ Patch a VS based on yaml manifest :param custom_objects: CustomObjectsApi @@ -106,9 +96,7 @@ def patch_virtual_server_from_yaml( try: print(f"Try to patch VirtualServer: {dep}") - custom_objects.patch_namespaced_custom_object( - "k8s.nginx.org", "v1", namespace, "virtualservers", name, dep - ) + custom_objects.patch_namespaced_custom_object("k8s.nginx.org", "v1", namespace, "virtualservers", name, dep) print(f"VirtualServer updated with name '{dep['metadata']['name']}'") except ApiException: logging.exception(f"Failed with exception while patching VirtualServer: {name}") @@ -118,9 +106,7 @@ def patch_virtual_server_from_yaml( raise -def delete_and_create_vs_from_yaml( - custom_objects: CustomObjectsApi, name, yaml_manifest, namespace -) -> None: +def delete_and_create_vs_from_yaml(custom_objects: CustomObjectsApi, name, yaml_manifest, namespace) -> None: """ Perform delete and create for vs with same name based on yaml @@ -149,16 +135,12 @@ def patch_virtual_server(custom_objects: CustomObjectsApi, name, namespace, body :return: str """ print("Update a VirtualServer:") - custom_objects.patch_namespaced_custom_object( - "k8s.nginx.org", "v1", namespace, "virtualservers", name, body - ) + custom_objects.patch_namespaced_custom_object("k8s.nginx.org", "v1", namespace, "virtualservers", name, body) print(f"VirtualServer updated with a name '{body['metadata']['name']}'") return body["metadata"]["name"] -def patch_v_s_route_from_yaml( - custom_objects: CustomObjectsApi, name, yaml_manifest, namespace -) -> None: +def patch_v_s_route_from_yaml(custom_objects: CustomObjectsApi, name, yaml_manifest, namespace) -> None: """ Update a VirtualServerRoute based on yaml manifest @@ -182,13 +164,12 @@ def patch_v_s_route_from_yaml( raise except Exception as ex: logging.exception( - f"Failed with exception while patching VirtualServerRoute: {name}, Exception: {ex.with_traceback}") + f"Failed with exception while patching VirtualServerRoute: {name}, Exception: {ex.with_traceback}" + ) raise -def get_vs_nginx_template_conf( - v1: CoreV1Api, vs_namespace, vs_name, pod_name, pod_namespace -) -> str: +def get_vs_nginx_template_conf(v1: CoreV1Api, vs_namespace, vs_name, pod_name, pod_namespace) -> str: """ Get contents of /etc/nginx/conf.d/vs_{namespace}_{vs_name}.conf in the pod. @@ -229,9 +210,7 @@ def create_v_s_route(custom_objects: CustomObjectsApi, vsr, namespace) -> str: :return: str """ print("Create a VirtualServerRoute:") - custom_objects.create_namespaced_custom_object( - "k8s.nginx.org", "v1", namespace, "virtualserverroutes", vsr - ) + custom_objects.create_namespaced_custom_object("k8s.nginx.org", "v1", namespace, "virtualserverroutes", vsr) print(f"VirtualServerRoute created with a name '{vsr['metadata']['name']}'") return vsr["metadata"]["name"] @@ -247,9 +226,7 @@ def patch_v_s_route(custom_objects: CustomObjectsApi, name, namespace, body) -> :return: str """ print("Update a VirtualServerRoute:") - custom_objects.patch_namespaced_custom_object( - "k8s.nginx.org", "v1", namespace, "virtualserverroutes", name, body - ) + custom_objects.patch_namespaced_custom_object("k8s.nginx.org", "v1", namespace, "virtualserverroutes", name, body) print(f"VirtualServerRoute updated with a name '{body['metadata']['name']}'") return body["metadata"]["name"] diff --git a/tests/suite/yaml_utils.py b/tests/suite/yaml_utils.py index c2cfc11f3a..c7c8c43d62 100644 --- a/tests/suite/yaml_utils.py +++ b/tests/suite/yaml_utils.py @@ -13,7 +13,7 @@ def get_first_ingress_host_from_yaml(file) -> str: with open(file) as f: docs = yaml.safe_load_all(f) for dep in docs: - return dep['spec']['rules'][0]['host'] + return dep["spec"]["rules"][0]["host"] def get_name_from_yaml(file) -> str: @@ -27,9 +27,10 @@ def get_name_from_yaml(file) -> str: with open(file) as f: docs = yaml.safe_load_all(f) for dep in docs: - return dep['metadata']['name'] + return dep["metadata"]["name"] return res + def get_namespace_from_yaml(file) -> str: """ Parse yaml file and return first metadata.name appeared. @@ -42,12 +43,13 @@ def get_namespace_from_yaml(file) -> str: docs = yaml.safe_load_all(f) for dep in docs: try: - res = dep['metadata']['namespace'] + res = dep["metadata"]["namespace"] break except KeyError: continue return res + def get_paths_from_vs_yaml(file) -> []: """ Parse yaml file and return all the found spec.routes.path. @@ -59,8 +61,8 @@ def get_paths_from_vs_yaml(file) -> []: with open(file) as f: docs = yaml.safe_load_all(f) for dep in docs: - for route in dep['spec']['routes']: - res.append(route['path']) + for route in dep["spec"]["routes"]: + res.append(route["path"]) return res @@ -74,7 +76,7 @@ def get_first_host_from_yaml(file) -> str: with open(file) as f: docs = yaml.safe_load_all(f) for dep in docs: - return dep['spec']['host'] + return dep["spec"]["host"] def get_configmap_fields_from_yaml(file) -> {}: @@ -86,7 +88,7 @@ def get_configmap_fields_from_yaml(file) -> {}: """ with open(file) as f: dep = yaml.safe_load(f) - return dep['data'] + return dep["data"] def get_route_namespace_from_vs_yaml(file) -> []: @@ -100,8 +102,8 @@ def get_route_namespace_from_vs_yaml(file) -> []: with open(file) as f: docs = yaml.safe_load_all(f) for dep in docs: - for route in dep['spec']['routes']: - res.append(route['route'].split('/')[0]) + for route in dep["spec"]["routes"]: + res.append(route["route"].split("/")[0]) return res @@ -116,8 +118,8 @@ def get_paths_from_vsr_yaml(file) -> []: with open(file) as f: docs = yaml.safe_load_all(f) for dep in docs: - for route in dep['spec']['subroutes']: - res.append(route['path']) + for route in dep["spec"]["subroutes"]: + res.append(route["path"]) return res @@ -132,5 +134,5 @@ def get_secret_name_from_vs_yaml(file) -> str: with open(file) as f: docs = yaml.safe_load_all(f) for dep in docs: - return dep['spec']['tls']['secret'] + return dep["spec"]["tls"]["secret"] return res