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