diff --git a/kuryr_tempest_plugin/config.py b/kuryr_tempest_plugin/config.py index 16e1070d..416fe48d 100644 --- a/kuryr_tempest_plugin/config.py +++ b/kuryr_tempest_plugin/config.py @@ -40,6 +40,11 @@ namespace_enabled = cfg.BoolOpt("namespace_enabled", help="Whether or not namespace handler and " "driver are enabled") +network_policy_enabled = cfg.BoolOpt("network_policy_enabled", + default=False, + help="Whether or not network policy " + "handler and driver are enabled") + service_tests_enabled = cfg.BoolOpt("service_tests_enabled", default=True, help="Whether or not service tests " diff --git a/kuryr_tempest_plugin/plugin.py b/kuryr_tempest_plugin/plugin.py index 731fd7ad..f0b0e33b 100644 --- a/kuryr_tempest_plugin/plugin.py +++ b/kuryr_tempest_plugin/plugin.py @@ -42,6 +42,8 @@ class KuryrTempestPlugin(plugins.TempestPlugin): group='kuryr_kubernetes') conf.register_opt(project_config.namespace_enabled, group='kuryr_kubernetes') + conf.register_opt(project_config.network_policy_enabled, + group='kuryr_kubernetes') conf.register_opt(project_config.service_tests_enabled, group='kuryr_kubernetes') conf.register_opt(project_config.kube_system_namespace, @@ -59,6 +61,7 @@ class KuryrTempestPlugin(plugins.TempestPlugin): return [('service_available', [project_config.service_option]), ('kuryr_kubernetes', [project_config.port_pool_enabled, project_config.namespace_enabled, + project_config.network_policy_enabled, project_config.service_tests_enabled, project_config.containerized, project_config.kube_system_namespace, diff --git a/kuryr_tempest_plugin/tests/scenario/base.py b/kuryr_tempest_plugin/tests/scenario/base.py index e05e52c1..527a9497 100644 --- a/kuryr_tempest_plugin/tests/scenario/base.py +++ b/kuryr_tempest_plugin/tests/scenario/base.py @@ -33,9 +33,10 @@ from tempest.scenario import manager CONF = config.CONF LOG = logging.getLogger(__name__) -KURYR_NET_CRD_GROUP = 'openstack.org' -KURYR_NET_CRD_VERSION = 'v1' +KURYR_CRD_GROUP = 'openstack.org' +KURYR_CRD_VERSION = 'v1' KURYR_NET_CRD_PLURAL = 'kuryrnets' +KURYR_NET_POLICY_CRD_PLURAL = 'kuryrnetpolicies' K8S_ANNOTATION_PREFIX = 'openstack.org/kuryr' K8S_ANNOTATION_LBAAS_STATE = K8S_ANNOTATION_PREFIX + '-lbaas-state' K8S_ANNOTATION_LBAAS_RT_STATE = K8S_ANNOTATION_PREFIX + '-lbaas-route-state' @@ -71,6 +72,27 @@ class BaseKuryrScenarioTest(manager.NetworkScenarioTest): cls.os_admin.floating_ips_client.delete_floatingip( fip['floatingip']['id']) + @classmethod + def create_network_policy(cls, name=None, namespace='default'): + if not name: + name = data_utils.rand_name(prefix='kuryr-network-policy') + np = cls.k8s_client.V1NetworkPolicy() + np.kind = 'NetworkPolicy' + np.api_version = 'networking.k8s.io/v1' + np.metadata = cls.k8s_client.V1ObjectMeta(name=name, + namespace=namespace) + np.spec = cls.k8s_client.V1NetworkPolicySpec( + egress=[cls.k8s_client.V1NetworkPolicyEgressRule(ports=None, + to=None)], + ingress=[cls.k8s_client.V1NetworkPolicyIngressRule(_from=None, + ports=None)], + pod_selector=cls.k8s_client.V1LabelSelector( + match_expressions=None, + match_labels=None), + policy_types=['Ingress', 'Egress']) + return cls.k8s_client.NetworkingV1Api( + ).create_namespaced_network_policy(namespace=namespace, body=np) + @classmethod def create_pod(cls, name=None, labels=None, image='kuryr/demo', namespace="default", annotations=None): @@ -96,6 +118,14 @@ class BaseKuryrScenarioTest(manager.NetworkScenarioTest): return name, pod + @classmethod + def delete_network_policy(cls, name, namespace='default'): + body = cls.k8s_client.V1DeleteOptions() + cls.k8s_client.NetworkingV1Api().delete_namespaced_network_policy( + name=name, + namespace=namespace, + body=body) + @classmethod def delete_pod(cls, pod_name, body=None, namespace="default"): if body is None: @@ -382,12 +412,34 @@ class BaseKuryrScenarioTest(manager.NetworkScenarioTest): def list_namespaces(cls, **kwargs): return cls.k8s_client.CoreV1Api().list_namespace(**kwargs) + @classmethod + def list_network_policies(cls, namespace='default', **kwargs): + network_policies_names = [] + k8s = cls.k8s_client.NetworkingV1Api() + for np in k8s.list_namespaced_network_policy(namespace, + **kwargs).items: + network_policies_names.append(np.metadata.name) + return network_policies_names + + @classmethod + def list_security_groups(cls, **filters): + sgs = cls.os_admin.security_groups_client.list_security_groups( + **filters)['security_groups'] + return sgs + @classmethod def get_kuryr_net_crds(cls, name): return cls.k8s_client.CustomObjectsApi().get_cluster_custom_object( - group=KURYR_NET_CRD_GROUP, version=KURYR_NET_CRD_VERSION, + group=KURYR_CRD_GROUP, version=KURYR_CRD_VERSION, plural=KURYR_NET_CRD_PLURAL, name=name) + @classmethod + def get_kuryr_netpolicy_crds(cls, name, namespace='default', **kwargs): + return cls.k8s_client.CustomObjectsApi().get_namespaced_custom_object( + group=KURYR_CRD_GROUP, version=KURYR_CRD_VERSION, + namespace=namespace, plural=KURYR_NET_POLICY_CRD_PLURAL, + name=name, **kwargs) + def get_pod_name_list(self, namespace="default"): return [pod.metadata.name for pod in self.k8s_client.CoreV1Api().list_namespaced_pod( diff --git a/kuryr_tempest_plugin/tests/scenario/test_network_policy.py b/kuryr_tempest_plugin/tests/scenario/test_network_policy.py new file mode 100644 index 00000000..6614e554 --- /dev/null +++ b/kuryr_tempest_plugin/tests/scenario/test_network_policy.py @@ -0,0 +1,70 @@ +# Copyright 2018 Red Hat, Inc. +# +# 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. + +import kubernetes +import time + +from oslo_log import log as logging +from tempest import config +from tempest.lib import decorators + +from kuryr_tempest_plugin.tests.scenario import base + +LOG = logging.getLogger(__name__) +CONF = config.CONF + + +class TestNetworkPolicyScenario(base.BaseKuryrScenarioTest): + + @classmethod + def skip_checks(cls): + super(TestNetworkPolicyScenario, cls).skip_checks() + if not CONF.kuryr_kubernetes.network_policy_enabled: + raise cls.skipException('Network Policy driver and handler must ' + 'be enabled to run this tests') + + @decorators.idempotent_id('24577a9b-1d29-409b-8b60-da3b49d776b1') + def test_create_delete_network_policy(self): + np = self.create_network_policy() + LOG.debug("Creating network policy %s" % np) + network_policy_name = np.metadata.name + kuryr_netpolicy_crd_name = 'np-' + network_policy_name + network_policies = self.list_network_policies() + kuryrnetpolicies = '' + while True: + try: + kuryrnetpolicies = self.get_kuryr_netpolicy_crds( + name=kuryr_netpolicy_crd_name) + break + except kubernetes.client.rest.ApiException: + time.sleep(1) + continue + sg_id = kuryrnetpolicies['spec']['securityGroupId'] + sgs = self.list_security_groups(fields='id') + sg_ids = [sg['id'] for sg in sgs] + self.assertIn(network_policy_name, network_policies) + self.assertEqual(kuryr_netpolicy_crd_name, + str(kuryrnetpolicies['metadata']['name'])) + self.assertIn(sg_id, sg_ids) + self.delete_network_policy(network_policy_name) + self.assertNotIn(network_policy_name, self.list_network_policies()) + while True: + time.sleep(1) + try: + self.get_kuryr_netpolicy_crds(name=kuryr_netpolicy_crd_name) + except kubernetes.client.rest.ApiException: + break + sgs_after = self.list_security_groups(fields='id') + sg_ids_after = [sg['id'] for sg in sgs_after] + self.assertNotIn(sg_id, sg_ids_after)