github.com/nginxinc/kubernetes-ingress@v1.12.5/tests/suite/test_v_s_route_focused_canary.py (about) 1 import pytest 2 import requests 3 import yaml 4 5 from settings import TEST_DATA 6 from suite.custom_resources_utils import create_virtual_server_from_yaml, create_v_s_route_from_yaml 7 from suite.fixtures import VirtualServerRoute 8 from suite.resources_utils import ensure_response_from_backend, create_example_app, \ 9 wait_until_all_pods_are_ready, create_namespace_with_name_from_yaml, delete_namespace 10 from suite.yaml_utils import get_paths_from_vsr_yaml, get_first_host_from_yaml, get_route_namespace_from_vs_yaml 11 12 13 def get_weights_of_splitting(file) -> []: 14 """ 15 Parse VSR yaml file into an array of weights. 16 17 :param file: an absolute path to file 18 :return: [] 19 """ 20 weights = [] 21 with open(file) as f: 22 docs = yaml.load_all(f) 23 for dep in docs: 24 for item in dep['spec']['subroutes'][0]['matches'][0]['splits']: 25 weights.append(item['weight']) 26 return weights 27 28 29 def get_upstreams_of_splitting(file) -> []: 30 """ 31 Parse VSR yaml file into an array of upstreams. 32 33 :param file: an absolute path to file 34 :return: [] 35 """ 36 upstreams = [] 37 with open(file) as f: 38 docs = yaml.load_all(f) 39 for dep in docs: 40 for item in dep['spec']['subroutes'][0]['matches'][0]['splits']: 41 upstreams.append(item['action']['pass']) 42 return upstreams 43 44 45 class VSRAdvancedRoutingSetup: 46 """ 47 Encapsulate advanced routing VSR example details. 48 49 Attributes: 50 namespace (str): 51 vs_host (str): 52 vs_name (str): 53 route (VirtualServerRoute): 54 backends_url (str): backend url 55 """ 56 57 def __init__(self, namespace, vs_host, vs_name, route: VirtualServerRoute, backends_url): 58 self.namespace = namespace 59 self.vs_host = vs_host 60 self.vs_name = vs_name 61 self.route = route 62 self.backends_url = backends_url 63 64 65 @pytest.fixture(scope="class") 66 def vsr_canary_setup(request, kube_apis, 67 ingress_controller_prerequisites, ingress_controller_endpoint) -> VSRAdvancedRoutingSetup: 68 """ 69 Prepare an example app for advanced routing VSR. 70 71 Single namespace with VS+VSR and simple app. 72 73 :param request: internal pytest fixture 74 :param kube_apis: client apis 75 :param ingress_controller_endpoint: 76 :param ingress_controller_prerequisites: 77 :return: 78 """ 79 vs_routes_ns = get_route_namespace_from_vs_yaml( 80 f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml") 81 ns_1 = create_namespace_with_name_from_yaml(kube_apis.v1, 82 vs_routes_ns[0], 83 f"{TEST_DATA}/common/ns.yaml") 84 print("------------------------- Deploy Virtual Server -----------------------------------") 85 vs_name = create_virtual_server_from_yaml(kube_apis.custom_objects, 86 f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml", 87 ns_1) 88 vs_host = get_first_host_from_yaml(f"{TEST_DATA}/{request.param['example']}/standard/virtual-server.yaml") 89 90 print("------------------------- Deploy Virtual Server Route -----------------------------------") 91 vsr_name = create_v_s_route_from_yaml(kube_apis.custom_objects, 92 f"{TEST_DATA}/{request.param['example']}/virtual-server-route.yaml", 93 ns_1) 94 vsr_paths = get_paths_from_vsr_yaml(f"{TEST_DATA}/{request.param['example']}/virtual-server-route.yaml") 95 route = VirtualServerRoute(ns_1, vsr_name, vsr_paths) 96 backends_url = f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.port}{vsr_paths[0]}" 97 98 print("---------------------- Deploy simple app ----------------------------") 99 create_example_app(kube_apis, "simple", ns_1) 100 wait_until_all_pods_are_ready(kube_apis.v1, ns_1) 101 102 def fin(): 103 print("Delete test namespace") 104 delete_namespace(kube_apis.v1, ns_1) 105 106 request.addfinalizer(fin) 107 108 return VSRAdvancedRoutingSetup(ns_1, vs_host, vs_name, route, backends_url) 109 110 111 @pytest.mark.vsr 112 @pytest.mark.parametrize('crd_ingress_controller, vsr_canary_setup', 113 [({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, 114 {"example": "virtual-server-route-focused-canary"})], 115 indirect=True) 116 class TestVSRFocusedCanaryRelease: 117 def test_flow_with_header(self, kube_apis, crd_ingress_controller, vsr_canary_setup): 118 ensure_response_from_backend(vsr_canary_setup.backends_url, vsr_canary_setup.vs_host) 119 120 weights = get_weights_of_splitting( 121 f"{TEST_DATA}/virtual-server-route-focused-canary/virtual-server-route.yaml") 122 upstreams = get_upstreams_of_splitting( 123 f"{TEST_DATA}/virtual-server-route-focused-canary/virtual-server-route.yaml") 124 sum_weights = sum(weights) 125 ratios = [round(i/sum_weights, 1) for i in weights] 126 127 counter_v1, counter_v2 = 0, 0 128 for _ in range(100): 129 resp = requests.get(vsr_canary_setup.backends_url, 130 headers={"host": vsr_canary_setup.vs_host, "x-version": "canary"}) 131 if upstreams[0] in resp.text in resp.text: 132 counter_v1 = counter_v1 + 1 133 elif upstreams[1] in resp.text in resp.text: 134 counter_v2 = counter_v2 + 1 135 else: 136 pytest.fail(f"An unexpected backend in response: {resp.text}") 137 138 assert abs(round(counter_v1/(counter_v1 + counter_v2), 1) - ratios[0]) <= 0.2 139 assert abs(round(counter_v2/(counter_v1 + counter_v2), 1) - ratios[1]) <= 0.2