github.com/nginxinc/kubernetes-ingress@v1.12.5/tests/suite/fixtures.py (about) 1 """Describe project shared pytest fixtures.""" 2 3 import time 4 import os, re 5 import pytest 6 import yaml 7 import subprocess 8 9 from kubernetes import config, client 10 from kubernetes.client import ( 11 CoreV1Api, 12 ExtensionsV1beta1Api, 13 RbacAuthorizationV1Api, 14 CustomObjectsApi, 15 ApiextensionsV1Api, 16 AppsV1Api, 17 ) 18 from kubernetes.client.rest import ApiException 19 20 from suite.custom_resources_utils import ( 21 create_virtual_server_from_yaml, 22 delete_virtual_server, 23 create_v_s_route_from_yaml, 24 delete_v_s_route, 25 create_crd_from_yaml, 26 delete_crd, 27 create_ts_from_yaml, 28 create_gc_from_yaml, 29 delete_ts, 30 delete_gc, 31 ) 32 from suite.kube_config_utils import ensure_context_in_config, get_current_context_name 33 from suite.resources_utils import ( 34 create_namespace_with_name_from_yaml, 35 delete_namespace, 36 create_ns_and_sa_from_yaml, 37 patch_rbac, 38 create_example_app, 39 wait_until_all_pods_are_ready, 40 delete_common_app, 41 ensure_connection_to_public_endpoint, 42 create_service_with_name, 43 create_deployment_with_name, 44 delete_deployment, 45 delete_service, 46 replace_configmap_from_yaml, 47 delete_testing_namespaces, 48 get_first_pod_name, 49 ) 50 from suite.resources_utils import ( 51 create_ingress_controller, 52 delete_ingress_controller, 53 configure_rbac, 54 cleanup_rbac, 55 ) 56 from suite.resources_utils import ( 57 create_service_from_yaml, 58 get_service_node_ports, 59 wait_for_public_ip, 60 ) 61 from suite.resources_utils import ( 62 create_configmap_from_yaml, 63 create_secret_from_yaml, 64 configure_rbac_with_ap, 65 create_items_from_yaml, 66 delete_items_from_yaml, 67 ) 68 from suite.yaml_utils import ( 69 get_first_host_from_yaml, 70 get_paths_from_vs_yaml, 71 get_paths_from_vsr_yaml, 72 get_route_namespace_from_vs_yaml, 73 get_name_from_yaml, 74 ) 75 76 from settings import ( 77 ALLOWED_SERVICE_TYPES, 78 ALLOWED_IC_TYPES, 79 DEPLOYMENTS, 80 TEST_DATA, 81 ALLOWED_DEPLOYMENT_TYPES, 82 ) 83 84 85 class KubeApis: 86 """ 87 Encapsulate all the used kubernetes-client APIs. 88 89 Attributes: 90 v1: CoreV1Api 91 extensions_v1_beta1: ExtensionsV1beta1Api 92 rbac_v1: RbacAuthorizationV1Api 93 api_extensions_v1: ApiextensionsV1Api 94 custom_objects: CustomObjectsApi 95 """ 96 97 def __init__( 98 self, 99 v1: CoreV1Api, 100 extensions_v1_beta1: ExtensionsV1beta1Api, 101 apps_v1_api: AppsV1Api, 102 rbac_v1: RbacAuthorizationV1Api, 103 api_extensions_v1: ApiextensionsV1Api, 104 custom_objects: CustomObjectsApi, 105 ): 106 self.v1 = v1 107 self.extensions_v1_beta1 = extensions_v1_beta1 108 self.apps_v1_api = apps_v1_api 109 self.rbac_v1 = rbac_v1 110 self.api_extensions_v1 = api_extensions_v1 111 self.custom_objects = custom_objects 112 113 114 class PublicEndpoint: 115 """ 116 Encapsulate the Public Endpoint info. 117 118 Attributes: 119 public_ip (str): 120 port (int): 121 port_ssl (int): 122 """ 123 124 def __init__(self, public_ip, port=80, port_ssl=443, api_port=8080, metrics_port=9113, tcp_server_port=3333, udp_server_port=3334): 125 self.public_ip = public_ip 126 self.port = port 127 self.port_ssl = port_ssl 128 self.api_port = api_port 129 self.metrics_port = metrics_port 130 self.tcp_server_port = tcp_server_port 131 self.udp_server_port = udp_server_port 132 133 134 class IngressControllerPrerequisites: 135 """ 136 Encapsulate shared items. 137 138 Attributes: 139 namespace (str): namespace name 140 config_map (str): config_map name 141 minorVer (int): k8s minor version 142 """ 143 144 def __init__(self, config_map, namespace, minorVer): 145 self.namespace = namespace 146 self.config_map = config_map 147 self.minorVer = minorVer 148 149 150 @pytest.fixture(autouse=True) 151 def print_name() -> None: 152 """Print out a current test name.""" 153 test_name = f"{os.environ.get('PYTEST_CURRENT_TEST').split(':')[2]} :: {os.environ.get('PYTEST_CURRENT_TEST').split(':')[4].split(' ')[0]}" 154 print(f"\n============================= {test_name} =============================") 155 156 157 @pytest.fixture(scope="class") 158 def test_namespace(kube_apis) -> str: 159 """ 160 Create a test namespace. 161 162 :param kube_apis: client apis 163 :return: str 164 """ 165 timestamp = round(time.time() * 1000) 166 print("------------------------- Create Test Namespace -----------------------------------") 167 namespace = create_namespace_with_name_from_yaml( 168 kube_apis.v1, f"test-namespace-{str(timestamp)}", f"{TEST_DATA}/common/ns.yaml" 169 ) 170 return namespace 171 172 173 @pytest.fixture(scope="session", autouse=True) 174 def delete_test_namespaces(kube_apis, request) -> None: 175 """ 176 Delete all the testing namespaces. 177 178 Testing namespaces are the ones starting with "test-namespace-" 179 180 :param kube_apis: client apis 181 :param request: pytest fixture 182 :return: str 183 """ 184 185 def fin(): 186 print( 187 "------------------------- Delete All Test Namespaces -----------------------------------" 188 ) 189 delete_testing_namespaces(kube_apis.v1) 190 191 request.addfinalizer(fin) 192 193 194 @pytest.fixture(scope="class") 195 def ingress_controller(cli_arguments, kube_apis, ingress_controller_prerequisites, request) -> str: 196 """ 197 Create Ingress Controller according to the context. 198 199 :param cli_arguments: context 200 :param kube_apis: client apis 201 :param ingress_controller_prerequisites 202 :param request: pytest fixture 203 :return: IC name 204 """ 205 namespace = ingress_controller_prerequisites.namespace 206 name = "nginx-ingress" 207 print("------------------------- Create IC without CRDs -----------------------------------") 208 try: 209 extra_args = request.param.get("extra_args", None) 210 extra_args.append("-enable-custom-resources=false") 211 except AttributeError: 212 print("IC will start with CRDs disabled and without any additional cli-arguments") 213 extra_args = ["-enable-custom-resources=false"] 214 try: 215 name = create_ingress_controller( 216 kube_apis.v1, kube_apis.apps_v1_api, cli_arguments, namespace, extra_args 217 ) 218 except ApiException as ex: 219 # Finalizer doesn't start if fixture creation was incomplete, ensure clean up here 220 print(f"Failed to complete IC fixture: {ex}\nClean up the cluster as much as possible.") 221 delete_ingress_controller( 222 kube_apis.apps_v1_api, name, cli_arguments["deployment-type"], namespace 223 ) 224 225 def fin(): 226 print("Delete IC:") 227 delete_ingress_controller( 228 kube_apis.apps_v1_api, name, cli_arguments["deployment-type"], namespace 229 ) 230 231 request.addfinalizer(fin) 232 233 return name 234 235 236 @pytest.fixture(scope="session") 237 def ingress_controller_endpoint( 238 cli_arguments, kube_apis, ingress_controller_prerequisites 239 ) -> PublicEndpoint: 240 """ 241 Create an entry point for the IC. 242 243 :param cli_arguments: tests context 244 :param kube_apis: client apis 245 :param ingress_controller_prerequisites: common cluster context 246 :return: PublicEndpoint 247 """ 248 print("------------------------- Create Public Endpoint -----------------------------------") 249 namespace = ingress_controller_prerequisites.namespace 250 if cli_arguments["service"] == "nodeport": 251 public_ip = cli_arguments["node-ip"] 252 print(f"The Public IP: {public_ip}") 253 service_name = create_service_from_yaml( 254 kube_apis.v1, 255 namespace, 256 f"{TEST_DATA}/common/service/nodeport-with-additional-ports.yaml", 257 ) 258 port, port_ssl, api_port, metrics_port, tcp_server_port, udp_server_port = get_service_node_ports( 259 kube_apis.v1, service_name, namespace 260 ) 261 return PublicEndpoint(public_ip, port, port_ssl, api_port, metrics_port, tcp_server_port, udp_server_port) 262 else: 263 create_service_from_yaml( 264 kube_apis.v1, 265 namespace, 266 f"{TEST_DATA}/common/service/loadbalancer-with-additional-ports.yaml", 267 ) 268 public_ip = wait_for_public_ip(kube_apis.v1, namespace) 269 print(f"The Public IP: {public_ip}") 270 return PublicEndpoint(public_ip) 271 272 273 @pytest.fixture(scope="session") 274 def ingress_controller_prerequisites( 275 cli_arguments, kube_apis, request 276 ) -> IngressControllerPrerequisites: 277 """ 278 Create RBAC, SA, IC namespace and default-secret. 279 280 :param cli_arguments: tests context 281 :param kube_apis: client apis 282 :param request: pytest fixture 283 :return: IngressControllerPrerequisites 284 """ 285 print("------------------------- Create IC Prerequisites -----------------------------------") 286 rbac = configure_rbac(kube_apis.rbac_v1) 287 namespace = create_ns_and_sa_from_yaml(kube_apis.v1, f"{DEPLOYMENTS}/common/ns-and-sa.yaml") 288 k8sVersionBin = subprocess.run(["kubectl", "version"], capture_output=True) 289 k8sVersion = (k8sVersionBin.stdout).decode("ascii") 290 serverVersion = k8sVersion[k8sVersion.find("Server Version:") :].lstrip() 291 minorSerVer = serverVersion[serverVersion.find("Minor") :].lstrip()[0:10] 292 k8sMinorVersion = int("".join(filter(str.isdigit, minorSerVer))) 293 if k8sMinorVersion >= 18: 294 print("Create IngressClass resources:") 295 subprocess.run(["kubectl", "apply", "-f", f"{DEPLOYMENTS}/common/ingress-class.yaml"]) 296 subprocess.run( 297 [ 298 "kubectl", 299 "apply", 300 "-f", 301 f"{TEST_DATA}/ingress-class/resource/custom-ingress-class-res.yaml", 302 ] 303 ) 304 config_map_yaml = f"{DEPLOYMENTS}/common/nginx-config.yaml" 305 create_configmap_from_yaml(kube_apis.v1, namespace, config_map_yaml) 306 with open(config_map_yaml) as f: 307 config_map = yaml.safe_load(f) 308 create_secret_from_yaml( 309 kube_apis.v1, namespace, f"{DEPLOYMENTS}/common/default-server-secret.yaml" 310 ) 311 312 def fin(): 313 print("Clean up prerequisites") 314 delete_namespace(kube_apis.v1, namespace) 315 if k8sMinorVersion >= 18: 316 print("Delete IngressClass resources:") 317 subprocess.run(["kubectl", "delete", "-f", f"{DEPLOYMENTS}/common/ingress-class.yaml"]) 318 subprocess.run( 319 [ 320 "kubectl", 321 "delete", 322 "-f", 323 f"{TEST_DATA}/ingress-class/resource/custom-ingress-class-res.yaml", 324 ] 325 ) 326 cleanup_rbac(kube_apis.rbac_v1, rbac) 327 328 request.addfinalizer(fin) 329 330 return IngressControllerPrerequisites(config_map, namespace, k8sMinorVersion) 331 332 333 @pytest.fixture(scope="session") 334 def kube_apis(cli_arguments) -> KubeApis: 335 """ 336 Set up kubernets-client to operate in cluster. 337 338 :param cli_arguments: a set of command-line arguments 339 :return: KubeApis 340 """ 341 context_name = cli_arguments["context"] 342 kubeconfig = cli_arguments["kubeconfig"] 343 config.load_kube_config(config_file=kubeconfig, context=context_name, persist_config=False) 344 v1 = client.CoreV1Api() 345 extensions_v1_beta1 = client.ExtensionsV1beta1Api() 346 apps_v1_api = client.AppsV1Api() 347 rbac_v1 = client.RbacAuthorizationV1Api() 348 api_extensions_v1 = client.ApiextensionsV1Api() 349 custom_objects = client.CustomObjectsApi() 350 return KubeApis( 351 v1, extensions_v1_beta1, apps_v1_api, rbac_v1, api_extensions_v1, custom_objects 352 ) 353 354 355 @pytest.fixture(scope="session", autouse=True) 356 def cli_arguments(request) -> {}: 357 """ 358 Verify the CLI arguments. 359 360 :param request: pytest fixture 361 :return: {context, image, image-pull-policy, deployment-type, ic-type, service, node-ip, kubeconfig} 362 """ 363 result = {"kubeconfig": request.config.getoption("--kubeconfig")} 364 assert result["kubeconfig"] != "", "Empty kubeconfig is not allowed" 365 print(f"\nTests will use this kubeconfig: {result['kubeconfig']}") 366 367 result["context"] = request.config.getoption("--context") 368 if result["context"] != "": 369 ensure_context_in_config(result["kubeconfig"], result["context"]) 370 print(f"Tests will run against: {result['context']}") 371 else: 372 result["context"] = get_current_context_name(result["kubeconfig"]) 373 print(f"Tests will use a current context: {result['context']}") 374 375 result["image"] = request.config.getoption("--image") 376 assert result["image"] != "", "Empty image is not allowed" 377 print(f"Tests will use the image: {result['image']}") 378 379 result["image-pull-policy"] = request.config.getoption("--image-pull-policy") 380 assert result["image-pull-policy"] != "", "Empty image-pull-policy is not allowed" 381 print(f"Tests will run with the image-pull-policy: {result['image-pull-policy']}") 382 383 result["deployment-type"] = request.config.getoption("--deployment-type") 384 assert ( 385 result["deployment-type"] in ALLOWED_DEPLOYMENT_TYPES 386 ), f"Deployment type {result['deployment-type']} is not allowed" 387 print(f"Tests will use the IC deployment of type: {result['deployment-type']}") 388 389 result["ic-type"] = request.config.getoption("--ic-type") 390 assert result["ic-type"] in ALLOWED_IC_TYPES, f"IC type {result['ic-type']} is not allowed" 391 print(f"Tests will run against the IC of type: {result['ic-type']}") 392 393 result["service"] = request.config.getoption("--service") 394 assert result["service"] in ALLOWED_SERVICE_TYPES, f"Service {result['service']} is not allowed" 395 print(f"Tests will use Service of this type: {result['service']}") 396 if result["service"] == "nodeport": 397 node_ip = request.config.getoption("--node-ip", None) 398 assert node_ip is not None and node_ip != "", f"Service 'nodeport' requires a node-ip" 399 result["node-ip"] = node_ip 400 print(f"Tests will use the node-ip: {result['node-ip']}") 401 return result 402 403 404 @pytest.fixture(scope="class") 405 def crd_ingress_controller( 406 cli_arguments, kube_apis, ingress_controller_prerequisites, ingress_controller_endpoint, request 407 ) -> None: 408 """ 409 Create an Ingress Controller with CRD enabled. 410 411 :param cli_arguments: pytest context 412 :param kube_apis: client apis 413 :param ingress_controller_prerequisites 414 :param ingress_controller_endpoint: 415 :param request: pytest fixture to parametrize this method 416 {type: complete|rbac-without-vs, extra_args: } 417 'type' type of test pre-configuration 418 'extra_args' list of IC cli arguments 419 :return: 420 """ 421 namespace = ingress_controller_prerequisites.namespace 422 name = "nginx-ingress" 423 vs_crd_name = get_name_from_yaml(f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_virtualservers.yaml") 424 vsr_crd_name = get_name_from_yaml( 425 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_virtualserverroutes.yaml" 426 ) 427 pol_crd_name = get_name_from_yaml(f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_policies.yaml") 428 ts_crd_name = get_name_from_yaml( 429 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_transportservers.yaml" 430 ) 431 gc_crd_name = get_name_from_yaml( 432 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_globalconfigurations.yaml" 433 ) 434 435 try: 436 print("------------------------- Update ClusterRole -----------------------------------") 437 if request.param["type"] == "rbac-without-vs": 438 patch_rbac(kube_apis.rbac_v1, f"{TEST_DATA}/virtual-server/rbac-without-vs.yaml") 439 print("------------------------- Register CRDs -----------------------------------") 440 create_crd_from_yaml( 441 kube_apis.api_extensions_v1, 442 vs_crd_name, 443 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_virtualservers.yaml", 444 ) 445 create_crd_from_yaml( 446 kube_apis.api_extensions_v1, 447 vsr_crd_name, 448 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_virtualserverroutes.yaml", 449 ) 450 create_crd_from_yaml( 451 kube_apis.api_extensions_v1, 452 pol_crd_name, 453 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_policies.yaml", 454 ) 455 create_crd_from_yaml( 456 kube_apis.api_extensions_v1, 457 ts_crd_name, 458 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_transportservers.yaml", 459 ) 460 create_crd_from_yaml( 461 kube_apis.api_extensions_v1, 462 gc_crd_name, 463 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_globalconfigurations.yaml", 464 ) 465 print("------------------------- Create IC -----------------------------------") 466 name = create_ingress_controller( 467 kube_apis.v1, 468 kube_apis.apps_v1_api, 469 cli_arguments, 470 namespace, 471 request.param.get("extra_args", None), 472 ) 473 ensure_connection_to_public_endpoint( 474 ingress_controller_endpoint.public_ip, 475 ingress_controller_endpoint.port, 476 ingress_controller_endpoint.port_ssl, 477 ) 478 except ApiException as ex: 479 # Finalizer method doesn't start if fixture creation was incomplete, ensure clean up here 480 print(f"Failed to complete CRD IC fixture: {ex}\nClean up the cluster as much as possible.") 481 delete_crd(kube_apis.api_extensions_v1, vs_crd_name) 482 delete_crd(kube_apis.api_extensions_v1, vsr_crd_name) 483 delete_crd(kube_apis.api_extensions_v1, pol_crd_name) 484 delete_crd(kube_apis.api_extensions_v1, ts_crd_name) 485 delete_crd(kube_apis.api_extensions_v1, gc_crd_name) 486 print("Restore the ClusterRole:") 487 patch_rbac(kube_apis.rbac_v1, f"{DEPLOYMENTS}/rbac/rbac.yaml") 488 print("Remove the IC:") 489 delete_ingress_controller( 490 kube_apis.apps_v1_api, name, cli_arguments["deployment-type"], namespace 491 ) 492 493 def fin(): 494 delete_crd(kube_apis.api_extensions_v1, vs_crd_name) 495 delete_crd(kube_apis.api_extensions_v1, vsr_crd_name) 496 delete_crd(kube_apis.api_extensions_v1, pol_crd_name) 497 delete_crd(kube_apis.api_extensions_v1, ts_crd_name) 498 delete_crd(kube_apis.api_extensions_v1, gc_crd_name) 499 print("Restore the ClusterRole:") 500 patch_rbac(kube_apis.rbac_v1, f"{DEPLOYMENTS}/rbac/rbac.yaml") 501 print("Remove the IC:") 502 delete_ingress_controller( 503 kube_apis.apps_v1_api, name, cli_arguments["deployment-type"], namespace 504 ) 505 506 request.addfinalizer(fin) 507 508 509 @pytest.fixture(scope="class") 510 def crd_ingress_controller_with_ap( 511 cli_arguments, kube_apis, ingress_controller_prerequisites, ingress_controller_endpoint, request 512 ) -> None: 513 """ 514 Create an Ingress Controller with AppProtect CRD enabled. 515 :param cli_arguments: pytest context 516 :param kube_apis: client apis 517 :param ingress_controller_prerequisites 518 :param ingress_controller_endpoint: 519 :param request: pytest fixture to parametrize this method 520 {extra_args: } 521 'extra_args' list of IC arguments 522 :return: 523 """ 524 namespace = ingress_controller_prerequisites.namespace 525 name = "nginx-ingress" 526 try: 527 print( 528 "--------------------Create roles and bindings for AppProtect------------------------" 529 ) 530 rbac = configure_rbac_with_ap(kube_apis.rbac_v1) 531 532 print("------------------------- Register AP CRD -----------------------------------") 533 ap_pol_crd_name = get_name_from_yaml( 534 f"{DEPLOYMENTS}/common/crds/appprotect.f5.com_appolicies.yaml" 535 ) 536 ap_log_crd_name = get_name_from_yaml( 537 f"{DEPLOYMENTS}/common/crds/appprotect.f5.com_aplogconfs.yaml" 538 ) 539 ap_uds_crd_name = get_name_from_yaml( 540 f"{DEPLOYMENTS}/common/crds/appprotect.f5.com_apusersigs.yaml" 541 ) 542 vs_crd_name = get_name_from_yaml( 543 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_virtualservers.yaml" 544 ) 545 vsr_crd_name = get_name_from_yaml( 546 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_virtualserverroutes.yaml" 547 ) 548 pol_crd_name = get_name_from_yaml(f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_policies.yaml") 549 ts_crd_name = get_name_from_yaml( 550 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_transportservers.yaml" 551 ) 552 create_crd_from_yaml( 553 kube_apis.api_extensions_v1, 554 ap_pol_crd_name, 555 f"{DEPLOYMENTS}/common/crds/appprotect.f5.com_appolicies.yaml", 556 ) 557 create_crd_from_yaml( 558 kube_apis.api_extensions_v1, 559 ap_log_crd_name, 560 f"{DEPLOYMENTS}/common/crds/appprotect.f5.com_aplogconfs.yaml", 561 ) 562 create_crd_from_yaml( 563 kube_apis.api_extensions_v1, 564 ap_uds_crd_name, 565 f"{DEPLOYMENTS}/common/crds/appprotect.f5.com_apusersigs.yaml", 566 ) 567 create_crd_from_yaml( 568 kube_apis.api_extensions_v1, 569 vs_crd_name, 570 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_virtualservers.yaml", 571 ) 572 create_crd_from_yaml( 573 kube_apis.api_extensions_v1, 574 vsr_crd_name, 575 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_virtualserverroutes.yaml", 576 ) 577 create_crd_from_yaml( 578 kube_apis.api_extensions_v1, 579 pol_crd_name, 580 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_policies.yaml", 581 ) 582 create_crd_from_yaml( 583 kube_apis.api_extensions_v1, 584 ts_crd_name, 585 f"{DEPLOYMENTS}/common/crds/k8s.nginx.org_transportservers.yaml", 586 ) 587 588 print("------------------------- Create IC -----------------------------------") 589 name = create_ingress_controller( 590 kube_apis.v1, 591 kube_apis.apps_v1_api, 592 cli_arguments, 593 namespace, 594 request.param.get("extra_args", None), 595 ) 596 ensure_connection_to_public_endpoint( 597 ingress_controller_endpoint.public_ip, 598 ingress_controller_endpoint.port, 599 ingress_controller_endpoint.port_ssl, 600 ) 601 except Exception as ex: 602 print(f"Failed to complete CRD IC fixture: {ex}\nClean up the cluster as much as possible.") 603 delete_crd( 604 kube_apis.api_extensions_v1, 605 ap_pol_crd_name, 606 ) 607 delete_crd( 608 kube_apis.api_extensions_v1, 609 ap_log_crd_name, 610 ) 611 delete_crd( 612 kube_apis.api_extensions_v1, 613 ap_uds_crd_name, 614 ) 615 delete_crd( 616 kube_apis.api_extensions_v1, 617 vs_crd_name, 618 ) 619 delete_crd( 620 kube_apis.api_extensions_v1, 621 vsr_crd_name, 622 ) 623 delete_crd( 624 kube_apis.api_extensions_v1, 625 pol_crd_name, 626 ) 627 delete_crd( 628 kube_apis.api_extensions_v1, 629 ts_crd_name, 630 ) 631 print("Remove ap-rbac") 632 cleanup_rbac(kube_apis.rbac_v1, rbac) 633 print("Remove the IC:") 634 delete_ingress_controller( 635 kube_apis.apps_v1_api, name, cli_arguments["deployment-type"], namespace 636 ) 637 638 def fin(): 639 print("--------------Cleanup----------------") 640 delete_crd( 641 kube_apis.api_extensions_v1, 642 ap_pol_crd_name, 643 ) 644 delete_crd( 645 kube_apis.api_extensions_v1, 646 ap_log_crd_name, 647 ) 648 delete_crd( 649 kube_apis.api_extensions_v1, 650 ap_uds_crd_name, 651 ) 652 delete_crd( 653 kube_apis.api_extensions_v1, 654 vs_crd_name, 655 ) 656 delete_crd( 657 kube_apis.api_extensions_v1, 658 vsr_crd_name, 659 ) 660 delete_crd( 661 kube_apis.api_extensions_v1, 662 pol_crd_name, 663 ) 664 delete_crd( 665 kube_apis.api_extensions_v1, 666 ts_crd_name, 667 ) 668 print("Remove ap-rbac") 669 cleanup_rbac(kube_apis.rbac_v1, rbac) 670 print("Remove the IC:") 671 delete_ingress_controller( 672 kube_apis.apps_v1_api, name, cli_arguments["deployment-type"], namespace 673 ) 674 675 request.addfinalizer(fin) 676 677 678 class VirtualServerSetup: 679 """ 680 Encapsulate Virtual Server Example details. 681 682 Attributes: 683 public_endpoint (PublicEndpoint): 684 namespace (str): 685 vs_host (str): 686 vs_name (str): 687 backend_1_url (str): 688 backend_2_url (str): 689 """ 690 691 def __init__(self, public_endpoint: PublicEndpoint, namespace, vs_host, vs_name, vs_paths): 692 self.public_endpoint = public_endpoint 693 self.namespace = namespace 694 self.vs_host = vs_host 695 self.vs_name = vs_name 696 self.backend_1_url = ( 697 f"http://{public_endpoint.public_ip}:{public_endpoint.port}{vs_paths[0]}" 698 ) 699 self.backend_2_url = ( 700 f"http://{public_endpoint.public_ip}:{public_endpoint.port}{vs_paths[1]}" 701 ) 702 self.backend_1_url_ssl = ( 703 f"https://{public_endpoint.public_ip}:{public_endpoint.port_ssl}{vs_paths[0]}" 704 ) 705 self.backend_2_url_ssl = ( 706 f"https://{public_endpoint.public_ip}:{public_endpoint.port_ssl}{vs_paths[1]}" 707 ) 708 709 710 @pytest.fixture(scope="class") 711 def virtual_server_setup( 712 request, kube_apis, ingress_controller_endpoint, test_namespace 713 ) -> VirtualServerSetup: 714 """ 715 Prepare Virtual Server Example. 716 717 :param request: internal pytest fixture to parametrize this method: 718 {example: virtual-server|virtual-server-tls|..., app_type: simple|split|...} 719 'example' is a directory name in TEST_DATA, 720 'app_type' is a directory name in TEST_DATA/common/app 721 :param kube_apis: client apis 722 :param crd_ingress_controller: 723 :param ingress_controller_endpoint: 724 :param test_namespace: 725 :return: VirtualServerSetup 726 """ 727 print( 728 "------------------------- Deploy Virtual Server Example -----------------------------------" 729 ) 730 vs_source = f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml" 731 vs_name = create_virtual_server_from_yaml(kube_apis.custom_objects, vs_source, test_namespace) 732 vs_host = get_first_host_from_yaml(vs_source) 733 vs_paths = get_paths_from_vs_yaml(vs_source) 734 if request.param["app_type"]: 735 create_example_app(kube_apis, request.param["app_type"], test_namespace) 736 wait_until_all_pods_are_ready(kube_apis.v1, test_namespace) 737 738 def fin(): 739 print("Clean up Virtual Server Example:") 740 delete_virtual_server(kube_apis.custom_objects, vs_name, test_namespace) 741 if request.param["app_type"]: 742 delete_common_app(kube_apis, request.param["app_type"], test_namespace) 743 744 request.addfinalizer(fin) 745 746 return VirtualServerSetup( 747 ingress_controller_endpoint, test_namespace, vs_host, vs_name, vs_paths 748 ) 749 750 751 class TransportServerSetup: 752 """ 753 Encapsulate Transport Server Example details. 754 755 Attributes: 756 name (str): 757 namespace (str): 758 """ 759 760 def __init__(self, name, namespace, ingress_pod_name, ic_namespace, public_endpoint: PublicEndpoint, resource): 761 self.name = name 762 self.namespace = namespace 763 self.ingress_pod_name = ingress_pod_name 764 self.ic_namespace = ic_namespace 765 self.public_endpoint = public_endpoint 766 self.resource = resource 767 768 769 @pytest.fixture(scope="class") 770 def transport_server_setup( 771 request, kube_apis, ingress_controller_prerequisites, test_namespace, ingress_controller_endpoint 772 ) -> TransportServerSetup: 773 """ 774 Prepare Transport Server Example. 775 776 :param ingress_controller_endpoint: 777 :param ingress_controller_prerequisites: 778 :param request: internal pytest fixture to parametrize this method 779 :param kube_apis: client apis 780 :param test_namespace: 781 :return: TransportServerSetup 782 """ 783 print( 784 "------------------------- Deploy Transport Server Example -----------------------------------" 785 ) 786 787 # deploy global config 788 global_config_file = ( 789 f"{TEST_DATA}/{request.param['example']}/standard/global-configuration.yaml" 790 ) 791 gc_resource = create_gc_from_yaml(kube_apis.custom_objects, global_config_file, "nginx-ingress") 792 793 # deploy service_file 794 service_file = f"{TEST_DATA}/{request.param['example']}/standard/service_deployment.yaml" 795 create_items_from_yaml(kube_apis, service_file, test_namespace) 796 797 # deploy transport server 798 transport_server_file = f"{TEST_DATA}/{request.param['example']}/standard/transport-server.yaml" 799 ts_resource = create_ts_from_yaml( 800 kube_apis.custom_objects, transport_server_file, test_namespace 801 ) 802 803 wait_until_all_pods_are_ready(kube_apis.v1, test_namespace) 804 805 def fin(): 806 print("Clean up TransportServer Example:") 807 delete_ts(kube_apis.custom_objects, ts_resource, test_namespace) 808 delete_items_from_yaml(kube_apis, service_file, test_namespace) 809 delete_gc(kube_apis.custom_objects, gc_resource, "nginx-ingress") 810 811 request.addfinalizer(fin) 812 813 ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) 814 ic_namespace = ingress_controller_prerequisites.namespace 815 816 return TransportServerSetup( 817 ts_resource['metadata']['name'], 818 test_namespace, 819 ic_pod_name, 820 ic_namespace, 821 ingress_controller_endpoint, 822 ts_resource, 823 ) 824 825 826 @pytest.fixture(scope="class") 827 def v_s_route_app_setup(request, kube_apis, v_s_route_setup) -> None: 828 """ 829 Prepare an example app for Virtual Server Route. 830 831 1st namespace with backend1-svc and backend3-svc and deployment and 2nd namespace with backend2-svc and deployment. 832 833 :param request: internal pytest fixture 834 :param kube_apis: client apis 835 :param v_s_route_setup: 836 :return: 837 """ 838 print( 839 "---------------------- Deploy a VS Route Example Application ----------------------------" 840 ) 841 svc_one = create_service_with_name( 842 kube_apis.v1, v_s_route_setup.route_m.namespace, "backend1-svc" 843 ) 844 svc_three = create_service_with_name( 845 kube_apis.v1, v_s_route_setup.route_m.namespace, "backend3-svc" 846 ) 847 deployment_one = create_deployment_with_name( 848 kube_apis.apps_v1_api, v_s_route_setup.route_m.namespace, "backend1" 849 ) 850 deployment_three = create_deployment_with_name( 851 kube_apis.apps_v1_api, v_s_route_setup.route_m.namespace, "backend3" 852 ) 853 854 svc_two = create_service_with_name( 855 kube_apis.v1, v_s_route_setup.route_s.namespace, "backend2-svc" 856 ) 857 deployment_two = create_deployment_with_name( 858 kube_apis.apps_v1_api, v_s_route_setup.route_s.namespace, "backend2" 859 ) 860 861 wait_until_all_pods_are_ready(kube_apis.v1, v_s_route_setup.route_m.namespace) 862 wait_until_all_pods_are_ready(kube_apis.v1, v_s_route_setup.route_s.namespace) 863 864 def fin(): 865 print("Clean up the Application:") 866 delete_deployment(kube_apis.apps_v1_api, deployment_one, v_s_route_setup.route_m.namespace) 867 delete_service(kube_apis.v1, svc_one, v_s_route_setup.route_m.namespace) 868 delete_deployment( 869 kube_apis.apps_v1_api, deployment_three, v_s_route_setup.route_m.namespace 870 ) 871 delete_service(kube_apis.v1, svc_three, v_s_route_setup.route_m.namespace) 872 delete_deployment(kube_apis.apps_v1_api, deployment_two, v_s_route_setup.route_s.namespace) 873 delete_service(kube_apis.v1, svc_two, v_s_route_setup.route_s.namespace) 874 875 request.addfinalizer(fin) 876 877 878 class VirtualServerRoute: 879 """ 880 Encapsulate Virtual Server Route details. 881 882 Attributes: 883 namespace (str): 884 name (str): 885 paths ([]): 886 """ 887 888 def __init__(self, namespace, name, paths): 889 self.namespace = namespace 890 self.name = name 891 self.paths = paths 892 893 894 class VirtualServerRouteSetup: 895 """ 896 Encapsulate Virtual Server Example details. 897 898 Attributes: 899 public_endpoint (PublicEndpoint): 900 namespace (str): 901 vs_host (str): 902 vs_name (str): 903 route_m (VirtualServerRoute): route with multiple subroutes 904 route_s (VirtualServerRoute): route with single subroute 905 """ 906 907 def __init__( 908 self, 909 public_endpoint: PublicEndpoint, 910 namespace, 911 vs_host, 912 vs_name, 913 route_m: VirtualServerRoute, 914 route_s: VirtualServerRoute, 915 ): 916 self.public_endpoint = public_endpoint 917 self.namespace = namespace 918 self.vs_host = vs_host 919 self.vs_name = vs_name 920 self.route_m = route_m 921 self.route_s = route_s 922 923 924 @pytest.fixture(scope="class") 925 def v_s_route_setup(request, kube_apis, ingress_controller_endpoint) -> VirtualServerRouteSetup: 926 """ 927 Prepare Virtual Server Route Example. 928 929 1st namespace with VS and 1st addressed VSR and 2nd namespace with second addressed VSR. 930 931 :param request: internal pytest fixture to parametrize this method: 932 {example: virtual-server|virtual-server-tls|...} 933 'example' is a directory name in TEST_DATA 934 :param kube_apis: client apis 935 :param crd_ingress_controller: 936 :param ingress_controller_endpoint: 937 938 :return: VirtualServerRouteSetup 939 """ 940 vs_routes_ns = get_route_namespace_from_vs_yaml( 941 f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml" 942 ) 943 ns_1 = create_namespace_with_name_from_yaml( 944 kube_apis.v1, vs_routes_ns[0], f"{TEST_DATA}/common/ns.yaml" 945 ) 946 ns_2 = create_namespace_with_name_from_yaml( 947 kube_apis.v1, vs_routes_ns[1], f"{TEST_DATA}/common/ns.yaml" 948 ) 949 print("------------------------- Deploy Virtual Server -----------------------------------") 950 vs_name = create_virtual_server_from_yaml( 951 kube_apis.custom_objects, 952 f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml", 953 ns_1, 954 ) 955 vs_host = get_first_host_from_yaml( 956 f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml" 957 ) 958 959 print( 960 "------------------------- Deploy Virtual Server Routes -----------------------------------" 961 ) 962 vsr_m_name = create_v_s_route_from_yaml( 963 kube_apis.custom_objects, 964 f"{TEST_DATA}/{request.param['example']}/route-multiple.yaml", 965 ns_1, 966 ) 967 vsr_m_paths = get_paths_from_vsr_yaml( 968 f"{TEST_DATA}/{request.param['example']}/route-multiple.yaml" 969 ) 970 route_m = VirtualServerRoute(ns_1, vsr_m_name, vsr_m_paths) 971 972 vsr_s_name = create_v_s_route_from_yaml( 973 kube_apis.custom_objects, f"{TEST_DATA}/{request.param['example']}/route-single.yaml", ns_2 974 ) 975 vsr_s_paths = get_paths_from_vsr_yaml( 976 f"{TEST_DATA}/{request.param['example']}/route-single.yaml" 977 ) 978 route_s = VirtualServerRoute(ns_2, vsr_s_name, vsr_s_paths) 979 980 def fin(): 981 print("Clean up the Virtual Server Route:") 982 delete_v_s_route(kube_apis.custom_objects, vsr_m_name, ns_1) 983 delete_v_s_route(kube_apis.custom_objects, vsr_s_name, ns_2) 984 print("Clean up Virtual Server:") 985 delete_virtual_server(kube_apis.custom_objects, vs_name, ns_1) 986 print("Delete test namespaces") 987 delete_namespace(kube_apis.v1, ns_1) 988 delete_namespace(kube_apis.v1, ns_2) 989 990 request.addfinalizer(fin) 991 992 return VirtualServerRouteSetup( 993 ingress_controller_endpoint, ns_1, vs_host, vs_name, route_m, route_s 994 ) 995 996 997 @pytest.fixture(scope="function") 998 def restore_configmap(request, kube_apis, ingress_controller_prerequisites, test_namespace) -> None: 999 """ 1000 Return ConfigMap to the initial state after the test. 1001 1002 :param request: internal pytest fixture 1003 :param kube_apis: client apis 1004 :param ingress_controller_prerequisites: 1005 :param test_namespace: str 1006 :return: 1007 """ 1008 1009 def fin(): 1010 replace_configmap_from_yaml( 1011 kube_apis.v1, 1012 ingress_controller_prerequisites.config_map["metadata"]["name"], 1013 ingress_controller_prerequisites.namespace, 1014 f"{DEPLOYMENTS}/common/nginx-config.yaml", 1015 ) 1016 1017 request.addfinalizer(fin)