diff --git a/tests/data/virtual-server-error-pages/standard/virtual-server.yaml b/tests/data/virtual-server-error-pages/standard/virtual-server.yaml new file mode 100644 index 0000000000..dc622fc951 --- /dev/null +++ b/tests/data/virtual-server-error-pages/standard/virtual-server.yaml @@ -0,0 +1,35 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: virtual-server +spec: + host: virtual-server.example.com + upstreams: + - name: backend2 + service: backend2-svc + port: 80 + - name: backend1 + service: backend1-svc + port: 80 + routes: + - path: "/backend1" + errorPages: + - codes: [502] + redirect: + code: 307 + url: ${scheme}://virtual-server.example.com/error.html + action: + pass: backend1 + - path: "/backend2" + errorPages: + - codes: [502] + return: + code: 207 + type: application/json + body: | + {\"status\": \"${upstream_status}\",\"message\":\"Forbidden\"} + headers: + - name: x-debug-original-status + value: ${upstream_status} + action: + pass: backend2 \ No newline at end of file diff --git a/tests/data/virtual-server-error-pages/virtual-server-invalid.yaml b/tests/data/virtual-server-error-pages/virtual-server-invalid.yaml new file mode 100644 index 0000000000..177615f52e --- /dev/null +++ b/tests/data/virtual-server-error-pages/virtual-server-invalid.yaml @@ -0,0 +1,35 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: virtual-server +spec: + host: virtual-server.example.com + upstreams: + - name: backend2 + service: backend2-svc + port: 80 + - name: backend1 + service: backend1-svc + port: 80 + routes: + - path: "/backend1" + errorPages: + - codes: [308] + redirect: + code: 101 + url: /relative/path/url.html + action: + pass: backend1 + - path: "/backend2" + errorPages: + - codes: [502] + return: + code: 100 + type: ±!@£$%^&*() + body: | + {\"status\": \"${status}\",\"message\":\"Forbidden\"} + headers: + - name: x-debug-original-status + value: ${schema} + action: + pass: backend2 \ No newline at end of file diff --git a/tests/data/virtual-server-error-pages/virtual-server-matches.yaml b/tests/data/virtual-server-error-pages/virtual-server-matches.yaml new file mode 100644 index 0000000000..f9bac75974 --- /dev/null +++ b/tests/data/virtual-server-error-pages/virtual-server-matches.yaml @@ -0,0 +1,52 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: virtual-server +spec: + host: virtual-server.example.com + upstreams: + - name: backend2 + service: backend2-svc + port: 80 + - name: backend4-stable + service: backend4-stable-svc + port: 80 + - name: backend1-future + service: backend1-future-svc + port: 80 + - name: backend3-deprecated + service: backend3-deprecated-svc + port: 80 + routes: + - path: "/backend1" + matches: + - conditions: + - header: x-version + value: future + action: + pass: backend1-future + - conditions: + - header: x-version + value: deprecated + action: + pass: backend3-deprecated + action: + pass: backend4-stable + errorPages: + - codes: [502, 404] + redirect: + code: 307 + url: ${scheme}://virtual-server.example.com/error.html + - path: "/backend2" + errorPages: + - codes: [502] + return: + code: 207 + type: application/json + body: | + {\"status\": \"${upstream_status}\",\"message\":\"Forbidden\"} + headers: + - name: x-debug-original-status + value: ${upstream_status} + action: + pass: backend2 \ No newline at end of file diff --git a/tests/data/virtual-server-error-pages/virtual-server-splits.yaml b/tests/data/virtual-server-error-pages/virtual-server-splits.yaml new file mode 100644 index 0000000000..2c1c5bf7d8 --- /dev/null +++ b/tests/data/virtual-server-error-pages/virtual-server-splits.yaml @@ -0,0 +1,43 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: virtual-server +spec: + host: virtual-server.example.com + upstreams: + - name: backend2 + service: backend2-svc + port: 80 + - name: backend1-v1 + service: backend1-svc-v1 + port: 80 + - name: backend1-v2 + service: backend1-svc-v2 + port: 80 + routes: + - path: "/backend1" + splits: + - weight: 90 + action: + pass: backend1-v1 + - weight: 10 + action: + pass: backend1-v2 + errorPages: + - codes: [502] + redirect: + code: 308 + url: ${scheme}://virtual-server.example.com/error.html + - path: "/backend2" + errorPages: + - codes: [502] + return: + code: 207 + type: application/json + body: | + {\"status\": \"${upstream_status}\",\"message\":\"Forbidden\"} + headers: + - name: x-debug-original-status + value: ${upstream_status} + action: + pass: backend2 \ No newline at end of file diff --git a/tests/data/virtual-server-error-pages/virtual-server-updated.yaml b/tests/data/virtual-server-error-pages/virtual-server-updated.yaml new file mode 100644 index 0000000000..804f572a8d --- /dev/null +++ b/tests/data/virtual-server-error-pages/virtual-server-updated.yaml @@ -0,0 +1,29 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: virtual-server +spec: + host: virtual-server.example.com + upstreams: + - name: backend2 + service: backend2-svc + port: 80 + - name: backend1 + service: backend1-svc + port: 80 + routes: + - path: "/backend1" + errorPages: + - codes: [502, 404] + redirect: + url: ${scheme}://virtual-server.example.com/error_${http_x_forwarded_proto}.html + action: + pass: backend1 + - path: "/backend2" + errorPages: + - codes: [502] + return: + body: | + Hello World! + action: + pass: backend2 \ No newline at end of file diff --git a/tests/data/virtual-server-route-error-pages/route-multiple-invalid.yaml b/tests/data/virtual-server-route-error-pages/route-multiple-invalid.yaml new file mode 100644 index 0000000000..9866aae68f --- /dev/null +++ b/tests/data/virtual-server-route-error-pages/route-multiple-invalid.yaml @@ -0,0 +1,35 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServerRoute +metadata: + name: backends +spec: + host: virtual-server-route.example.com + upstreams: + - name: backend1 + service: backend1-svc + port: 80 + - name: backend3 + service: backend3-svc + port: 80 + subroutes: + - path: "/backends/backend1" + errorPages: + - codes: [308] + redirect: + code: 101 + url: /relative/path/url.html + action: + pass: backend1 + - path: "/backends/backend3" + errorPages: + - codes: [502] + return: + code: 100 + type: ±!@£$%^&*() + body: | + {\"status\": \"${status}\",\"message\":\"Forbidden\"} + headers: + - name: x-debug-original-status + value: ${schema} + action: + pass: backend3 \ No newline at end of file diff --git a/tests/data/virtual-server-route-error-pages/route-multiple-matches.yaml b/tests/data/virtual-server-route-error-pages/route-multiple-matches.yaml new file mode 100644 index 0000000000..b659f5887d --- /dev/null +++ b/tests/data/virtual-server-route-error-pages/route-multiple-matches.yaml @@ -0,0 +1,52 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServerRoute +metadata: + name: backends +spec: + host: virtual-server-route.example.com + upstreams: + - name: backend1 + service: backend1-svc + port: 80 + - name: backend4-stable + service: backend4-stable-svc + port: 80 + - name: backend1-future + service: backend1-future-svc + port: 80 + - name: backend3-deprecated + service: backend3-deprecated-svc + port: 80 + subroutes: + - path: "/backends/backend1" + matches: + - conditions: + - argument: arg1 + value: v1 + action: + pass: backend1-future + - conditions: + - argument: arg1 + value: v2 + action: + pass: backend3-deprecated + errorPages: + - codes: [502, 404] + redirect: + code: 307 + url: ${scheme}://virtual-server-route.example.com/error.html + action: + pass: backend4-stable + - path: "/backends/backend3" + errorPages: + - codes: [502] + return: + code: 207 + type: application/json + body: | + {\"status\": \"${upstream_status}\",\"message\":\"Forbidden\"} + headers: + - name: x-debug-original-status + value: ${upstream_status} + action: + pass: backend3-deprecated \ No newline at end of file diff --git a/tests/data/virtual-server-route-error-pages/route-multiple-splits.yaml b/tests/data/virtual-server-route-error-pages/route-multiple-splits.yaml new file mode 100644 index 0000000000..62e0f2a917 --- /dev/null +++ b/tests/data/virtual-server-route-error-pages/route-multiple-splits.yaml @@ -0,0 +1,43 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServerRoute +metadata: + name: backends +spec: + host: virtual-server-route.example.com + upstreams: + - name: backend1-v1 + service: backend1-svc-v1 + port: 80 + - name: backend1-v2 + service: backend1-svc-v2 + port: 80 + - name: backend3 + service: backend3-svc + port: 80 + subroutes: + - path: "/backends/backend1" + splits: + - weight: 90 + action: + pass: backend1-v1 + - weight: 10 + action: + pass: backend1-v2 + errorPages: + - codes: [502] + redirect: + code: 308 + url: ${scheme}://virtual-server-route.example.com/error.html + - path: "/backends/backend3" + errorPages: + - codes: [502] + return: + code: 207 + type: application/json + body: | + {\"status\": \"${upstream_status}\",\"message\":\"Forbidden\"} + headers: + - name: x-debug-original-status + value: ${upstream_status} + action: + pass: backend3 \ No newline at end of file diff --git a/tests/data/virtual-server-route-error-pages/route-multiple-updated.yaml b/tests/data/virtual-server-route-error-pages/route-multiple-updated.yaml new file mode 100644 index 0000000000..fec87d9072 --- /dev/null +++ b/tests/data/virtual-server-route-error-pages/route-multiple-updated.yaml @@ -0,0 +1,29 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServerRoute +metadata: + name: backends +spec: + host: virtual-server-route.example.com + upstreams: + - name: backend1 + service: backend1-svc + port: 80 + - name: backend3 + service: backend3-svc + port: 80 + subroutes: + - path: "/backends/backend1" + errorPages: + - codes: [502, 404] + redirect: + url: ${scheme}://virtual-server-route.example.com/error_${http_x_forwarded_proto}.html + action: + pass: backend1 + - path: "/backends/backend3" + errorPages: + - codes: [502] + return: + body: | + Hello World! + action: + pass: backend3 \ No newline at end of file diff --git a/tests/data/virtual-server-route-error-pages/route-multiple.yaml b/tests/data/virtual-server-route-error-pages/route-multiple.yaml new file mode 100644 index 0000000000..4da8b4d7ed --- /dev/null +++ b/tests/data/virtual-server-route-error-pages/route-multiple.yaml @@ -0,0 +1,35 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServerRoute +metadata: + name: backends +spec: + host: virtual-server-route.example.com + upstreams: + - name: backend1 + service: backend1-svc + port: 80 + - name: backend3 + service: backend3-svc + port: 80 + subroutes: + - path: "/backends/backend1" + errorPages: + - codes: [502] + redirect: + code: 307 + url: ${scheme}://virtual-server-route.example.com/error.html + action: + pass: backend1 + - path: "/backends/backend3" + errorPages: + - codes: [502] + return: + code: 207 + type: application/json + body: | + {\"status\": \"${upstream_status}\",\"message\":\"Forbidden\"} + headers: + - name: x-debug-original-status + value: ${upstream_status} + action: + pass: backend3 \ No newline at end of file diff --git a/tests/data/virtual-server-route-error-pages/route-single-invalid.yaml b/tests/data/virtual-server-route-error-pages/route-single-invalid.yaml new file mode 100644 index 0000000000..32494ec93e --- /dev/null +++ b/tests/data/virtual-server-route-error-pages/route-single-invalid.yaml @@ -0,0 +1,19 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServerRoute +metadata: + name: backend2 +spec: + host: virtual-server-route.example.com + upstreams: + - name: backend2 + service: backend2-svc + port: 80 + subroutes: + - path: "/backend2" + errorPages: + - codes: [502] + redirect: + code: 307 + url: + action: + pass: backend2 \ No newline at end of file diff --git a/tests/data/virtual-server-route-error-pages/route-single.yaml b/tests/data/virtual-server-route-error-pages/route-single.yaml new file mode 100644 index 0000000000..f18b2cc1d1 --- /dev/null +++ b/tests/data/virtual-server-route-error-pages/route-single.yaml @@ -0,0 +1,19 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServerRoute +metadata: + name: backend2 +spec: + host: virtual-server-route.example.com + upstreams: + - name: backend2 + service: backend2-svc + port: 80 + subroutes: + - path: "/backend2" + errorPages: + - codes: [502] + redirect: + code: 307 + url: ${scheme}://virtual-server.example.com/error.html + action: + pass: backend2 \ No newline at end of file diff --git a/tests/data/virtual-server-route-error-pages/standard/virtual-server-updated.yaml b/tests/data/virtual-server-route-error-pages/standard/virtual-server-updated.yaml new file mode 100644 index 0000000000..d3660bbd73 --- /dev/null +++ b/tests/data/virtual-server-route-error-pages/standard/virtual-server-updated.yaml @@ -0,0 +1,16 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: virtual-server-route +spec: + host: virtual-server-route.example.com + routes: + - path: "/backends" + route: backends + errorPages: + - codes: [502] + return: + code: 402 + body: Hello World! + - path: "/backend2" + route: backend2-namespace/backend2 \ No newline at end of file diff --git a/tests/data/virtual-server-route-error-pages/standard/virtual-server.yaml b/tests/data/virtual-server-route-error-pages/standard/virtual-server.yaml new file mode 100644 index 0000000000..179878752a --- /dev/null +++ b/tests/data/virtual-server-route-error-pages/standard/virtual-server.yaml @@ -0,0 +1,11 @@ +apiVersion: k8s.nginx.org/v1 +kind: VirtualServer +metadata: + name: virtual-server-route +spec: + host: virtual-server-route.example.com + routes: + - path: "/backends" + route: backends # implicit namespace + - path: "/backend2" + route: backend2-namespace/backend2 \ No newline at end of file diff --git a/tests/suite/test_v_s_route_error_pages.py b/tests/suite/test_v_s_route_error_pages.py new file mode 100644 index 0000000000..b67e45a08e --- /dev/null +++ b/tests/suite/test_v_s_route_error_pages.py @@ -0,0 +1,132 @@ +import requests +import pytest +import json + +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.custom_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 + + +@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) +class TestVSRErrorPages: + 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 + + 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_content = json.loads(resp.content) + 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): + 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 + + 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): + 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.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" + ] + 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} is invalid and was rejected: " + vsr_m_event_text = f"VirtualServerRoute {text_m} is invalid and was rejected: " + 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) + 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) + + assert_event_starts_with_text_and_contains_errors(vsr_s_event_text, vsr_s_events, invalid_fields_s) + assert_event_starts_with_text_and_contains_errors(vsr_m_event_text, vsr_m_events, invalid_fields_m) + assert "upstream" not in config + + @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 + + 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 + diff --git a/tests/suite/test_virtual_server_error_pages.py b/tests/suite/test_virtual_server_error_pages.py new file mode 100644 index 0000000000..4a753a5f62 --- /dev/null +++ b/tests/suite/test_virtual_server_error_pages.py @@ -0,0 +1,87 @@ +import pytest +import json +import requests + +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.custom_resources_utils import patch_virtual_server_from_yaml +from suite.resources_utils import wait_before_test, get_first_pod_name, 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-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 + + 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_content = json.loads(resp.content) + 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 + + 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' + + 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.code: Invalid value: 100", + "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} is invalid and was rejected: " + 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) + 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) + + @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