From 9819fe5d7f56f3409fd6d728113f3ef08897df18 Mon Sep 17 00:00:00 2001 From: scavnicka Date: Mon, 12 Oct 2020 12:19:48 +0000 Subject: [PATCH] Create Tempest case to ensure Services without Selectors To ensure that connectivity is working we need to create a new tempest test, which will create a service without selectors, create the endpoints and check the connectivity to the endpoints. Depends-On: Ia6404c22132af3a17ce865c4f33a57b2b6832e9f Change-Id: I07f24bb754f2dde24fe47b340ebec04440ff3890 --- kuryr_tempest_plugin/config.py | 3 + kuryr_tempest_plugin/tests/scenario/base.py | 79 ++++++++++++++++++- .../tests/scenario/test_service.py | 19 +++++ 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/kuryr_tempest_plugin/config.py b/kuryr_tempest_plugin/config.py index 29f256b8..00cdd52d 100644 --- a/kuryr_tempest_plugin/config.py +++ b/kuryr_tempest_plugin/config.py @@ -91,4 +91,7 @@ kuryr_k8s_opts = [ cfg.BoolOpt("ipv6", default=False, help="True if Kuryr is configured to use IPv6 subnets as pod " "and service subnets."), + cfg.BoolOpt("test_services_without_selector", default=False, + help="Whether or not service without selector tests will be " + "running"), ] diff --git a/kuryr_tempest_plugin/tests/scenario/base.py b/kuryr_tempest_plugin/tests/scenario/base.py index 258a3967..346d4544 100644 --- a/kuryr_tempest_plugin/tests/scenario/base.py +++ b/kuryr_tempest_plugin/tests/scenario/base.py @@ -654,6 +654,75 @@ class BaseKuryrScenarioTest(manager.NetworkScenarioTest): cls.addClassResourceCleanup(cls.delete_service, service_name, namespace=namespace) + @classmethod + def service_without_selector_base(cls, pod_num=2, + spec_type="ClusterIP", + protocol="TCP", + port=80, + target_port=8080, + namespace="default", + get_ip=True, + service_name=None): + + """Create a setup for services without selector + + This method creates a pod, service without selector and endpoint. + """ + pod_name_list = [] + for i in range(pod_num): + pod_name, pod = cls.create_pod(namespace=namespace) + pod_name_list.append(pod_name) + + cls.pod_num = pod_num + service_name, service_obj = cls.create_service( + spec_type=spec_type, protocol=protocol, port=port, + target_port=target_port, namespace=namespace, + service_name=service_name, pod_label=None) + pod_1_ip = cls.get_pod_ip(pod_name_list[0], namespace=namespace) + pod_2_ip = cls.get_pod_ip(pod_name_list[1], namespace=namespace) + port = service_obj.spec.ports[0] + port_name = port.name + # Endpoints is a collection of endpoints that implement + # the actual service + endpoint = cls.k8s_client.V1Endpoints() + endpoint.metadata = cls.k8s_client.V1ObjectMeta(name=service_name) + # EndpointSubset is a group of addresses with a set of ports + endpoint.subsets = [cls.k8s_client.V1EndpointSubset( + addresses=[ + cls.k8s_client.V1EndpointAddress( + ip=pod_1_ip), + cls.k8s_client.V1EndpointAddress( + ip=pod_2_ip + ) + ], + ports=[cls.k8s_client.V1EndpointPort( + name=port_name, + port=target_port, + protocol=protocol)])] + cls.k8s_client.CoreV1Api().create_namespaced_endpoints( + namespace=namespace, body=endpoint) + if get_ip: + cls.service_ip = cls.get_service_ip( + service_name, spec_type=spec_type, namespace=namespace) + cls.verify_lbaas_endpoints_configured(service_name, pod_num, + namespace) + cls.service_name = service_name + + @classmethod + def wait_for_ns_serviceaccount(cls, namespace, + timeout_period=consts.NS_TIMEOUT): + start = time.time() + while time.time() - start < timeout_period: + time.sleep(5) + try: + cls.k8s_client.CoreV1Api().read_namespaced_service_account( + 'default', namespace) + return True + except kubernetes.client.rest.ApiException: + pass + + return False + @classmethod def create_namespace(cls, name=None, wait_for_crd=True, timeout_period=consts.NS_TIMEOUT): @@ -664,7 +733,15 @@ class BaseKuryrScenarioTest(manager.NetworkScenarioTest): namespace_obj = cls.k8s_client.CoreV1Api().create_namespace( body=namespace) - if not wait_for_crd: + if not wait_for_crd or not CONF.kuryr_kubernetes.subnet_per_namespace: + # You cannot create pods until default ServiceAccount for the + # namespace is created, let's wait for it. + if not cls.wait_for_ns_serviceaccount(name): + raise lib_exc.TimeoutException( + "Timed out waiting for default ServiceAccount to get " + "created in %s namespace. Is " + "kubernetes-controller-manager running?" % name) + return name, namespace_obj start = time.time() diff --git a/kuryr_tempest_plugin/tests/scenario/test_service.py b/kuryr_tempest_plugin/tests/scenario/test_service.py index 93f5077d..abaa0d57 100644 --- a/kuryr_tempest_plugin/tests/scenario/test_service.py +++ b/kuryr_tempest_plugin/tests/scenario/test_service.py @@ -117,3 +117,22 @@ class TestUdpServiceScenario(base.BaseKuryrScenarioTest): # as the focus of this test is not to check FIP connectivity. self.check_service_internal_connectivity(service_port='90', protocol='UDP') + + +class TestServiceWithoutSelectorScenario(base.BaseKuryrScenarioTest): + + @classmethod + def skip_checks(cls): + super(TestServiceWithoutSelectorScenario, cls).skip_checks() + if not CONF.kuryr_kubernetes.test_services_without_selector: + raise cls.skipException("Service without selectors tests" + " are not enabled") + + @decorators.idempotent_id('bb8cc977-c867-4766-b623-133d8495ee50') + def test_service_without_selector(self): + # Create a service without selector + ns_name, ns_obj = self.create_namespace() + self.addCleanup(self.delete_namespace, ns_name) + self.service_without_selector_base(namespace=ns_name) + + self.check_service_internal_connectivity(namespace=ns_name)