github.com/nginxinc/kubernetes-ingress@v1.12.5/tests/suite/test_v_s_route_upstream_options.py (about) 1 import pytest 2 import requests 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, wait_for_event_count_increases 8 from suite.custom_resources_utils import get_vs_nginx_template_conf, patch_v_s_route_from_yaml, patch_v_s_route, \ 9 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.parametrize('crd_ingress_controller, v_s_route_setup', 14 [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, 15 {"example": "virtual-server-route-upstream-options"})], 16 indirect=True) 17 @pytest.mark.vsr 18 class TestVSRouteUpstreamOptions: 19 def test_nginx_config_upstreams_defaults(self, kube_apis, ingress_controller_prerequisites, 20 crd_ingress_controller, v_s_route_setup, v_s_route_app_setup): 21 print("Case 1: no ConfigMap keys, 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 v_s_route_setup.namespace, 25 v_s_route_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": 1024, "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=1024;", 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_r_only(self, kube_apis, 79 ingress_controller_prerequisites, 80 crd_ingress_controller, 81 v_s_route_setup, v_s_route_app_setup, 82 options, expected_strings): 83 req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" 84 text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" 85 text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" 86 vsr_s_event_text = f"Configuration for {text_s} was added or updated" 87 vsr_m_event_text = f"Configuration for {text_m} was added or updated" 88 events_ns_m = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) 89 events_ns_s = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) 90 initial_count_vsr_m = assert_event_and_get_count(vsr_m_event_text, events_ns_m) 91 initial_count_vsr_s = assert_event_and_get_count(vsr_s_event_text, events_ns_s) 92 print(f"Case 2: no key in ConfigMap, option specified in VSR") 93 new_body_m = generate_item_with_upstream_options( 94 f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", 95 options) 96 new_body_s = generate_item_with_upstream_options( 97 f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", 98 options) 99 patch_v_s_route(kube_apis.custom_objects, 100 v_s_route_setup.route_m.name, v_s_route_setup.route_m.namespace, new_body_m) 101 patch_v_s_route(kube_apis.custom_objects, 102 v_s_route_setup.route_s.name, v_s_route_setup.route_s.namespace, new_body_s) 103 wait_before_test(1) 104 ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) 105 config = get_vs_nginx_template_conf(kube_apis.v1, 106 v_s_route_setup.namespace, 107 v_s_route_setup.vs_name, 108 ic_pod_name, 109 ingress_controller_prerequisites.namespace) 110 resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", 111 headers={"host": v_s_route_setup.vs_host}) 112 resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", 113 headers={"host": v_s_route_setup.vs_host}) 114 115 wait_for_event_count_increases(kube_apis, vsr_s_event_text, 116 initial_count_vsr_s, v_s_route_setup.route_s.namespace) 117 wait_for_event_count_increases(kube_apis, vsr_m_event_text, 118 initial_count_vsr_m, v_s_route_setup.route_m.namespace) 119 120 for _ in expected_strings: 121 assert _ in config 122 assert_response_codes(resp_1, resp_2) 123 124 @pytest.mark.parametrize('config_map_file, expected_strings, unexpected_strings', [ 125 (f"{TEST_DATA}/virtual-server-route-upstream-options/configmap-with-keys.yaml", 126 ["max_fails=3 ", "fail_timeout=33s ", "max_conns=0;", 127 "proxy_connect_timeout 44s;", "proxy_read_timeout 22s;", "proxy_send_timeout 55s;", 128 "keepalive 1024;", 'set $default_connection_header "";', 129 "client_max_body_size 3m;", 130 "proxy_buffering off;", "proxy_buffer_size 1k;", "proxy_buffers 8 1k;"], 131 ["ip_hash;", "least_conn;", "random ", "hash", "least_time ", 132 "max_fails=1 ", "fail_timeout=10s ", "max_conns=1000;", 133 "proxy_connect_timeout 60s;", "proxy_read_timeout 60s;", "proxy_send_timeout 60s;", 134 "client_max_body_size 1m;", 135 "slow_start=0s", 136 "proxy_buffering on;"]), 137 ]) 138 def test_when_option_in_config_map_only(self, kube_apis, 139 ingress_controller_prerequisites, 140 crd_ingress_controller, 141 v_s_route_setup, v_s_route_app_setup, restore_configmap, 142 config_map_file, expected_strings, unexpected_strings): 143 req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" 144 text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" 145 text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" 146 vsr_s_event_text = f"Configuration for {text_s} was added or updated" 147 vsr_m_event_text = f"Configuration for {text_m} was added or updated" 148 print(f"Case 3: key specified in ConfigMap, no option in VS") 149 patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_m.name, 150 f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", 151 v_s_route_setup.route_m.namespace) 152 patch_v_s_route_from_yaml(kube_apis.custom_objects, v_s_route_setup.route_s.name, 153 f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", 154 v_s_route_setup.route_s.namespace) 155 config_map_name = ingress_controller_prerequisites.config_map["metadata"]["name"] 156 replace_configmap_from_yaml(kube_apis.v1, config_map_name, 157 ingress_controller_prerequisites.namespace, 158 config_map_file) 159 wait_before_test() 160 ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) 161 config = get_vs_nginx_template_conf(kube_apis.v1, 162 v_s_route_setup.namespace, 163 v_s_route_setup.vs_name, 164 ic_pod_name, 165 ingress_controller_prerequisites.namespace) 166 resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", 167 headers={"host": v_s_route_setup.vs_host}) 168 resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", 169 headers={"host": v_s_route_setup.vs_host}) 170 vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) 171 vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) 172 173 assert_event(vsr_m_event_text, vsr_m_events) 174 assert_event(vsr_s_event_text, vsr_s_events) 175 for _ in expected_strings: 176 assert _ in config 177 for _ in unexpected_strings: 178 assert _ not in config 179 assert_response_codes(resp_1, resp_2) 180 181 @pytest.mark.parametrize('options, expected_strings, unexpected_strings', [ 182 ({"lb-method": "least_conn", "max-fails": 12, 183 "fail-timeout": "1m", "connect-timeout": "1m", "read-timeout": "77s", "send-timeout": "23s", 184 "keepalive": 48, "client-max-body-size": "0", 185 "buffering": True, "buffer-size": "2k", "buffers": {"number": 4, "size": "2k"}}, 186 ["least_conn;", "max_fails=12 ", 187 "fail_timeout=1m ", "max_conns=0;", 188 "proxy_connect_timeout 1m;", "proxy_read_timeout 77s;", "proxy_send_timeout 23s;", 189 "keepalive 48;", 'set $default_connection_header "";', 190 "client_max_body_size 0;", 191 "proxy_buffering on;", "proxy_buffer_size 2k;", "proxy_buffers 4 2k;"], 192 ["ip_hash;", "random ", "hash", "least_time ", "max_fails=1 ", "fail_timeout=10s ", 193 "proxy_connect_timeout 44s;", "proxy_read_timeout 22s;", "proxy_send_timeout 55s;", 194 "keepalive 1024;", 195 "client_max_body_size 3m;", "client_max_body_size 1m;", 196 "proxy_buffering off;", "proxy_buffer_size 1k;", "proxy_buffers 8 1k;"]) 197 ]) 198 def test_v_s_r_overrides_config_map(self, kube_apis, 199 ingress_controller_prerequisites, 200 crd_ingress_controller, v_s_route_setup, v_s_route_app_setup, restore_configmap, 201 options, expected_strings, unexpected_strings): 202 req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" 203 text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" 204 text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" 205 vsr_s_event_text = f"Configuration for {text_s} was added or updated" 206 vsr_m_event_text = f"Configuration for {text_m} was added or updated" 207 events_ns_m = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) 208 events_ns_s = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) 209 initial_count_vsr_m = assert_event_and_get_count(vsr_m_event_text, events_ns_m) 210 initial_count_vsr_s = assert_event_and_get_count(vsr_s_event_text, events_ns_s) 211 print(f"Case 4: key specified in ConfigMap, option specified in VS") 212 new_body_m = generate_item_with_upstream_options( 213 f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", 214 options) 215 new_body_s = generate_item_with_upstream_options( 216 f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", 217 options) 218 patch_v_s_route(kube_apis.custom_objects, 219 v_s_route_setup.route_m.name, v_s_route_setup.route_m.namespace, new_body_m) 220 patch_v_s_route(kube_apis.custom_objects, 221 v_s_route_setup.route_s.name, v_s_route_setup.route_s.namespace, new_body_s) 222 config_map_name = ingress_controller_prerequisites.config_map["metadata"]["name"] 223 replace_configmap_from_yaml(kube_apis.v1, config_map_name, 224 ingress_controller_prerequisites.namespace, 225 f"{TEST_DATA}/virtual-server-route-upstream-options/configmap-with-keys.yaml") 226 wait_before_test() 227 ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) 228 config = get_vs_nginx_template_conf(kube_apis.v1, 229 v_s_route_setup.namespace, 230 v_s_route_setup.vs_name, 231 ic_pod_name, 232 ingress_controller_prerequisites.namespace) 233 resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", 234 headers={"host": v_s_route_setup.vs_host}) 235 resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", 236 headers={"host": v_s_route_setup.vs_host}) 237 vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) 238 vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) 239 240 assert_event_count_increased(vsr_m_event_text, initial_count_vsr_m, vsr_m_events) 241 assert_event_count_increased(vsr_s_event_text, initial_count_vsr_s, vsr_s_events) 242 for _ in expected_strings: 243 assert _ in config 244 for _ in unexpected_strings: 245 assert _ not in config 246 assert_response_codes(resp_1, resp_2) 247 248 249 @pytest.mark.vsr 250 @pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', 251 [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, 252 {"example": "virtual-server-route-upstream-options"})], 253 indirect=True) 254 class TestVSRouteUpstreamOptionsValidation: 255 def test_event_message_and_config(self, kube_apis, ingress_controller_prerequisites, 256 crd_ingress_controller, v_s_route_setup): 257 invalid_fields_s = [ 258 "upstreams[0].lb-method", "upstreams[0].fail-timeout", 259 "upstreams[0].max-fails", "upstreams[0].connect-timeout", 260 "upstreams[0].read-timeout", "upstreams[0].send-timeout", 261 "upstreams[0].keepalive", "upstreams[0].max-conns", 262 "upstreams[0].next-upstream", 263 "upstreams[0].next-upstream-timeout", "upstreams[0].next-upstream-tries", 264 "upstreams[0].client-max-body-size", 265 "upstreams[0].buffers.number", "upstreams[0].buffers.size", "upstreams[0].buffer-size" 266 ] 267 invalid_fields_m = [ 268 "upstreams[0].lb-method", "upstreams[0].fail-timeout", 269 "upstreams[0].max-fails", "upstreams[0].connect-timeout", 270 "upstreams[0].read-timeout", "upstreams[0].send-timeout", 271 "upstreams[0].keepalive", "upstreams[0].max-conns", 272 "upstreams[0].next-upstream", 273 "upstreams[0].next-upstream-timeout", "upstreams[0].next-upstream-tries", 274 "upstreams[0].client-max-body-size", 275 "upstreams[0].buffers.number", "upstreams[0].buffers.size", "upstreams[0].buffer-size", 276 "upstreams[1].lb-method", "upstreams[1].fail-timeout", 277 "upstreams[1].max-fails", "upstreams[1].connect-timeout", 278 "upstreams[1].read-timeout", "upstreams[1].send-timeout", 279 "upstreams[1].keepalive", "upstreams[1].max-conns", 280 "upstreams[1].next-upstream", 281 "upstreams[1].next-upstream-timeout", "upstreams[1].next-upstream-tries", 282 "upstreams[1].client-max-body-size", 283 "upstreams[1].buffers.number", "upstreams[1].buffers.size", "upstreams[1].buffer-size" 284 ] 285 text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" 286 text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" 287 vsr_s_event_text = f"VirtualServerRoute {text_s} was rejected with error:" 288 vsr_m_event_text = f"VirtualServerRoute {text_m} was rejected with error:" 289 patch_v_s_route_from_yaml(kube_apis.custom_objects, 290 v_s_route_setup.route_s.name, 291 f"{TEST_DATA}/virtual-server-route-upstream-options/route-single-invalid-keys.yaml", 292 v_s_route_setup.route_s.namespace) 293 patch_v_s_route_from_yaml(kube_apis.custom_objects, 294 v_s_route_setup.route_m.name, 295 f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple-invalid-keys.yaml", 296 v_s_route_setup.route_m.namespace) 297 wait_before_test(2) 298 ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) 299 config = get_vs_nginx_template_conf(kube_apis.v1, 300 v_s_route_setup.namespace, 301 v_s_route_setup.vs_name, 302 ic_pod_name, 303 ingress_controller_prerequisites.namespace) 304 vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) 305 vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) 306 307 assert_event_starts_with_text_and_contains_errors(vsr_s_event_text, vsr_s_events, invalid_fields_s) 308 assert_event_starts_with_text_and_contains_errors(vsr_m_event_text, vsr_m_events, invalid_fields_m) 309 assert "upstream" not in config 310 311 def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, 312 crd_ingress_controller, v_s_route_setup): 313 ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) 314 invalid_fields = [ 315 "upstreams.lb-method", "upstreams.fail-timeout", 316 "upstreams.max-fails", "upstreams.connect-timeout", 317 "upstreams.read-timeout", "upstreams.send-timeout", 318 "upstreams.keepalive", "upstreams.max-conns", 319 "upstreams.next-upstream", 320 "upstreams.next-upstream-timeout", "upstreams.next-upstream-tries", 321 "upstreams.client-max-body-size", 322 "upstreams.buffers.number", "upstreams.buffers.size", "upstreams.buffer-size", 323 "upstreams.buffering", "upstreams.tls" 324 ] 325 config_old = get_vs_nginx_template_conf(kube_apis.v1, 326 v_s_route_setup.namespace, 327 v_s_route_setup.vs_name, 328 ic_pod_name, 329 ingress_controller_prerequisites.namespace) 330 source_yaml = f"{TEST_DATA}/virtual-server-route-upstream-options/route-single-invalid-keys-openapi.yaml" 331 try: 332 patch_v_s_route_from_yaml(kube_apis.custom_objects, 333 v_s_route_setup.route_s.name, 334 source_yaml, 335 v_s_route_setup.route_s.namespace) 336 except ApiException as ex: 337 assert ex.status == 422 338 for item in invalid_fields: 339 assert item in ex.body 340 except Exception as ex: 341 pytest.fail(f"An unexpected exception is raised: {ex}") 342 else: 343 pytest.fail("Expected an exception but there was none") 344 345 wait_before_test(2) 346 config_new = get_vs_nginx_template_conf(kube_apis.v1, 347 v_s_route_setup.namespace, 348 v_s_route_setup.vs_name, 349 ic_pod_name, 350 ingress_controller_prerequisites.namespace) 351 assert config_old == config_new, "Expected: config doesn't change" 352 353 354 @pytest.mark.vsr 355 @pytest.mark.skip_for_nginx_oss 356 @pytest.mark.parametrize('crd_ingress_controller, v_s_route_setup', 357 [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, 358 {"example": "virtual-server-route-upstream-options"})], 359 indirect=True) 360 class TestOptionsSpecificForPlus: 361 @pytest.mark.parametrize('options, expected_strings', [ 362 ({"lb-method": "least_conn", 363 "healthCheck": {"enable": True, "port": 8080}, 364 "slow-start": "3h", 365 "queue": {"size": 100}, 366 "sessionCookie": {"enable": True, 367 "name": "TestCookie", 368 "path": "/some-valid/path", 369 "expires": "max", 370 "domain": "virtual-server-route.example.com", "httpOnly": True, "secure": True}}, 371 ["health_check uri=/ port=8080 interval=5s jitter=0s", "fails=1 passes=1;", 372 "slow_start=3h", "queue 100 timeout=60s;", 373 "sticky cookie TestCookie expires=max domain=virtual-server-route.example.com httponly secure path=/some-valid/path;"]), 374 ({"lb-method": "least_conn", 375 "healthCheck": {"enable": True, "path": "/health", 376 "interval": "15s", "jitter": "3", 377 "fails": 2, "passes": 2, "port": 8080, 378 "tls": {"enable": True}, "statusMatch": "200", 379 "connect-timeout": "35s", "read-timeout": "45s", "send-timeout": "55s", 380 "headers": [{"name": "Host", "value": "virtual-server.example.com"}]}, 381 "slow-start": "0s", 382 "queue": {"size": 1000, "timeout": "66s"}}, 383 ["health_check uri=/health port=8080 interval=15s jitter=3", "fails=2 passes=2 match=", 384 "proxy_pass https://vs", "status 200;", 385 "proxy_connect_timeout 35s;", "proxy_read_timeout 45s;", "proxy_send_timeout 55s;", 386 'proxy_set_header Host "virtual-server.example.com";', 387 "slow_start=0s", "queue 1000 timeout=66s;"]) 388 ]) 389 def test_config_and_events(self, kube_apis, 390 ingress_controller_prerequisites, 391 crd_ingress_controller, 392 v_s_route_setup, v_s_route_app_setup, 393 options, expected_strings): 394 expected_strings.append(f"location @hc-vs_{v_s_route_setup.namespace}_{v_s_route_setup.vs_name}" 395 f"_vsr_{v_s_route_setup.route_m.namespace}_{v_s_route_setup.route_m.name}") 396 expected_strings.append(f"location @hc-vs_{v_s_route_setup.namespace}_{v_s_route_setup.vs_name}" 397 f"_vsr_{v_s_route_setup.route_s.namespace}_{v_s_route_setup.route_s.name}") 398 req_url = f"http://{v_s_route_setup.public_endpoint.public_ip}:{v_s_route_setup.public_endpoint.port}" 399 text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" 400 text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" 401 vsr_s_event_text = f"Configuration for {text_s} was added or updated" 402 vsr_m_event_text = f"Configuration for {text_m} was added or updated" 403 events_ns_m = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) 404 events_ns_s = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) 405 initial_count_vsr_m = assert_event_and_get_count(vsr_m_event_text, events_ns_m) 406 initial_count_vsr_s = assert_event_and_get_count(vsr_s_event_text, events_ns_s) 407 print(f"Case 2: no key in ConfigMap, option specified in VSR") 408 new_body_m = generate_item_with_upstream_options( 409 f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", 410 options) 411 new_body_s = generate_item_with_upstream_options( 412 f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", 413 options) 414 patch_v_s_route(kube_apis.custom_objects, 415 v_s_route_setup.route_m.name, v_s_route_setup.route_m.namespace, new_body_m) 416 patch_v_s_route(kube_apis.custom_objects, 417 v_s_route_setup.route_s.name, v_s_route_setup.route_s.namespace, new_body_s) 418 wait_before_test(1) 419 ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) 420 config = get_vs_nginx_template_conf(kube_apis.v1, 421 v_s_route_setup.namespace, 422 v_s_route_setup.vs_name, 423 ic_pod_name, 424 ingress_controller_prerequisites.namespace) 425 resp_1 = requests.get(f"{req_url}{v_s_route_setup.route_m.paths[0]}", 426 headers={"host": v_s_route_setup.vs_host}) 427 resp_2 = requests.get(f"{req_url}{v_s_route_setup.route_s.paths[0]}", 428 headers={"host": v_s_route_setup.vs_host}) 429 vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) 430 vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) 431 432 assert_event_count_increased(vsr_m_event_text, initial_count_vsr_m, vsr_m_events) 433 assert_event_count_increased(vsr_s_event_text, initial_count_vsr_s, vsr_s_events) 434 for _ in expected_strings: 435 assert _ in config 436 assert_response_codes(resp_1, resp_2) 437 438 @pytest.mark.parametrize('options', [{"slow-start": "0s"}]) 439 def test_slow_start_warning(self, kube_apis, 440 ingress_controller_prerequisites, crd_ingress_controller, 441 v_s_route_setup, v_s_route_app_setup, options): 442 ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) 443 text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" 444 text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" 445 vsr_s_event_text = f"Configuration for {text_s} was added or updated with warning(s): " \ 446 f"Slow start will be disabled" 447 vsr_m_event_text = f"Configuration for {text_m} was added or updated with warning(s): " \ 448 f"Slow start will be disabled" 449 print(f"Case 2: no key in ConfigMap, option specified in VSR") 450 new_body_m = generate_item_with_upstream_options( 451 f"{TEST_DATA}/virtual-server-route-upstream-options/route-multiple.yaml", 452 options) 453 new_body_s = generate_item_with_upstream_options( 454 f"{TEST_DATA}/virtual-server-route-upstream-options/route-single.yaml", 455 options) 456 patch_v_s_route(kube_apis.custom_objects, 457 v_s_route_setup.route_m.name, v_s_route_setup.route_m.namespace, new_body_m) 458 patch_v_s_route(kube_apis.custom_objects, 459 v_s_route_setup.route_s.name, v_s_route_setup.route_s.namespace, new_body_s) 460 wait_before_test(1) 461 462 config = get_vs_nginx_template_conf(kube_apis.v1, 463 v_s_route_setup.namespace, 464 v_s_route_setup.vs_name, 465 ic_pod_name, 466 ingress_controller_prerequisites.namespace) 467 vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) 468 vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) 469 470 assert_event(vsr_s_event_text, vsr_s_events) 471 assert_event(vsr_m_event_text, vsr_m_events) 472 assert "slow_start" not in config 473 474 def test_validation_flow(self, kube_apis, ingress_controller_prerequisites, 475 crd_ingress_controller, v_s_route_setup): 476 invalid_fields_s = [ 477 "upstreams[0].healthCheck.path", "upstreams[0].healthCheck.interval", "upstreams[0].healthCheck.jitter", 478 "upstreams[0].healthCheck.fails", "upstreams[0].healthCheck.passes", 479 "upstreams[0].healthCheck.connect-timeout", 480 "upstreams[0].healthCheck.read-timeout", "upstreams[0].healthCheck.send-timeout", 481 "upstreams[0].healthCheck.headers[0].name", "upstreams[0].healthCheck.headers[0].value", 482 "upstreams[0].healthCheck.statusMatch", 483 "upstreams[0].slow-start", 484 "upstreams[0].queue.size", "upstreams[0].queue.timeout", 485 "upstreams[0].sessionCookie.name", "upstreams[0].sessionCookie.path", 486 "upstreams[0].sessionCookie.expires", "upstreams[0].sessionCookie.domain" 487 ] 488 invalid_fields_m = [ 489 "upstreams[0].healthCheck.path", "upstreams[0].healthCheck.interval", "upstreams[0].healthCheck.jitter", 490 "upstreams[0].healthCheck.fails", "upstreams[0].healthCheck.passes", 491 "upstreams[0].healthCheck.connect-timeout", 492 "upstreams[0].healthCheck.read-timeout", "upstreams[0].healthCheck.send-timeout", 493 "upstreams[0].healthCheck.headers[0].name", "upstreams[0].healthCheck.headers[0].value", 494 "upstreams[0].healthCheck.statusMatch", 495 "upstreams[0].slow-start", 496 "upstreams[0].queue.size", "upstreams[0].queue.timeout", 497 "upstreams[0].sessionCookie.name", "upstreams[0].sessionCookie.path", 498 "upstreams[0].sessionCookie.expires", "upstreams[0].sessionCookie.domain", 499 "upstreams[1].healthCheck.path", "upstreams[1].healthCheck.interval", "upstreams[1].healthCheck.jitter", 500 "upstreams[1].healthCheck.fails", "upstreams[1].healthCheck.passes", 501 "upstreams[1].healthCheck.connect-timeout", 502 "upstreams[1].healthCheck.read-timeout", "upstreams[1].healthCheck.send-timeout", 503 "upstreams[1].healthCheck.headers[0].name", "upstreams[0].healthCheck.headers[0].value", 504 "upstreams[1].healthCheck.statusMatch", 505 "upstreams[1].slow-start", 506 "upstreams[1].queue.size", "upstreams[1].queue.timeout", 507 "upstreams[1].sessionCookie.name", "upstreams[1].sessionCookie.path", 508 "upstreams[1].sessionCookie.expires", "upstreams[1].sessionCookie.domain" 509 ] 510 text_s = f"{v_s_route_setup.route_s.namespace}/{v_s_route_setup.route_s.name}" 511 text_m = f"{v_s_route_setup.route_m.namespace}/{v_s_route_setup.route_m.name}" 512 vsr_s_event_text = f"VirtualServerRoute {text_s} was rejected with error:" 513 vsr_m_event_text = f"VirtualServerRoute {text_m} was rejected with error:" 514 patch_v_s_route_from_yaml(kube_apis.custom_objects, 515 v_s_route_setup.route_s.name, 516 f"{TEST_DATA}/virtual-server-route-upstream-options/plus-route-s-invalid-keys.yaml", 517 v_s_route_setup.route_s.namespace) 518 patch_v_s_route_from_yaml(kube_apis.custom_objects, 519 v_s_route_setup.route_m.name, 520 f"{TEST_DATA}/virtual-server-route-upstream-options/plus-route-m-invalid-keys.yaml", 521 v_s_route_setup.route_m.namespace) 522 wait_before_test(2) 523 ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) 524 config = get_vs_nginx_template_conf(kube_apis.v1, 525 v_s_route_setup.namespace, 526 v_s_route_setup.vs_name, 527 ic_pod_name, 528 ingress_controller_prerequisites.namespace) 529 vsr_s_events = get_events(kube_apis.v1, v_s_route_setup.route_s.namespace) 530 vsr_m_events = get_events(kube_apis.v1, v_s_route_setup.route_m.namespace) 531 532 assert_event_starts_with_text_and_contains_errors(vsr_s_event_text, vsr_s_events, invalid_fields_s) 533 assert_event_starts_with_text_and_contains_errors(vsr_m_event_text, vsr_m_events, invalid_fields_m) 534 assert "upstream" not in config 535 536 def test_openapi_validation_flow(self, kube_apis, ingress_controller_prerequisites, 537 crd_ingress_controller, v_s_route_setup): 538 ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) 539 invalid_fields = [ 540 "upstreams.healthCheck.enable", "upstreams.healthCheck.path", 541 "upstreams.healthCheck.interval", "upstreams.healthCheck.jitter", 542 "upstreams.healthCheck.fails", "upstreams.healthCheck.passes", 543 "upstreams.healthCheck.port", "upstreams.healthCheck.connect-timeout", 544 "upstreams.healthCheck.read-timeout", "upstreams.healthCheck.send-timeout", 545 "upstreams.healthCheck.headers.name", "upstreams.healthCheck.headers.value", 546 "upstreams.healthCheck.statusMatch", 547 "upstreams.slow-start", 548 "upstreams.queue.size", "upstreams.queue.timeout", 549 "upstreams.sessionCookie.name", "upstreams.sessionCookie.path", 550 "upstreams.sessionCookie.expires", "upstreams.sessionCookie.domain", 551 "upstreams.sessionCookie.httpOnly", "upstreams.sessionCookie.secure" 552 ] 553 config_old = get_vs_nginx_template_conf(kube_apis.v1, 554 v_s_route_setup.namespace, 555 v_s_route_setup.vs_name, 556 ic_pod_name, 557 ingress_controller_prerequisites.namespace) 558 source_yaml = f"{TEST_DATA}/virtual-server-route-upstream-options/plus-route-s-invalid-keys-openapi.yaml" 559 try: 560 patch_v_s_route_from_yaml(kube_apis.custom_objects, 561 v_s_route_setup.route_s.name, 562 source_yaml, 563 v_s_route_setup.route_s.namespace) 564 except ApiException as ex: 565 assert ex.status == 422 566 for item in invalid_fields: 567 assert item in ex.body 568 except Exception as ex: 569 pytest.fail(f"An unexpected exception is raised: {ex}") 570 else: 571 pytest.fail("Expected an exception but there was none") 572 573 wait_before_test(2) 574 config_new = get_vs_nginx_template_conf(kube_apis.v1, 575 v_s_route_setup.namespace, 576 v_s_route_setup.vs_name, 577 ic_pod_name, 578 ingress_controller_prerequisites.namespace) 579 assert config_old == config_new, "Expected: config doesn't change"