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

     1  import requests
     2  import pytest
     3  from kubernetes.client.rest import ApiException
     4  
     5  from settings import TEST_DATA
     6  from suite.custom_assertions import assert_event_and_get_count, assert_event_count_increased, assert_response_codes, \
     7      assert_event, assert_event_starts_with_text_and_contains_errors, assert_vs_conf_not_exists
     8  from suite.custom_resources_utils import get_vs_nginx_template_conf, patch_virtual_server_from_yaml, \
     9      patch_virtual_server, generate_item_with_upstream_options
    10  from suite.resources_utils import get_first_pod_name, wait_before_test, replace_configmap_from_yaml, get_events
    11  
    12  
    13  @pytest.mark.vs
    14  @pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup',
    15                           [({"type": "complete", "extra_args": [f"-enable-custom-resources"]},
    16                             {"example": "virtual-server-upstream-options", "app_type": "simple"})],
    17                           indirect=True)
    18  class TestVirtualServerUpstreamOptions:
    19      def test_nginx_config_defaults(self, kube_apis, ingress_controller_prerequisites,
    20                                     crd_ingress_controller, virtual_server_setup):
    21          print("Case 1: no ConfigMap key, no options in VS")
    22          ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
    23          config = get_vs_nginx_template_conf(kube_apis.v1,
    24                                              virtual_server_setup.namespace,
    25                                              virtual_server_setup.vs_name,
    26                                              ic_pod_name,
    27                                              ingress_controller_prerequisites.namespace)
    28  
    29          assert "random two least_conn;" in config
    30          assert "ip_hash;" not in config
    31          assert "hash " not in config
    32          assert "least_time " not in config
    33  
    34          assert "proxy_connect_timeout 60s;" in config
    35          assert "proxy_read_timeout 60s;" in config
    36          assert "proxy_send_timeout 60s;" in config
    37  
    38          assert "max_fails=1 fail_timeout=10s max_conns=0;" in config
    39          assert "slow_start" not in config
    40  
    41          assert "keepalive" not in config
    42          assert 'set $default_connection_header "";' not in config
    43          assert 'set $default_connection_header close;' in config
    44          assert "proxy_set_header Upgrade $http_upgrade;" in config
    45          assert "proxy_set_header Connection $vs_connection_header;" in config
    46          assert "proxy_http_version 1.1;" in config
    47  
    48          assert "proxy_next_upstream error timeout;" in config
    49          assert "proxy_next_upstream_timeout 0s;" in config
    50          assert "proxy_next_upstream_tries 0;" in config
    51  
    52          assert "client_max_body_size 1m;" in config
    53  
    54          assert "proxy_buffer_size" not in config
    55          assert "proxy_buffering on;" in config
    56          assert "proxy_buffers" not in config
    57  
    58          assert "sticky cookie" not in config
    59  
    60      @pytest.mark.parametrize('options, expected_strings', [
    61          ({"lb-method": "least_conn", "max-fails": 8,
    62            "fail-timeout": "13s", "connect-timeout": "55s", "read-timeout": "1s", "send-timeout": "1h",
    63            "keepalive": 54, "max-conns": 1048, "client-max-body-size": "1048K",
    64            "buffering": True, "buffer-size": "2k", "buffers": {"number": 4, "size": "2k"}},
    65           ["least_conn;", "max_fails=8 ",
    66            "fail_timeout=13s ", "proxy_connect_timeout 55s;", "proxy_read_timeout 1s;",
    67            "proxy_send_timeout 1h;", "keepalive 54;", 'set $default_connection_header "";', "max_conns=1048;",
    68            "client_max_body_size 1048K;",
    69            "proxy_buffering on;", "proxy_buffer_size 2k;", "proxy_buffers 4 2k;"]),
    70          ({"lb-method": "ip_hash", "connect-timeout": "75", "read-timeout": "15", "send-timeout": "1h"},
    71           ["ip_hash;", "proxy_connect_timeout 75s;", "proxy_read_timeout 15s;", "proxy_send_timeout 1h;"]),
    72          ({"connect-timeout": "1m", "read-timeout": "1m", "send-timeout": "1s"},
    73           ["proxy_connect_timeout 1m;", "proxy_read_timeout 1m;", "proxy_send_timeout 1s;"]),
    74          ({"next-upstream": "error timeout non_idempotent", "next-upstream-timeout": "5s", "next-upstream-tries": 10},
    75           ["proxy_next_upstream error timeout non_idempotent;",
    76            "proxy_next_upstream_timeout 5s;", "proxy_next_upstream_tries 10;"])
    77      ])
    78      def test_when_option_in_v_s_only(self, kube_apis, ingress_controller_prerequisites,
    79                                       crd_ingress_controller, virtual_server_setup,
    80                                       options, expected_strings):
    81          text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}"
    82          vs_event_text = f"Configuration for {text} was added or updated"
    83          events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace)
    84          initial_count = assert_event_and_get_count(vs_event_text, events_vs)
    85          print(f"Case 2: no key in ConfigMap , option specified in VS")
    86          new_body = generate_item_with_upstream_options(
    87              f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml",
    88              options)
    89          patch_virtual_server(kube_apis.custom_objects,
    90                               virtual_server_setup.vs_name, virtual_server_setup.namespace, new_body)
    91          wait_before_test(1)
    92          ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
    93          config = get_vs_nginx_template_conf(kube_apis.v1,
    94                                              virtual_server_setup.namespace,
    95                                              virtual_server_setup.vs_name,
    96                                              ic_pod_name,
    97                                              ingress_controller_prerequisites.namespace)
    98          resp_1 = requests.get(virtual_server_setup.backend_1_url,
    99                                headers={"host": virtual_server_setup.vs_host})
   100          resp_2 = requests.get(virtual_server_setup.backend_2_url,
   101                                headers={"host": virtual_server_setup.vs_host})
   102          vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace)
   103  
   104          assert_event_count_increased(vs_event_text, initial_count, vs_events)
   105          for _ in expected_strings:
   106              assert _ in config
   107          assert_response_codes(resp_1, resp_2)
   108  
   109      @pytest.mark.parametrize('config_map_file, expected_strings, unexpected_strings', [
   110          (f"{TEST_DATA}/virtual-server-upstream-options/configmap-with-keys.yaml",
   111           ["max_fails=3 ", "fail_timeout=33s ", "max_conns=0;",
   112            "proxy_connect_timeout 44s;", "proxy_read_timeout 22s;", "proxy_send_timeout 55s;",
   113            "keepalive 1024;", 'set $default_connection_header "";',
   114            "client_max_body_size 3m;",
   115            "proxy_buffering off;", "proxy_buffer_size 1k;", "proxy_buffers 8 1k;"],
   116           ["ip_hash;", "least_conn;", "random ", "hash", "least_time ",
   117            "max_fails=1 ", "fail_timeout=10s ", "max_conns=1000;",
   118            "proxy_connect_timeout 60s;", "proxy_read_timeout 60s;", "proxy_send_timeout 60s;",
   119            "client_max_body_size 1m;", "slow_start=0s",
   120            "proxy_buffering on;"]),
   121      ])
   122      def test_when_option_in_config_map_only(self, kube_apis, ingress_controller_prerequisites,
   123                                              crd_ingress_controller, virtual_server_setup, restore_configmap,
   124                                              config_map_file, expected_strings, unexpected_strings):
   125          text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}"
   126          vs_event_text = f"Configuration for {text} was added or updated"
   127          print(f"Case 3: key specified in ConfigMap, no option in VS")
   128          patch_virtual_server_from_yaml(kube_apis.custom_objects, virtual_server_setup.vs_name,
   129                                         f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml",
   130                                         virtual_server_setup.namespace)
   131          config_map_name = ingress_controller_prerequisites.config_map["metadata"]["name"]
   132          replace_configmap_from_yaml(kube_apis.v1, config_map_name,
   133                                      ingress_controller_prerequisites.namespace,
   134                                      config_map_file)
   135          wait_before_test(1)
   136          ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
   137          config = get_vs_nginx_template_conf(kube_apis.v1,
   138                                              virtual_server_setup.namespace,
   139                                              virtual_server_setup.vs_name,
   140                                              ic_pod_name,
   141                                              ingress_controller_prerequisites.namespace)
   142          resp_1 = requests.get(virtual_server_setup.backend_1_url,
   143                                headers={"host": virtual_server_setup.vs_host})
   144          resp_2 = requests.get(virtual_server_setup.backend_2_url,
   145                                headers={"host": virtual_server_setup.vs_host})
   146          vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace)
   147  
   148          assert_event(vs_event_text, vs_events)
   149          for _ in expected_strings:
   150              assert _ in config
   151          for _ in unexpected_strings:
   152              assert _ not in config
   153          assert_response_codes(resp_1, resp_2)
   154  
   155      @pytest.mark.parametrize('options, expected_strings, unexpected_strings', [
   156          ({"lb-method": "least_conn", "max-fails": 12,
   157            "fail-timeout": "1m", "connect-timeout": "1m", "read-timeout": "77s", "send-timeout": "23s",
   158            "keepalive": 48, "client-max-body-size": "0",
   159            "buffering": True, "buffer-size": "2k", "buffers": {"number": 4, "size": "2k"}},
   160           ["least_conn;", "max_fails=12 ",
   161            "fail_timeout=1m ", "max_conns=0;", "proxy_connect_timeout 1m;", "proxy_read_timeout 77s;",
   162            "proxy_send_timeout 23s;", "keepalive 48;", 'set $default_connection_header "";',
   163            "client_max_body_size 0;",
   164            "proxy_buffering on;", "proxy_buffer_size 2k;", "proxy_buffers 4 2k;"],
   165           ["ip_hash;", "random ", "hash", "least_time ", "max_fails=1 ",
   166            "fail_timeout=10s ", "proxy_connect_timeout 44s;", "proxy_read_timeout 22s;",
   167            "proxy_send_timeout 55s;", "keepalive 1024;",
   168            "client_max_body_size 3m;", "client_max_body_size 1m;",
   169            "proxy_buffering off;", "proxy_buffer_size 1k;", "proxy_buffers 8 1k;"])
   170      ])
   171      def test_v_s_overrides_config_map(self, kube_apis, ingress_controller_prerequisites,
   172                                        crd_ingress_controller, virtual_server_setup, restore_configmap,
   173                                        options, expected_strings, unexpected_strings):
   174          text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}"
   175          vs_event_text = f"Configuration for {text} was added or updated"
   176          events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace)
   177          initial_count = assert_event_and_get_count(vs_event_text, events_vs)
   178          print(f"Case 4: key in ConfigMap, option specified in VS")
   179          new_body = generate_item_with_upstream_options(
   180              f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml",
   181              options)
   182          patch_virtual_server(kube_apis.custom_objects,
   183                               virtual_server_setup.vs_name, virtual_server_setup.namespace, new_body)
   184          config_map_name = ingress_controller_prerequisites.config_map["metadata"]["name"]
   185          replace_configmap_from_yaml(kube_apis.v1, config_map_name,
   186                                      ingress_controller_prerequisites.namespace,
   187                                      f"{TEST_DATA}/virtual-server-upstream-options/configmap-with-keys.yaml")
   188          wait_before_test(1)
   189          ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
   190          config = get_vs_nginx_template_conf(kube_apis.v1,
   191                                              virtual_server_setup.namespace,
   192                                              virtual_server_setup.vs_name,
   193                                              ic_pod_name,
   194                                              ingress_controller_prerequisites.namespace)
   195          resp_1 = requests.get(virtual_server_setup.backend_1_url,
   196                                headers={"host": virtual_server_setup.vs_host})
   197          resp_2 = requests.get(virtual_server_setup.backend_2_url,
   198                                headers={"host": virtual_server_setup.vs_host})
   199          vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace)
   200  
   201          assert_event_count_increased(vs_event_text, initial_count, vs_events)
   202          for _ in expected_strings:
   203              assert _ in config
   204          for _ in unexpected_strings:
   205              assert _ not in config
   206          assert_response_codes(resp_1, resp_2)
   207  
   208  
   209  @pytest.mark.vs
   210  @pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup',
   211                           [({"type": "complete", "extra_args": [f"-enable-custom-resources"]},
   212                             {"example": "virtual-server-upstream-options", "app_type": "simple"})],
   213                           indirect=True)
   214  class TestVirtualServerUpstreamOptionValidation:
   215      def test_event_message_and_config(self, kube_apis, ingress_controller_prerequisites,
   216                                        crd_ingress_controller, virtual_server_setup):
   217          invalid_fields = [
   218              "upstreams[0].lb-method", "upstreams[0].fail-timeout",
   219              "upstreams[0].max-fails", "upstreams[0].connect-timeout",
   220              "upstreams[0].read-timeout", "upstreams[0].send-timeout",
   221              "upstreams[0].keepalive", "upstreams[0].max-conns",
   222              "upstreams[0].next-upstream",
   223              "upstreams[0].next-upstream-timeout", "upstreams[0].next-upstream-tries",
   224              "upstreams[0].client-max-body-size",
   225              "upstreams[0].buffers.number", "upstreams[0].buffers.size", "upstreams[0].buffer-size",
   226              "upstreams[1].lb-method", "upstreams[1].fail-timeout",
   227              "upstreams[1].max-fails", "upstreams[1].connect-timeout",
   228              "upstreams[1].read-timeout", "upstreams[1].send-timeout",
   229              "upstreams[1].keepalive", "upstreams[1].max-conns",
   230              "upstreams[1].next-upstream",
   231              "upstreams[1].next-upstream-timeout", "upstreams[1].next-upstream-tries",
   232              "upstreams[1].client-max-body-size",
   233              "upstreams[1].buffers.number", "upstreams[1].buffers.size", "upstreams[1].buffer-size"
   234          ]
   235          text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}"
   236          vs_event_text = f"VirtualServer {text} was rejected with error:"
   237          vs_file = f"{TEST_DATA}/virtual-server-upstream-options/virtual-server-with-invalid-keys.yaml"
   238          patch_virtual_server_from_yaml(kube_apis.custom_objects,
   239                                         virtual_server_setup.vs_name,
   240                                         vs_file,
   241                                         virtual_server_setup.namespace)
   242          wait_before_test(2)
   243          ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
   244          vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace)
   245  
   246          assert_event_starts_with_text_and_contains_errors(vs_event_text, vs_events, invalid_fields)
   247          assert_vs_conf_not_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace,
   248                                    virtual_server_setup)
   249  
   250      def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites,
   251                                       crd_ingress_controller, virtual_server_setup):
   252          ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
   253          invalid_fields = [
   254              "upstreams.lb-method", "upstreams.fail-timeout",
   255              "upstreams.max-fails", "upstreams.connect-timeout",
   256              "upstreams.read-timeout", "upstreams.send-timeout",
   257              "upstreams.keepalive", "upstreams.max-conns",
   258              "upstreams.next-upstream",
   259              "upstreams.next-upstream-timeout", "upstreams.next-upstream-tries",
   260              "upstreams.client-max-body-size",
   261              "upstreams.buffers.number", "upstreams.buffers.size", "upstreams.buffer-size",
   262              "upstreams.buffering", "upstreams.tls"
   263          ]
   264          config_old = get_vs_nginx_template_conf(kube_apis.v1,
   265                                                  virtual_server_setup.namespace,
   266                                                  virtual_server_setup.vs_name,
   267                                                  ic_pod_name,
   268                                                  ingress_controller_prerequisites.namespace)
   269          vs_file = f"{TEST_DATA}/virtual-server-upstream-options/virtual-server-with-invalid-keys-openapi.yaml"
   270          try:
   271              patch_virtual_server_from_yaml(kube_apis.custom_objects,
   272                                             virtual_server_setup.vs_name,
   273                                             vs_file,
   274                                             virtual_server_setup.namespace)
   275          except ApiException as ex:
   276              assert ex.status == 422
   277              for item in invalid_fields:
   278                  assert item in ex.body
   279          except Exception as ex:
   280              pytest.fail(f"An unexpected exception is raised: {ex}")
   281          else:
   282              pytest.fail("Expected an exception but there was none")
   283  
   284          wait_before_test(2)
   285          config_new = get_vs_nginx_template_conf(kube_apis.v1,
   286                                                  virtual_server_setup.namespace,
   287                                                  virtual_server_setup.vs_name,
   288                                                  ic_pod_name,
   289                                                  ingress_controller_prerequisites.namespace)
   290          assert config_old == config_new, "Expected: config doesn't change"
   291  
   292  
   293  @pytest.mark.vs
   294  @pytest.mark.skip_for_nginx_oss
   295  @pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup',
   296                           [({"type": "complete", "extra_args": [f"-enable-custom-resources"]},
   297                             {"example": "virtual-server-upstream-options", "app_type": "simple"})],
   298                           indirect=True)
   299  class TestOptionsSpecificForPlus:
   300      @pytest.mark.parametrize('options, expected_strings', [
   301          ({"lb-method": "least_conn",
   302            "healthCheck": {"enable": True, "port": 8080},
   303            "slow-start": "3h",
   304            "queue": {"size": 100},
   305            "sessionCookie": {"enable": True,
   306                              "name": "TestCookie",
   307                              "path": "/some-valid/path",
   308                              "expires": "max",
   309                              "domain": "virtual-server-route.example.com", "httpOnly": True, "secure": True}},
   310           ["health_check uri=/ port=8080 interval=5s jitter=0s", "fails=1 passes=1;",
   311            "slow_start=3h", "queue 100 timeout=60s;",
   312            "sticky cookie TestCookie expires=max domain=virtual-server-route.example.com httponly secure path=/some-valid/path;"]),
   313          ({"lb-method": "least_conn",
   314            "healthCheck": {"enable": True, "path": "/health",
   315                            "interval": "15s", "jitter": "3",
   316                            "fails": 2, "passes": 2, "port": 8080,
   317                            "tls": {"enable": True}, "statusMatch": "200",
   318                            "connect-timeout": "35s", "read-timeout": "45s", "send-timeout": "55s",
   319                            "headers": [{"name": "Host", "value": "virtual-server.example.com"}]},
   320            "queue": {"size": 1000, "timeout": "66s"},
   321            "slow-start": "0s"},
   322           ["health_check uri=/health port=8080 interval=15s jitter=3", "fails=2 passes=2 match=",
   323            "proxy_pass https://vs", "status 200;",
   324            "proxy_connect_timeout 35s;", "proxy_read_timeout 45s;", "proxy_send_timeout 55s;",
   325            'proxy_set_header Host "virtual-server.example.com";',
   326            "slow_start=0s", "queue 1000 timeout=66s;"])
   327  
   328      ])
   329      def test_config_and_events(self, kube_apis, ingress_controller_prerequisites,
   330                                 crd_ingress_controller, virtual_server_setup,
   331                                 options, expected_strings):
   332          expected_strings.append(f"location @hc-vs_"
   333                                  f"{virtual_server_setup.namespace}_{virtual_server_setup.vs_name}_backend1")
   334          expected_strings.append(f"location @hc-vs_"
   335                                  f"{virtual_server_setup.namespace}_{virtual_server_setup.vs_name}_backend2")
   336          text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}"
   337          vs_event_text = f"Configuration for {text} was added or updated"
   338          events_vs = get_events(kube_apis.v1, virtual_server_setup.namespace)
   339          initial_count = assert_event_and_get_count(vs_event_text, events_vs)
   340          print(f"Case 1: option specified in VS")
   341          new_body = generate_item_with_upstream_options(
   342              f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml",
   343              options)
   344          patch_virtual_server(kube_apis.custom_objects,
   345                               virtual_server_setup.vs_name, virtual_server_setup.namespace, new_body)
   346          wait_before_test(1)
   347          ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
   348          config = get_vs_nginx_template_conf(kube_apis.v1,
   349                                              virtual_server_setup.namespace,
   350                                              virtual_server_setup.vs_name,
   351                                              ic_pod_name,
   352                                              ingress_controller_prerequisites.namespace)
   353          resp_1 = requests.get(virtual_server_setup.backend_1_url,
   354                                headers={"host": virtual_server_setup.vs_host})
   355          resp_2 = requests.get(virtual_server_setup.backend_2_url,
   356                                headers={"host": virtual_server_setup.vs_host})
   357          vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace)
   358  
   359          assert_event_count_increased(vs_event_text, initial_count, vs_events)
   360          for _ in expected_strings:
   361              assert _ in config
   362          assert_response_codes(resp_1, resp_2)
   363  
   364      @pytest.mark.parametrize('options', [{"slow-start": "0s"}])
   365      def test_slow_start_warning(self, kube_apis, ingress_controller_prerequisites,
   366                                  crd_ingress_controller, virtual_server_setup, options):
   367          ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
   368          text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}"
   369          vs_event_text = f"Configuration for {text} was added or updated ; with warning(s): Slow start will be disabled"
   370          print(f"Case 0: verify a warning")
   371          new_body = generate_item_with_upstream_options(
   372              f"{TEST_DATA}/virtual-server-upstream-options/standard/virtual-server.yaml",
   373              options)
   374          patch_virtual_server(kube_apis.custom_objects,
   375                               virtual_server_setup.vs_name, virtual_server_setup.namespace, new_body)
   376          wait_before_test(1)
   377  
   378          config = get_vs_nginx_template_conf(kube_apis.v1,
   379                                              virtual_server_setup.namespace,
   380                                              virtual_server_setup.vs_name,
   381                                              ic_pod_name,
   382                                              ingress_controller_prerequisites.namespace)
   383          vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace)
   384  
   385          assert_event(vs_event_text, vs_events)
   386          assert "slow_start" not in config
   387  
   388      def test_validation_flow(self, kube_apis, ingress_controller_prerequisites,
   389                               crd_ingress_controller, virtual_server_setup):
   390          invalid_fields = [
   391              "upstreams[0].healthCheck.path", "upstreams[0].healthCheck.interval", "upstreams[0].healthCheck.jitter",
   392              "upstreams[0].healthCheck.fails", "upstreams[0].healthCheck.passes",
   393              "upstreams[0].healthCheck.connect-timeout",
   394              "upstreams[0].healthCheck.read-timeout", "upstreams[0].healthCheck.send-timeout",
   395              "upstreams[0].healthCheck.headers[0].name", "upstreams[0].healthCheck.headers[0].value",
   396              "upstreams[0].healthCheck.statusMatch",
   397              "upstreams[0].slow-start",
   398              "upstreams[0].queue.size", "upstreams[0].queue.timeout",
   399              "upstreams[0].sessionCookie.name", "upstreams[0].sessionCookie.path",
   400              "upstreams[0].sessionCookie.expires", "upstreams[0].sessionCookie.domain",
   401              "upstreams[1].healthCheck.path", "upstreams[1].healthCheck.interval", "upstreams[1].healthCheck.jitter",
   402              "upstreams[1].healthCheck.fails", "upstreams[1].healthCheck.passes",
   403              "upstreams[1].healthCheck.connect-timeout",
   404              "upstreams[1].healthCheck.read-timeout", "upstreams[1].healthCheck.send-timeout",
   405              "upstreams[1].healthCheck.headers[0].name", "upstreams[1].healthCheck.headers[0].value",
   406              "upstreams[1].healthCheck.statusMatch",
   407              "upstreams[1].slow-start",
   408              "upstreams[1].queue.size", "upstreams[1].queue.timeout",
   409              "upstreams[1].sessionCookie.name", "upstreams[1].sessionCookie.path",
   410              "upstreams[1].sessionCookie.expires", "upstreams[1].sessionCookie.domain"
   411          ]
   412          text = f"{virtual_server_setup.namespace}/{virtual_server_setup.vs_name}"
   413          vs_event_text = f"VirtualServer {text} was rejected with error:"
   414          vs_file = f"{TEST_DATA}/virtual-server-upstream-options/plus-virtual-server-with-invalid-keys.yaml"
   415          patch_virtual_server_from_yaml(kube_apis.custom_objects,
   416                                         virtual_server_setup.vs_name,
   417                                         vs_file,
   418                                         virtual_server_setup.namespace)
   419          wait_before_test(2)
   420          ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
   421          vs_events = get_events(kube_apis.v1, virtual_server_setup.namespace)
   422  
   423          assert_event_starts_with_text_and_contains_errors(vs_event_text, vs_events, invalid_fields)
   424          assert_vs_conf_not_exists(kube_apis, ic_pod_name, ingress_controller_prerequisites.namespace,
   425                                    virtual_server_setup)
   426  
   427      def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites,
   428                                       crd_ingress_controller, virtual_server_setup):
   429          ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
   430          invalid_fields = [
   431              "upstreams.healthCheck.enable", "upstreams.healthCheck.path",
   432              "upstreams.healthCheck.interval", "upstreams.healthCheck.jitter",
   433              "upstreams.healthCheck.fails", "upstreams.healthCheck.passes",
   434              "upstreams.healthCheck.port", "upstreams.healthCheck.connect-timeout",
   435              "upstreams.healthCheck.read-timeout", "upstreams.healthCheck.send-timeout",
   436              "upstreams.healthCheck.headers.name", "upstreams.healthCheck.headers.value",
   437              "upstreams.healthCheck.statusMatch",
   438              "upstreams.slow-start",
   439              "upstreams.queue.size", "upstreams.queue.timeout",
   440              "upstreams.sessionCookie.name", "upstreams.sessionCookie.path",
   441              "upstreams.sessionCookie.expires", "upstreams.sessionCookie.domain",
   442              "upstreams.sessionCookie.httpOnly", "upstreams.sessionCookie.secure"
   443          ]
   444          config_old = get_vs_nginx_template_conf(kube_apis.v1,
   445                                                  virtual_server_setup.namespace,
   446                                                  virtual_server_setup.vs_name,
   447                                                  ic_pod_name,
   448                                                  ingress_controller_prerequisites.namespace)
   449          vs_file = f"{TEST_DATA}/virtual-server-upstream-options/plus-virtual-server-with-invalid-keys-openapi.yaml"
   450          try:
   451              patch_virtual_server_from_yaml(kube_apis.custom_objects,
   452                                             virtual_server_setup.vs_name,
   453                                             vs_file,
   454                                             virtual_server_setup.namespace)
   455          except ApiException as ex:
   456              assert ex.status == 422
   457              for item in invalid_fields:
   458                  assert item in ex.body
   459          except Exception as ex:
   460              pytest.fail(f"An unexpected exception is raised: {ex}")
   461          else:
   462              pytest.fail("Expected an exception but there was none")
   463  
   464          wait_before_test(2)
   465          config_new = get_vs_nginx_template_conf(kube_apis.v1,
   466                                                  virtual_server_setup.namespace,
   467                                                  virtual_server_setup.vs_name,
   468                                                  ic_pod_name,
   469                                                  ingress_controller_prerequisites.namespace)
   470          assert config_old == config_new, "Expected: config doesn't change"