From 4b0fceea709fe9fb23764174444b88087d262490 Mon Sep 17 00:00:00 2001 From: yangjianfeng Date: Thu, 14 Apr 2022 09:59:26 +0800 Subject: [PATCH] Add annotation project driver scenario test cases Depends-on: https://review.opendev.org/832768 Depends-On: https://review.opendev.org/c/openstack/neutron/+/853261 Implements: blueprint specify-project-by-annotation Change-Id: Ia4591ef96ce642f53ead6147ff4b56960746e510 --- kuryr_tempest_plugin/config.py | 3 + kuryr_tempest_plugin/tests/scenario/base.py | 33 ++++++- kuryr_tempest_plugin/tests/scenario/consts.py | 5 + .../tests/scenario/test_annotation_project.py | 99 +++++++++++++++++++ 4 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 kuryr_tempest_plugin/tests/scenario/test_annotation_project.py diff --git a/kuryr_tempest_plugin/config.py b/kuryr_tempest_plugin/config.py index d7a9926d..70769cea 100644 --- a/kuryr_tempest_plugin/config.py +++ b/kuryr_tempest_plugin/config.py @@ -113,5 +113,8 @@ kuryr_k8s_opts = [ cfg.BoolOpt("trigger_namespace_upon_pod", default=False, help="Whether or not Namespace should be handled upon Pod " "creation"), + cfg.BoolOpt("annotation_project_driver", default=False, + help="Whether or not annotation project tests will be " + "running"), ] diff --git a/kuryr_tempest_plugin/tests/scenario/base.py b/kuryr_tempest_plugin/tests/scenario/base.py index 1296ac51..9d53c5a8 100644 --- a/kuryr_tempest_plugin/tests/scenario/base.py +++ b/kuryr_tempest_plugin/tests/scenario/base.py @@ -890,7 +890,7 @@ class BaseKuryrScenarioTest(manager.NetworkScenarioTest): return False @classmethod - def create_namespace(cls, name=None, labels=None, + def create_namespace(cls, name=None, labels=None, annotations=None, wait_for_crd=True, timeout_period=consts.NS_TIMEOUT): if CONF.kuryr_kubernetes.trigger_namespace_upon_pod: @@ -898,8 +898,8 @@ class BaseKuryrScenarioTest(manager.NetworkScenarioTest): if not name: name = data_utils.rand_name(prefix='kuryr-namespace') namespace = cls.k8s_client.V1Namespace() - namespace.metadata = cls.k8s_client.V1ObjectMeta(name=name, - labels=labels) + namespace.metadata = cls.k8s_client.V1ObjectMeta( + name=name, labels=labels, annotations=annotations) namespace_obj = cls.k8s_client.CoreV1Api().create_namespace( body=namespace) @@ -996,6 +996,33 @@ class BaseKuryrScenarioTest(manager.NetworkScenarioTest): namespace=namespace, plural=KURYR_LOAD_BALANCER_CRD_PLURAL, name=name) + @classmethod + def wait_for_kuryr_resource(cls, namespace, resource_kind, name, + status_key=None): + start = time.time() + while time.time() - start < consts.KURYR_RESOURCE_CHECK_TIMEOUT: + time.sleep(5) + try: + resource_crd = cls.k8s_client.CustomObjectsApi( + ).get_namespaced_custom_object( + group=KURYR_CRD_GROUP, version=KURYR_CRD_VERSION, + namespace=namespace, plural=resource_kind, name=name) + except kubernetes.client.rest.ApiException: + continue + if not status_key: + return resource_crd + try: + if resource_crd['status'][status_key]: + return resource_crd + continue + except KeyError: + continue + msg = ("Timed out waiting for %(resource_kind)s/%(resource_name)s " + "status %(status_key)s" % {"resource_kind": resource_kind, + "resource_name": name, + "status_key": status_key}) + raise lib_exc.TimeoutException(msg) + @classmethod def get_pod_list(cls, namespace='default', label_selector=''): return cls.k8s_client.CoreV1Api().list_namespaced_pod( diff --git a/kuryr_tempest_plugin/tests/scenario/consts.py b/kuryr_tempest_plugin/tests/scenario/consts.py index c05ef92c..98929798 100644 --- a/kuryr_tempest_plugin/tests/scenario/consts.py +++ b/kuryr_tempest_plugin/tests/scenario/consts.py @@ -24,3 +24,8 @@ POD_CHECK_SLEEP_TIME = 5 NP_CHECK_SLEEP_TIME = 10 NS_TIMEOUT = 600 REPETITIONS_PER_BACKEND = 10 +KURYR_RESOURCE_CHECK_TIMEOUT = 300 +KURYR_PORT_CRD_PLURAL = 'kuryrports' +KURYR_LOAD_BALANCER_CRD_PLURAL = 'kuryrloadbalancers' +KURYR_NETWORK_POLICY_CRD_PLURAL = 'kuryrnetworkpolicies' +K8s_ANNOTATION_PROJECT = 'openstack.org/kuryr-project' diff --git a/kuryr_tempest_plugin/tests/scenario/test_annotation_project.py b/kuryr_tempest_plugin/tests/scenario/test_annotation_project.py new file mode 100644 index 00000000..4b3c539d --- /dev/null +++ b/kuryr_tempest_plugin/tests/scenario/test_annotation_project.py @@ -0,0 +1,99 @@ +# Copyright 2022 Troila. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from tempest import config +from tempest.lib import decorators + +from kuryr_tempest_plugin.tests.scenario import base +from kuryr_tempest_plugin.tests.scenario import consts + +CONF = config.CONF + + +class TestAnnotationProjectScenario(base.BaseKuryrScenarioTest): + + @classmethod + def skip_checks(cls): + super(TestAnnotationProjectScenario, cls).skip_checks() + if not CONF.kuryr_kubernetes.annotation_project_driver: + raise cls.skipException('Annotation project driver must be ' + 'enabled to run these tests') + + @classmethod + def resource_setup(cls): + super(TestAnnotationProjectScenario, cls).resource_setup() + cls.project_id = cls.os_primary.projects_client.project_id + + @decorators.idempotent_id('edb10a26-4572-4565-80e4-af16af4186d3') + def test_create_namespace_and_pod(self): + annotations = {consts.K8s_ANNOTATION_PROJECT: self.project_id} + namespace_name, namespace = self.create_namespace( + annotations=annotations) + # Ensure the namespace can be cleaned up upon tests finishing + self.namespaces.append(namespace) + + pod_name, _ = self.create_pod(labels={"app": 'pod-label'}, + namespace=namespace_name) + self.wait_for_kuryr_resource( + namespace_name, consts.KURYR_PORT_CRD_PLURAL, + pod_name, status_key='vifs') + + if CONF.kuryr_kubernetes.kuryrnetworks: + kuryr_net_crd = self.get_kuryr_network_crds(namespace_name) + subnet = self.os_admin.subnets_client.show_subnet( + subnet_id=kuryr_net_crd['status']['subnetId']) + self.assertEqual(subnet['subnet']['project_id'], self.project_id) + network = self.os_admin.networks_client.show_network( + kuryr_net_crd['status']['netId']) + self.assertEqual(network['network']['project_id'], self.project_id) + + ports = self.os_admin.ports_client.list_ports( + **{'project_id': self.project_id, 'device_owner': 'compute:kuryr'}) + self.assertTrue(len(ports['ports']) > 0) + + def test_create_service(self): + if not CONF.kuryr_kubernetes.kuryrloadbalancers: + raise self.skipException("Kuryrloadbalancers CRD should be " + "used to run this test.") + annotations = {consts.K8s_ANNOTATION_PROJECT: self.project_id} + namespace_name, namespace = self.create_namespace( + annotations=annotations) + self.namespaces.append(namespace) + service_name, pods = self.create_setup_for_service_test( + namespace=namespace_name) + kuryr_loadbalancer_crd = self.wait_for_kuryr_resource( + namespace_name, consts.KURYR_LOAD_BALANCER_CRD_PLURAL, + service_name, status_key='loadbalancer') + lb = self.lbaas.show_loadbalancer( + kuryr_loadbalancer_crd['status']['loadbalancer']['id']) + self.assertEqual(lb['project_id'], self.project_id) + + def test_create_network_policy(self): + if not CONF.kuryr_kubernetes.network_policy_enabled: + raise self.skipException("Network policy handler and driver " + "should be used to run this test.") + annotations = {consts.K8s_ANNOTATION_PROJECT: self.project_id} + namespace_name, namespace = self.create_namespace( + annotations=annotations) + self.namespaces.append(namespace) + self.create_network_policy( + name='network-policy', namespace=namespace_name) + kuryr_network_policy_crd = self.wait_for_kuryr_resource( + namespace_name, consts.KURYR_NETWORK_POLICY_CRD_PLURAL, + 'network-policy', status_key="securityGroupId") + sg_id = kuryr_network_policy_crd['status']['securityGroupId'] + security_group = \ + self.os_admin.security_groups_client.show_security_group(sg_id) + self.assertEqual(security_group['security_group']['project_id'], + self.project_id)