github.com/nginxinc/kubernetes-ingress@v1.12.5/tests/suite/test_v_s_route_error_pages.py (about)

     1  import requests
     2  import pytest
     3  import json
     4  
     5  from kubernetes.client.rest import ApiException
     6  
     7  from settings import TEST_DATA
     8  from suite.custom_assertions import wait_and_assert_status_code, \
     9      assert_event_starts_with_text_and_contains_errors
    10  from suite.custom_resources_utils import get_vs_nginx_template_conf, patch_v_s_route_from_yaml, \
    11      patch_virtual_server_from_yaml
    12  from suite.resources_utils import get_first_pod_name, get_events, wait_before_test
    13  
    14  
    15  @pytest.mark.vsr
    16  @pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup',
    17                           [({"type": "complete", "extra_args": [f"-enable-custom-resources"]},
    18                             {"example": "virtual-server-route-error-pages"})],
    19                           indirect=True)
    20  class TestVSRErrorPages:
    21      def test_redirect_strategy(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller,
    22                                 v_s_route_setup):
    23          req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}"
    24          wait_and_assert_status_code(307, f"{req_url}{v_s_route_setup.route_m.paths[0]}",
    25                                      v_s_route_setup.vs_host, allow_redirects=False)
    26          resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}",
    27                              headers={"host": v_s_route_setup.vs_host}, allow_redirects=False)
    28          assert f'http://{v_s_route_setup.vs_host}/error.html' in resp.next.url
    29  
    30      def test_return_strategy(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller,
    31                               v_s_route_setup):
    32          req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}"
    33          wait_and_assert_status_code(207, f"{req_url}{v_s_route_setup.route_m.paths[1]}", v_s_route_setup.vs_host)
    34          resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}",
    35                              headers={"host": v_s_route_setup.vs_host})
    36          resp_content = json.loads(resp.content)
    37          assert resp_content['status'] == '502' \
    38              and resp_content['message'] == 'Forbidden' \
    39              and resp.headers.get('x-debug-original-status') == '502'
    40  
    41      def test_virtual_server_after_update(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller,
    42                                           v_s_route_setup):
    43          req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}"
    44          patch_v_s_route_from_yaml(kube_apis.custom_objects,
    45                                    v_s_route_setup.route_m.name,
    46                                    f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple-updated.yaml",
    47                                    v_s_route_setup.route_m.namespace)
    48          wait_and_assert_status_code(301, f"{req_url}{v_s_route_setup.route_m.paths[0]}",
    49                                      v_s_route_setup.vs_host, allow_redirects=False)
    50          resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}",
    51                              headers={"host": v_s_route_setup.vs_host, "x-forwarded-proto": "http"},
    52                              allow_redirects=False)
    53          assert f'http://{v_s_route_setup.vs_host}/error_http.html' in resp.next.url
    54  
    55          wait_and_assert_status_code(502, f"{req_url}{v_s_route_setup.route_m.paths[1]}",
    56                                      v_s_route_setup.vs_host, allow_redirects=False)
    57          resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[1]}",
    58                              headers={"host": v_s_route_setup.vs_host})
    59          resp_content = resp.content.decode('utf-8')
    60          assert resp_content == 'Hello World!\n'
    61  
    62      def test_validation_event_flow(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller,
    63                                     v_s_route_setup):
    64          invalid_fields_m = [
    65              "spec.subroutes[0].errorPages[0].redirect.url: Invalid value",
    66              "spec.subroutes[0].errorPages[0].redirect.code: Invalid value: 101",
    67              "spec.subroutes[1].errorPages[0].return.body: Invalid value: \"status\"",
    68              "spec.subroutes[1].errorPages[0].return.code: Invalid value: 100",
    69              "spec.subroutes[1].errorPages[0].return.headers[0].value: Invalid value: \"schema\""
    70          ]
    71          invalid_fields_s = [
    72              "spec.subroutes[0].errorPages[0].redirect.url: Required value: must specify a url"
    73          ]
    74          text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}"
    75          text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}"
    76          vsr_s_event_text = f"VirtualServerRoute {text_s} was rejected with error:"
    77          vsr_m_event_text = f"VirtualServerRoute {text_m} was rejected with error:"
    78          patch_v_s_route_from_yaml(kube_apis.custom_objects,
    79                                    v_s_route_setup.route_s.name,
    80                                    f"{TEST_DATA}/virtual-server-route-error-pages/route-single-invalid.yaml",
    81                                    v_s_route_setup.route_s.namespace)
    82          patch_v_s_route_from_yaml(kube_apis.custom_objects,
    83                                    v_s_route_setup.route_m.name,
    84                                    f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple-invalid.yaml",
    85                                    v_s_route_setup.route_m.namespace)
    86          wait_before_test(2)
    87          ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
    88          config = get_vs_nginx_template_conf(kube_apis.v1,
    89                                              v_s_route_setup.namespace,
    90                                              v_s_route_setup.vs_name,
    91                                              ic_pod_name,
    92                                              ingress_controller_prerequisites.namespace)
    93          vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace)
    94          vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace)
    95  
    96          assert_event_starts_with_text_and_contains_errors(vsr_s_event_text, vsr_s_events, invalid_fields_s)
    97          assert_event_starts_with_text_and_contains_errors(vsr_m_event_text, vsr_m_events, invalid_fields_m)
    98          assert "upstream" not in config
    99  
   100      def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites,
   101                                       crd_ingress_controller, v_s_route_setup):
   102          ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
   103          config_old = get_vs_nginx_template_conf(kube_apis.v1,
   104                                                  v_s_route_setup.namespace,
   105                                                  v_s_route_setup.vs_name,
   106                                                  ic_pod_name,
   107                                                  ingress_controller_prerequisites.namespace)
   108          vsr_src = f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple-invalid-openapi.yaml"
   109          try:
   110              patch_v_s_route_from_yaml(kube_apis.custom_objects,
   111                                        v_s_route_setup.route_m.name,
   112                                        vsr_src,
   113                                        v_s_route_setup.route_m.namespace)
   114          except ApiException as ex:
   115              assert ex.status == 422 \
   116                     and "spec.subroutes.errorPages.codes" in ex.body \
   117                     and "spec.subroutes.errorPages.redirect.code" in ex.body \
   118                     and "spec.subroutes.errorPages.redirect.url" in ex.body \
   119                     and "spec.subroutes.errorPages.return.code" in ex.body \
   120                     and "spec.subroutes.errorPages.return.type" in ex.body \
   121                     and "spec.subroutes.errorPages.return.body" in ex.body \
   122                     and "spec.subroutes.errorPages.return.headers.name" in ex.body \
   123                     and "spec.subroutes.errorPages.return.headers.value" in ex.body
   124          except Exception as ex:
   125              pytest.fail(f"An unexpected exception is raised: {ex}")
   126          else:
   127              pytest.fail("Expected an exception but there was none")
   128  
   129          wait_before_test(1)
   130          config_new = get_vs_nginx_template_conf(kube_apis.v1,
   131                                                  v_s_route_setup.namespace,
   132                                                  v_s_route_setup.vs_name,
   133                                                  ic_pod_name,
   134                                                  ingress_controller_prerequisites.namespace)
   135          assert config_old == config_new, "Expected: config doesn't change"
   136  
   137      @pytest.mark.parametrize('v_s_r_data', [
   138          {"src": "route-multiple-splits.yaml", "expected_code": 308},
   139          {"src": "route-multiple-matches.yaml", "expected_code": 307}
   140      ])
   141      def test_splits_and_matches(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller,
   142                                  v_s_route_setup, v_s_r_data):
   143          req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}"
   144          patch_v_s_route_from_yaml(kube_apis.custom_objects,
   145                                    v_s_route_setup.route_m.name,
   146                                    f"{TEST_DATA}/virtual-server-route-error-pages/{v_s_r_data['src']}",
   147                                    v_s_route_setup.route_m.namespace)
   148          wait_and_assert_status_code(v_s_r_data["expected_code"], f"{req_url}{v_s_route_setup.route_m.paths[0]}",
   149                                      v_s_route_setup.vs_host, allow_redirects=False)
   150          resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}",
   151                              headers={"host": v_s_route_setup.vs_host}, allow_redirects=False)
   152          assert f'http://{v_s_route_setup.vs_host}/error.html' in resp.next.url
   153  
   154      def test_vsr_overrides_vs(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller,
   155                                v_s_route_setup):
   156          req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}"
   157          vs_src = f"{TEST_DATA}/virtual-server-route-error-pages/standard/virtual-server-updated.yaml"
   158          patch_virtual_server_from_yaml(kube_apis.custom_objects,
   159                                         v_s_route_setup.vs_name,
   160                                         vs_src,
   161                                         v_s_route_setup.namespace)
   162          patch_v_s_route_from_yaml(kube_apis.custom_objects,
   163                                    v_s_route_setup.route_m.name,
   164                                    f"{TEST_DATA}/virtual-server-route-error-pages/route-multiple.yaml",
   165                                    v_s_route_setup.route_m.namespace)
   166          wait_and_assert_status_code(307, f"{req_url}{v_s_route_setup.route_m.paths[0]}",
   167                                      v_s_route_setup.vs_host, allow_redirects=False)
   168          resp = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}",
   169                              headers={"host": v_s_route_setup.vs_host}, allow_redirects=False)
   170          assert f'http://{v_s_route_setup.vs_host}/error.html' in resp.next.url