From d4233537326738993834d496f2effb7eab5150bb Mon Sep 17 00:00:00 2001 From: Yi Feng Date: Tue, 18 Jan 2022 17:21:08 +0900 Subject: [PATCH] Support specifying namespace for deploying CNF This patch implements that in the instantiate operation of ETSI NFV-SOL003 VNF Lifecycle Management 2.6.1, users can specify the target namespace in InstantiateVnfRequest to deploy CNF on Kubernetes VIM. Implements: blueprint k8s-namespace Change-Id: I292256bc58b54e248da54ccbf3c7e82bd28fd022 --- ...upport-k8s-namespace-9e861c87e4aa1aaa.yaml | 7 + tacker/common/exceptions.py | 5 + .../Definitions/helloworld3_df_simple.yaml | 150 +++++++++ .../Definitions/helloworld3_top.vnfd.yaml | 31 ++ .../Definitions/helloworld3_types.yaml | 53 +++ .../kubernetes/deployment_has_namespace.yaml | 22 ++ .../kubernetes/deployment_no_namespace.yaml | 21 ++ .../Files/kubernetes/namespace01.yaml | 4 + .../Files/kubernetes/namespace02.yaml | 4 + .../TOSCA-Metadata/TOSCA.meta | 24 ++ .../vnflcm/test_kubernetes_multi_ns.py | 140 ++++++++ .../vnfm/infra_drivers/kubernetes/fakes.py | 6 +- .../kubernetes/test_kubernetes_driver.py | 303 ++++++++++-------- .../kubernetes/test_kubernetes_driver_helm.py | 13 +- .../kubernetes/test_translate_outputs.py | 70 ++-- .../infra_drivers/kubernetes/test_utils.py | 70 ++++ .../fixture_data/fixture_data_utils.py | 3 +- .../kubernetes/k8s/translate_outputs.py | 23 +- .../kubernetes/kubernetes_driver.py | 122 +++---- tacker/vnfm/infra_drivers/kubernetes/utils.py | 83 +++++ 20 files changed, 909 insertions(+), 245 deletions(-) create mode 100644 releasenotes/notes/support-k8s-namespace-9e861c87e4aa1aaa.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Definitions/helloworld3_df_simple.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Definitions/helloworld3_top.vnfd.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Definitions/helloworld3_types.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/deployment_has_namespace.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/deployment_no_namespace.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/namespace01.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/namespace02.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/TOSCA-Metadata/TOSCA.meta create mode 100644 tacker/tests/functional/sol_kubernetes/vnflcm/test_kubernetes_multi_ns.py create mode 100644 tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_utils.py create mode 100644 tacker/vnfm/infra_drivers/kubernetes/utils.py diff --git a/releasenotes/notes/support-k8s-namespace-9e861c87e4aa1aaa.yaml b/releasenotes/notes/support-k8s-namespace-9e861c87e4aa1aaa.yaml new file mode 100644 index 000000000..bbe41e846 --- /dev/null +++ b/releasenotes/notes/support-k8s-namespace-9e861c87e4aa1aaa.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + The user specifies the target namespace in the InstantiateVnfRequest to + deploy the CNF on the Kubernetes VIM. The additionalParams field provides + the new parameter ``namespace`` for the target namespace. The Kubernetes + resources in the VNF must be in the same namespace. diff --git a/tacker/common/exceptions.py b/tacker/common/exceptions.py index d1c85ce43..2dff7ca73 100644 --- a/tacker/common/exceptions.py +++ b/tacker/common/exceptions.py @@ -433,6 +433,11 @@ class InvalidIpAddr(TackerException): message = _('Invalid ip address value in resource %(id)s.') +class NamespaceIsNotUnique(TackerException): + message = _('There are multiple namespaces in the manifest file ' + 'for Kubernetes. Only one namespace can be used in one VNF.') + + class TenantMatchFailure(TackerException): message = _('The target %(resource)s %(id)s cannot be %(action)s ' 'from a VIM of a different tenant.') diff --git a/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Definitions/helloworld3_df_simple.yaml b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Definitions/helloworld3_df_simple.yaml new file mode 100644 index 000000000..c21f44fc9 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Definitions/helloworld3_df_simple.yaml @@ -0,0 +1,150 @@ +tosca_definitions_version: tosca_simple_yaml_1_2 + +description: Sample VNF + +imports: + - etsi_nfv_sol001_common_types.yaml + - etsi_nfv_sol001_vnfd_types.yaml + - helloworld3_types.yaml + +topology_template: + inputs: + descriptor_id: + type: string + descriptor_version: + type: string + provider: + type: string + product_name: + type: string + software_version: + type: string + vnfm_info: + type: list + entry_schema: + type: string + flavour_id: + type: string + flavour_description: + type: string + + substitution_mappings: + node_type: company.provider.VNF + properties: + flavour_id: simple + requirements: + virtual_link_external: [] + + node_templates: + VNF: + type: company.provider.VNF + properties: + flavour_description: A simple flavour + + VDU1: + type: tosca.nodes.nfv.Vdu.Compute + properties: + name: vdu1 + description: kubernetes controller resource as VDU + vdu_profile: + min_number_of_instances: 1 + max_number_of_instances: 3 + + VDU2: + type: tosca.nodes.nfv.Vdu.Compute + properties: + name: vdu2 + description: kubernetes controller resource as VDU + vdu_profile: + min_number_of_instances: 1 + max_number_of_instances: 3 + + policies: + - scaling_aspects: + type: tosca.policies.nfv.ScalingAspects + properties: + aspects: + vdu1_aspect: + name: vdu1_aspect + description: vdu1 scaling aspect + max_scale_level: 2 + step_deltas: + - delta_1 + vdu2_aspect: + name: vdu2_aspect + description: vdu2 scaling aspect + max_scale_level: 2 + step_deltas: + - delta_1 + + - instantiation_levels: + type: tosca.policies.nfv.InstantiationLevels + properties: + levels: + instantiation_level_1: + description: Smallest size + scale_info: + vdu1_aspect: + scale_level: 0 + vdu2_aspect: + scale_level: 0 + instantiation_level_2: + description: Largest size + scale_info: + vdu1_aspect: + scale_level: 2 + vdu2_aspect: + scale_level: 2 + default_level: instantiation_level_1 + + - vdu1_initial_delta: + type: tosca.policies.nfv.VduInitialDelta + properties: + initial_delta: + number_of_instances: 1 + targets: [ VDU1 ] + + - vdu1_scaling_aspect_deltas: + type: tosca.policies.nfv.VduScalingAspectDeltas + properties: + aspect: vdu1_aspect + deltas: + delta_1: + number_of_instances: 1 + targets: [ VDU1 ] + + - vdu1_instantiation_levels: + type: tosca.policies.nfv.VduInstantiationLevels + properties: + levels: + instantiation_level_1: + number_of_instances: 1 + instantiation_level_2: + number_of_instances: 3 + targets: [ VDU1 ] + + - vdu2_initial_delta: + type: tosca.policies.nfv.VduInitialDelta + properties: + initial_delta: + number_of_instances: 1 + targets: [ VDU2 ] + + - vdu2_scaling_aspect_deltas: + type: tosca.policies.nfv.VduScalingAspectDeltas + properties: + aspect: vdu2_aspect + deltas: + delta_1: + number_of_instances: 1 + targets: [ VDU2 ] + + - vdu2_instantiation_levels: + type: tosca.policies.nfv.VduInstantiationLevels + properties: + levels: + instantiation_level_1: + number_of_instances: 1 + instantiation_level_2: + number_of_instances: 3 + targets: [ VDU2 ] \ No newline at end of file diff --git a/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Definitions/helloworld3_top.vnfd.yaml b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Definitions/helloworld3_top.vnfd.yaml new file mode 100644 index 000000000..bbb9ac5da --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Definitions/helloworld3_top.vnfd.yaml @@ -0,0 +1,31 @@ +tosca_definitions_version: tosca_simple_yaml_1_2 + +description: Sample VNF + +imports: + - etsi_nfv_sol001_common_types.yaml + - etsi_nfv_sol001_vnfd_types.yaml + - helloworld3_types.yaml + - helloworld3_df_simple.yaml + +topology_template: + inputs: + selected_flavour: + type: string + description: VNF deployment flavour selected by the consumer. It is provided in the API + + node_templates: + VNF: + type: company.provider.VNF + properties: + flavour_id: { get_input: selected_flavour } + descriptor_id: b1bb0ce7-ebca-4fa7-95ed-4840d70a8993 + provider: Company + product_name: Sample VNF + software_version: '1.0' + descriptor_version: '1.0' + vnfm_info: + - Tacker + requirements: + #- virtual_link_external # mapped in lower-level templates + #- virtual_link_internal # mapped in lower-level templates diff --git a/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Definitions/helloworld3_types.yaml b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Definitions/helloworld3_types.yaml new file mode 100644 index 000000000..bd93b4004 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Definitions/helloworld3_types.yaml @@ -0,0 +1,53 @@ +tosca_definitions_version: tosca_simple_yaml_1_2 + +description: VNF type definition + +imports: + - etsi_nfv_sol001_common_types.yaml + - etsi_nfv_sol001_vnfd_types.yaml + +node_types: + company.provider.VNF: + derived_from: tosca.nodes.nfv.VNF + properties: + descriptor_id: + type: string + constraints: [ valid_values: [ b1bb0ce7-ebca-4fa7-95ed-4840d70a8993 ] ] + default: b1bb0ce7-ebca-4fa7-95ed-4840d70a8993 + descriptor_version: + type: string + constraints: [ valid_values: [ '1.0' ] ] + default: '1.0' + provider: + type: string + constraints: [ valid_values: [ 'Company' ] ] + default: 'Company' + product_name: + type: string + constraints: [ valid_values: [ 'Sample VNF' ] ] + default: 'Sample VNF' + software_version: + type: string + constraints: [ valid_values: [ '1.0' ] ] + default: '1.0' + vnfm_info: + type: list + entry_schema: + type: string + constraints: [ valid_values: [ Tacker ] ] + default: [ Tacker ] + flavour_id: + type: string + constraints: [ valid_values: [ simple ] ] + default: simple + flavour_description: + type: string + default: "" + requirements: + - virtual_link_external: + capability: tosca.capabilities.nfv.VirtualLinkable + - virtual_link_internal: + capability: tosca.capabilities.nfv.VirtualLinkable + interfaces: + Vnflcm: + type: tosca.interfaces.nfv.Vnflcm diff --git a/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/deployment_has_namespace.yaml b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/deployment_has_namespace.yaml new file mode 100644 index 000000000..da3455440 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/deployment_has_namespace.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vdu1 + namespace: multi-namespace02 +spec: + replicas: 1 + selector: + matchLabels: + app: webserver + template: + metadata: + labels: + app: webserver + spec: + containers: + - name: nginx + image: nginx + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + protocol: TCP \ No newline at end of file diff --git a/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/deployment_no_namespace.yaml b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/deployment_no_namespace.yaml new file mode 100644 index 000000000..79b2a4c3f --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/deployment_no_namespace.yaml @@ -0,0 +1,21 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vdu2 +spec: + replicas: 1 + selector: + matchLabels: + app: webserver + template: + metadata: + labels: + app: webserver + spec: + containers: + - name: nginx + image: nginx + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + protocol: TCP \ No newline at end of file diff --git a/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/namespace01.yaml b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/namespace01.yaml new file mode 100644 index 000000000..4d7e052ba --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/namespace01.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: multi-namespace01 \ No newline at end of file diff --git a/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/namespace02.yaml b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/namespace02.yaml new file mode 100644 index 000000000..18185ee1b --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/Files/kubernetes/namespace02.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: multi-namespace02 \ No newline at end of file diff --git a/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/TOSCA-Metadata/TOSCA.meta b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/TOSCA-Metadata/TOSCA.meta new file mode 100644 index 000000000..725843a6d --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/test_cnf_multi_ns/TOSCA-Metadata/TOSCA.meta @@ -0,0 +1,24 @@ +TOSCA-Meta-File-Version: 1.0 +Created-by: dummy_user +CSAR-Version: 1.1 +Entry-Definitions: Definitions/helloworld3_top.vnfd.yaml + +Name: Files/kubernetes/deployment_has_namespace.yaml +Content-Type: application/yaml +Algorithm: SHA-256 +Hash: c33b1ec0793619e4752fb0bca2c5c20c9ae2e1717ade94e7d4466efc80a7c6f4 + +Name: Files/kubernetes/deployment_no_namespace.yaml +Content-Type: application/yaml +Algorithm: SHA-256 +Hash: 064c5f54722d74dd7faae6a3f83a504eed579135b366b1251e6d2f024951a7a0 + +Name: Files/kubernetes/namespace01.yaml +Content-Type: application/yaml +Algorithm: SHA-256 +Hash: 6cee66e9786c158edae7da6b1c4639246070cb6ccbfcfbe7f5cec4184552b07d + +Name: Files/kubernetes/namespace02.yaml +Content-Type: application/yaml +Algorithm: SHA-256 +Hash: 04a7db97412b8d88fe6390c34489ac8e963c70d828c11737592723a7fbd30d8c \ No newline at end of file diff --git a/tacker/tests/functional/sol_kubernetes/vnflcm/test_kubernetes_multi_ns.py b/tacker/tests/functional/sol_kubernetes/vnflcm/test_kubernetes_multi_ns.py new file mode 100644 index 000000000..38bc6e906 --- /dev/null +++ b/tacker/tests/functional/sol_kubernetes/vnflcm/test_kubernetes_multi_ns.py @@ -0,0 +1,140 @@ +# All Rights Reserved. +# +# 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 tacker.tests.functional.sol_kubernetes.vnflcm import base as vnflcm_base + + +class VnfLcmKubernetesMultiNsTest(vnflcm_base.BaseVnfLcmKubernetesTest): + + @classmethod + def setUpClass(cls): + super(VnfLcmKubernetesMultiNsTest, cls).setUpClass() + vnf_package_id, cls.vnfd_id = cls._create_and_upload_vnf_package( + cls, cls.tacker_client, "test_cnf_multi_ns", + {"key": "sample_multi_ns_functional"}) + cls.vnf_package_ids.append(vnf_package_id) + + @classmethod + def tearDownClass(cls): + super(VnfLcmKubernetesMultiNsTest, cls).tearDownClass() + + def _test_cnf_scale(self, vnf_instance, aspect_id, + number_of_steps=1, error=False): + scale_level = self._get_scale_level_by_aspect_id( + vnf_instance, aspect_id) + + # test scale out + scale_level = self._test_scale( + vnf_instance['id'], 'SCALE_OUT', aspect_id, scale_level, + number_of_steps, error) + if error: + return scale_level + + # test scale in + scale_level = self._test_scale( + vnf_instance['id'], 'SCALE_IN', aspect_id, scale_level, + number_of_steps) + + return scale_level + + def test_multi_tenant_k8s_additional_params(self): + vnf_instance_name = "multi_tenant_k8s_additional_params" + vnf_instance_description = "multi tenant k8s additional params" + files = ["Files/kubernetes/deployment_has_namespace.yaml", + "Files/kubernetes/namespace01.yaml"] + additional_param = { + "lcm-kubernetes-def-files": files, + "namespace": "multi-namespace01"} + # instantiate + vnf_instance = self._create_and_instantiate_vnf_instance( + self.vnfd_id, "simple", vnf_instance_name, + vnf_instance_description, additional_param) + # scale + self._test_cnf_scale(vnf_instance, "vdu1_aspect", number_of_steps=1) + + before_vnfc_rscs = self._get_vnfc_resource_info(vnf_instance) + deployment_target_vnfc = [vnfc_rsc for vnfc_rsc in before_vnfc_rscs if + vnfc_rsc['vduId'] == 'VDU1'][0] + vnfc_instance_id = [deployment_target_vnfc['id']] + # heal + after_vnfc_rscs = self._test_heal(vnf_instance, vnfc_instance_id) + for vnfc_rsc in after_vnfc_rscs: + after_pod_name = vnfc_rsc['computeResource']['resourceId'] + if vnfc_rsc['id'] == deployment_target_vnfc['id']: + after_resource = deployment_target_vnfc + compute_resource = after_resource['computeResource'] + before_pod_name = compute_resource['resourceId'] + self.assertNotEqual(after_pod_name, before_pod_name) + # terminate + self._terminate_vnf_instance(vnf_instance['id']) + self._delete_vnf_instance(vnf_instance['id']) + + def test_multi_tenant_k8s_manifest(self): + vnf_instance_name = "multi_tenant_k8s_manifest" + vnf_instance_description = "multi tenant k8s manifest" + files = ["Files/kubernetes/deployment_has_namespace.yaml", + "Files/kubernetes/namespace02.yaml"] + additional_param = {"lcm-kubernetes-def-files": files} + # instantiate + vnf_instance = self._create_and_instantiate_vnf_instance( + self.vnfd_id, "simple", vnf_instance_name, + vnf_instance_description, additional_param) + # scale + self._test_cnf_scale(vnf_instance, "vdu1_aspect", number_of_steps=1) + + before_vnfc_rscs = self._get_vnfc_resource_info(vnf_instance) + deployment_target_vnfc = [vnfc_rsc for vnfc_rsc in before_vnfc_rscs if + vnfc_rsc['vduId'] == 'VDU1'][0] + vnfc_instance_id = [deployment_target_vnfc['id']] + # heal + after_vnfc_rscs = self._test_heal(vnf_instance, vnfc_instance_id) + for vnfc_rsc in after_vnfc_rscs: + after_pod_name = vnfc_rsc['computeResource']['resourceId'] + if vnfc_rsc['id'] == deployment_target_vnfc['id']: + after_resource = deployment_target_vnfc + compute_resource = after_resource['computeResource'] + before_pod_name = compute_resource['resourceId'] + self.assertNotEqual(after_pod_name, before_pod_name) + # terminate + self._terminate_vnf_instance(vnf_instance['id']) + self._delete_vnf_instance(vnf_instance['id']) + + def test_multi_tenant_k8s_default(self): + vnf_instance_name = "multi_tenant_k8s_default" + vnf_instance_description = "multi tenant k8s default" + files = ["Files/kubernetes/deployment_no_namespace.yaml"] + additional_param = {"lcm-kubernetes-def-files": files} + # instantiate + vnf_instance = self._create_and_instantiate_vnf_instance( + self.vnfd_id, "simple", vnf_instance_name, + vnf_instance_description, additional_param) + # scale + self._test_cnf_scale(vnf_instance, "vdu2_aspect", number_of_steps=1) + + before_vnfc_rscs = self._get_vnfc_resource_info(vnf_instance) + deployment_target_vnfc = [vnfc_rsc for vnfc_rsc in before_vnfc_rscs if + vnfc_rsc['vduId'] == 'VDU2'][0] + vnfc_instance_id = [deployment_target_vnfc['id']] + # heal + after_vnfc_rscs = self._test_heal(vnf_instance, vnfc_instance_id) + for vnfc_rsc in after_vnfc_rscs: + after_pod_name = vnfc_rsc['computeResource']['resourceId'] + if vnfc_rsc['id'] == deployment_target_vnfc['id']: + after_resource = deployment_target_vnfc + compute_resource = after_resource['computeResource'] + before_pod_name = compute_resource['resourceId'] + self.assertNotEqual(after_pod_name, before_pod_name) + # terminate + self._terminate_vnf_instance(vnf_instance['id']) + self._delete_vnf_instance(vnf_instance['id']) diff --git a/tacker/tests/unit/vnfm/infra_drivers/kubernetes/fakes.py b/tacker/tests/unit/vnfm/infra_drivers/kubernetes/fakes.py index 1fd31c3d3..cd84a35f5 100644 --- a/tacker/tests/unit/vnfm/infra_drivers/kubernetes/fakes.py +++ b/tacker/tests/unit/vnfm/infra_drivers/kubernetes/fakes.py @@ -1049,10 +1049,8 @@ def get_scale_policy(type, aspect_id='vdu1', delta_num=1, is_legacy=False, def get_vnf_resource_list(kind, name='fake_name'): vnf_resource = models.VnfResource() vnf_resource.vnf_instance_id = uuidsentinel.vnf_instance_id - vnf_resource.resource_name = \ - _("fake_namespace,{name}").format(name=name) - vnf_resource.resource_type = \ - _("v1,{kind}").format(kind=kind) + vnf_resource.resource_name = name + vnf_resource.resource_type = f"v1,{kind}" return [vnf_resource] diff --git a/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_kubernetes_driver.py b/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_kubernetes_driver.py index 0d977114f..0d8d07289 100644 --- a/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_kubernetes_driver.py +++ b/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_kubernetes_driver.py @@ -594,7 +594,7 @@ class TestKubernetes(base.TestCase): mock_vnf_by_id.return_value = fake_vnf_get_by_id vnf_resource = vnf_resource_obj.VnfResource(context=self.context) vnf_resource.vnf_instance_id = vnf_instance.id - vnf_resource.resource_name = "curry-ns,curry-endpoint-test001" + vnf_resource.resource_name = "curry-endpoint-test001" vnf_resource.resource_type = "v1,Pod" vnf_resource.resource_identifier = '' vnf_resource.resource_status = '' @@ -647,9 +647,11 @@ class TestKubernetes(base.TestCase): vnf_software_images, instantiate_vnf_req, vnf_package_path) + @mock.patch('tacker.objects.vnf_instance.VnfInstance.save') @mock.patch.object(vnf_package.VnfPackage, "get_by_id") @mock.patch.object(vnf_package_vnfd.VnfPackageVnfd, "get_by_id") - def test_pre_instantiation_vnf(self, mock_vnfd_by_id, mock_vnf_by_id): + def test_pre_instantiation_vnf( + self, mock_vnfd_by_id, mock_vnf_by_id, mock_save): vnf_instance = fd_utils.get_vnf_instance_object() vim_connection_info = None vnf_software_images = None @@ -686,8 +688,7 @@ class TestKubernetes(base.TestCase): vnf_software_images, instantiate_vnf_req, vnf_package_path) for item in new_k8s_objs.values(): - self.assertEqual(item[0].resource_name, 'curry-ns,' - 'curry-endpoint-test001') + self.assertEqual(item[0].resource_name, 'curry-endpoint-test001') self.assertEqual(item[0].resource_type, 'v1,Pod') def _delete_single_vnf_resource(self, mock_vnf_resource_list, @@ -696,6 +697,7 @@ class TestKubernetes(base.TestCase): vnf_id = 'fake_vnf_id' vnf_instance = fd_utils.get_vnf_instance_object() vnf_instance_id = vnf_instance.id + vnf_instance.vnf_metadata['namespace'] = "default" vnf_resource = models.VnfResource() vnf_resource.vnf_instance_id = vnf_instance_id vnf_resource.resource_name = resource_name @@ -714,7 +716,7 @@ class TestKubernetes(base.TestCase): terminate_vnf_req = objects.TerminateVnfRequest( termination_type=fields.VnfInstanceTerminationType.GRACEFUL, graceful_termination_timeout=5) - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,Pod" mock_delete_namespaced_pod.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -730,7 +732,7 @@ class TestKubernetes(base.TestCase): mock_delete_namespaced_pod): terminate_vnf_req = objects.TerminateVnfRequest( termination_type=fields.VnfInstanceTerminationType.FORCEFUL) - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,Pod" mock_delete_namespaced_pod.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -744,7 +746,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_pod_terminate_vnfreq_none(self, mock_vnf_resource_list, mock_delete_namespaced_pod): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,Pod" mock_delete_namespaced_pod.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -758,7 +760,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_service(self, mock_vnf_resource_list, mock_delete_namespaced_service): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,Service" mock_delete_namespaced_service.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -772,7 +774,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_secret(self, mock_vnf_resource_list, mock_delete_namespaced_secret): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,Secret" mock_delete_namespaced_secret.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -786,7 +788,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_config_map(self, mock_vnf_resource_list, mock_delete_namespaced_config_map): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,ConfigMap" mock_delete_namespaced_config_map.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -801,7 +803,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_persistent_volume_claim(self, mock_vnf_resource_list, mock_delete_namespaced_persistent_volume_claim): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,PersistentVolumeClaim" mock_delete_namespaced_persistent_volume_claim.return_value = \ client.V1Status() @@ -816,7 +818,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_limit_range(self, mock_vnf_resource_list, mock_delete_namespaced_limit_range): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,LimitRange" mock_delete_namespaced_limit_range.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -830,7 +832,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_pod_template(self, mock_vnf_resource_list, mock_delete_namespaced_pod_template): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,PodTemplate" mock_delete_namespaced_pod_template.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -844,7 +846,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_namespace(self, mock_vnf_resource_list, mock_delete_namespace): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "v1,Namespace" mock_delete_namespace.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -858,7 +860,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_persistent_volume(self, mock_vnf_resource_list, mock_delete_persistent_volume): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "v1,PersistentVolume" mock_delete_persistent_volume.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -872,7 +874,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_resource_quota(self, mock_vnf_resource_list, mock_delete_namespaced_resource_quota): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,ResourceQuota" mock_delete_namespaced_resource_quota.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -886,7 +888,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_service_account(self, mock_vnf_resource_list, mock_delete_namespaced_service_account): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,ServiceAccount" mock_delete_namespaced_service_account.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -900,7 +902,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_api_service(self, mock_vnf_resource_list, mock_delete_api_service): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "apiregistration.k8s.io/v1,APIService" mock_delete_api_service.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -914,7 +916,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_daemon_set(self, mock_vnf_resource_list, mock_delete_namespaced_daemon_set): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "apps/v1,DaemonSet" mock_delete_namespaced_daemon_set.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -928,7 +930,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_deployment(self, mock_vnf_resource_list, mock_delete_namespaced_deployment): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "apps/v1,Deployment" mock_delete_namespaced_deployment.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -942,7 +944,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_replica_set(self, mock_vnf_resource_list, mock_delete_namespaced_replica_set): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "apps/v1,ReplicaSet" mock_delete_namespaced_replica_set.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -964,7 +966,7 @@ class TestKubernetes(base.TestCase): mock_read_namespaced_stateful_set, mock_list_namespaced_persistent_volume_claim, mock_delete_namespaced_persistent_volume_claim): - resource_name = "curryns,curry-test001" + resource_name = "curry-test001" resource_type = "apps/v1,StatefulSet" mock_delete_namespaced_stateful_set.return_value = client.V1Status() mock_delete_namespaced_persistent_volume_claim.return_value = \ @@ -997,7 +999,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_controller_revision(self, mock_vnf_resource_list, mock_delete_namespaced_controller_revision): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "apps/v1,ControllerRevision" mock_delete_namespaced_controller_revision.return_value = \ client.V1Status() @@ -1013,7 +1015,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_horizontal_pod_autoscaler(self, mock_vnf_resource_list, mock_delete_namespaced_horizontal_pod_autoscaler): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "autoscaling/v1,HorizontalPodAutoscaler" mock_delete_namespaced_horizontal_pod_autoscaler.return_value = \ client.V1Status() @@ -1028,7 +1030,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_job(self, mock_vnf_resource_list, mock_delete_namespaced_job): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "batch/v1,Job" mock_delete_namespaced_job.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -1042,7 +1044,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_lease(self, mock_vnf_resource_list, mock_delete_namespaced_lease): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "coordination.k8s.io/v1,Lease" mock_delete_namespaced_lease.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -1057,7 +1059,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_network_policy(self, mock_vnf_resource_list, mock_delete_namespaced_network_policy): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "networking.k8s.io/v1,NetworkPolicy" mock_delete_namespaced_network_policy.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -1072,7 +1074,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_cluster_role(self, mock_vnf_resource_list, mock_delete_cluster_role): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "rbac.authorization.k8s.io/v1,ClusterRole" mock_delete_cluster_role.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -1087,7 +1089,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_cluster_role_binding(self, mock_vnf_resource_list, mock_delete_cluster_role_binding): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "rbac.authorization.k8s.io/v1,ClusterRoleBinding" mock_delete_cluster_role_binding.return_value = \ client.V1Status() @@ -1103,7 +1105,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_role(self, mock_vnf_resource_list, mock_delete_namespaced_role): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "rbac.authorization.k8s.io/v1,Role" mock_delete_namespaced_role.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -1118,7 +1120,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_role_binding(self, mock_vnf_resource_list, mock_delete_namespaced_role_binding): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "rbac.authorization.k8s.io/v1,RoleBinding" mock_delete_namespaced_role_binding.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -1132,7 +1134,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_priority_class(self, mock_vnf_resource_list, mock_delete_priority_class): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "scheduling.k8s.io/v1,PriorityClass" mock_delete_priority_class.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -1146,7 +1148,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_storage_class(self, mock_vnf_resource_list, mock_delete_storage_class): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "storage.k8s.io/v1,StorageClass" mock_delete_storage_class.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -1160,7 +1162,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_volume_attachment(self, mock_vnf_resource_list, mock_delete_volume_attachment): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "storage.k8s.io/v1,VolumeAttachment" mock_delete_volume_attachment.return_value = client.V1Status() self._delete_single_vnf_resource( @@ -1182,20 +1184,21 @@ class TestKubernetes(base.TestCase): vnf_id = 'fake_vnf_id' vnf_instance = fd_utils.get_vnf_instance_object() vnf_instance_id = vnf_instance.id + vnf_instance.vnf_metadata['namespace'] = "default" terminate_vnf_req = objects.TerminateVnfRequest( termination_type=fields.VnfInstanceTerminationType.GRACEFUL, graceful_termination_timeout=5) vnf_resource1 = models.VnfResource() vnf_resource1.vnf_instance_id = vnf_instance_id - vnf_resource1.resource_name = ",fake_name1" + vnf_resource1.resource_name = "fake_name1" vnf_resource1.resource_type = "storage.k8s.io/v1,StorageClass" vnf_resource2 = models.VnfResource() vnf_resource2.vnf_instance_id = vnf_instance_id - vnf_resource2.resource_name = ",fake_name2" + vnf_resource2.resource_name = "fake_name2" vnf_resource2.resource_type = "v1,PersistentVolume" vnf_resource3 = models.VnfResource() vnf_resource3.vnf_instance_id = vnf_instance_id - vnf_resource3.resource_name = "fake_namespace,fake_name3" + vnf_resource3.resource_name = "fake_name3" vnf_resource3.resource_type = "v1,PersistentVolumeClaim" mock_vnf_resource_list.return_value = \ [vnf_resource1, vnf_resource2, vnf_resource3] @@ -1217,7 +1220,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_pod_api_fail(self, mock_vnf_resource_list, mock_delete_namespaced_pod): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,Pod" mock_delete_namespaced_pod.side_effect = Exception() self._delete_single_vnf_resource( @@ -1236,7 +1239,7 @@ class TestKubernetes(base.TestCase): mock_delete_namespaced_stateful_set, mock_read_namespaced_stateful_set, mock_list_namespaced_persistent_volume_claim): - resource_name = "curryns,curry-test001" + resource_name = "curry-test001" resource_type = "apps/v1,StatefulSet" mock_delete_namespaced_stateful_set.return_value = client.V1Status() stateful_set_obj = fakes.fake_v1_stateful_set() @@ -1257,7 +1260,7 @@ class TestKubernetes(base.TestCase): def test_delete_stateful_set_read_sfs_fail(self, mock_vnf_resource_list, mock_delete_namespaced_stateful_set, mock_read_namespaced_stateful_set): - resource_name = "curryns,curry-test001" + resource_name = "curry-test001" resource_type = "apps/v1,StatefulSet" mock_delete_namespaced_stateful_set.return_value = client.V1Status() mock_read_namespaced_stateful_set.side_effect = Exception() @@ -1275,6 +1278,7 @@ class TestKubernetes(base.TestCase): vnf_instance_id = '4a4c2d44-8a52-4895-9a75-9d1c76c3e738' vnf_instance = fd_utils.get_vnf_instance_object() vnf_instance.id = vnf_instance_id + vnf_instance.vnf_metadata['namespace'] = "default" vnf_resource = models.VnfResource() vnf_resource.vnf_instance_id = vnf_instance_id vnf_resource.resource_name = resource_name @@ -1290,7 +1294,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_pod(self, mock_vnf_resource_list, mock_read_namespaced_pod): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,Pod" mock_read_namespaced_pod.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1303,7 +1307,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_service(self, mock_vnf_resource_list, mock_read_namespaced_service): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,Service" mock_read_namespaced_service.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1316,7 +1320,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_secret(self, mock_vnf_resource_list, mock_read_namespaced_secret): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,Secret" mock_read_namespaced_secret.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1329,7 +1333,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_config_map(self, mock_vnf_resource_list, mock_read_namespaced_config_map): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,ConfigMap" mock_read_namespaced_config_map.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1343,7 +1347,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_persistent_volume_claim(self, mock_vnf_resource_list, mock_read_namespaced_persistent_volume_claim): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,PersistentVolumeClaim" mock_read_namespaced_persistent_volume_claim.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1356,7 +1360,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_limit_range(self, mock_vnf_resource_list, mock_read_namespaced_limit_range): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,LimitRange" mock_read_namespaced_limit_range.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1369,7 +1373,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_pod_template(self, mock_vnf_resource_list, mock_read_namespaced_pod_template): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,PodTemplate" mock_read_namespaced_pod_template.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1382,7 +1386,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_namespace(self, mock_vnf_resource_list, mock_read_namespace): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "v1,Namespace" mock_read_namespace.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1395,7 +1399,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_persistent_volume(self, mock_vnf_resource_list, mock_read_persistent_volume): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "v1,PersistentVolume" mock_read_persistent_volume.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1408,7 +1412,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_resource_quota(self, mock_vnf_resource_list, mock_read_namespaced_resource_quota): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,ResourceQuota" mock_read_namespaced_resource_quota.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1421,7 +1425,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_service_account(self, mock_vnf_resource_list, mock_read_namespaced_service_account): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,ServiceAccount" mock_read_namespaced_service_account.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1434,7 +1438,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_api_service(self, mock_vnf_resource_list, mock_read_api_service): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "apiregistration.k8s.io/v1,APIService" mock_read_api_service.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1447,7 +1451,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_daemon_set(self, mock_vnf_resource_list, mock_read_namespaced_daemon_set): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "apps/v1,DaemonSet" mock_read_namespaced_daemon_set.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1460,7 +1464,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_deployment(self, mock_vnf_resource_list, mock_read_namespaced_deployment): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "apps/v1,Deployment" mock_read_namespaced_deployment.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1473,7 +1477,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_replica_set(self, mock_vnf_resource_list, mock_read_namespaced_replica_set): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "apps/v1,ReplicaSet" mock_read_namespaced_replica_set.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1486,7 +1490,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_stateful_set(self, mock_vnf_resource_list, mock_read_namespaced_stateful_set): - resource_name = "curryns,curry-test001" + resource_name = "curry-test001" resource_type = "apps/v1,StatefulSet" mock_read_namespaced_stateful_set.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1500,7 +1504,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_controller_revision(self, mock_vnf_resource_list, mock_read_namespaced_controller_revision): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "apps/v1,ControllerRevision" mock_read_namespaced_controller_revision.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1515,7 +1519,7 @@ class TestKubernetes(base.TestCase): def test_delete_wait_horizontal_pod_autoscaler(self, mock_vnf_resource_list, mock_read_namespaced_horizontal_pod_autoscaler): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "autoscaling/v1,HorizontalPodAutoscaler" mock_read_namespaced_horizontal_pod_autoscaler.side_effect = \ Exception() @@ -1529,7 +1533,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_job(self, mock_vnf_resource_list, mock_read_namespaced_job): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "batch/v1,Job" mock_read_namespaced_job.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1542,7 +1546,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_lease(self, mock_vnf_resource_list, mock_read_namespaced_lease): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "coordination.k8s.io/v1,Lease" mock_read_namespaced_lease.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1556,7 +1560,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_network_policy(self, mock_vnf_resource_list, mock_read_namespaced_network_policy): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "networking.k8s.io/v1,NetworkPolicy" mock_read_namespaced_network_policy.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1570,7 +1574,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_cluster_role(self, mock_vnf_resource_list, mock_read_cluster_role): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "rbac.authorization.k8s.io/v1,ClusterRole" mock_read_cluster_role.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1584,7 +1588,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_cluster_role_binding(self, mock_vnf_resource_list, mock_read_cluster_role_binding): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "rbac.authorization.k8s.io/v1,ClusterRoleBinding" mock_read_cluster_role_binding.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1598,7 +1602,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_role(self, mock_vnf_resource_list, mock_read_namespaced_role): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "rbac.authorization.k8s.io/v1,Role" mock_read_namespaced_role.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1612,7 +1616,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_role_binding(self, mock_vnf_resource_list, mock_read_namespaced_role_binding): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "rbac.authorization.k8s.io/v1,RoleBinding" mock_read_namespaced_role_binding.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1625,7 +1629,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_priority_class(self, mock_vnf_resource_list, mock_read_priority_class): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "scheduling.k8s.io/v1,PriorityClass" mock_read_priority_class.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1638,7 +1642,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_storage_class(self, mock_vnf_resource_list, mock_read_storage_class): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "storage.k8s.io/v1,StorageClass" mock_read_storage_class.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1651,7 +1655,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_volume_attachment(self, mock_vnf_resource_list, mock_read_volume_attachment): - resource_name = ",fake_name" + resource_name = "fake_name" resource_type = "storage.k8s.io/v1,VolumeAttachment" mock_read_volume_attachment.side_effect = Exception() self._delete_wait_single_vnf_resource( @@ -1664,7 +1668,7 @@ class TestKubernetes(base.TestCase): @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_delete_wait_retry(self, mock_vnf_resource_list, mock_read_namespaced_pod): - resource_name = "fake_namespace,fake_name" + resource_name = "fake_name" resource_type = "v1,Pod" mock_read_namespaced_pod.return_value = client.V1Status() self._delete_wait_single_vnf_resource( @@ -1789,12 +1793,7 @@ class TestKubernetes(base.TestCase): 'deploy_kubernetes_objects') def test_instantiate_vnf_without_target_k8s_files( self, mock_deploy_kubernetes_objects): - vnf = { - 'vnfd': { - 'attributes': { - 'vnfd': { - 'tosca_definitions_version': 'tosca_simple_yaml_1_0'} - }}} + vnf = objects.VnfInstance(vnf_metadata={'namespace': 'default'}) vim_connection_info = objects.VimConnectionInfo( access_info={'auth_url': 'http://fake-url/identity/v3'}) vnfd_dict = fakes.fake_vnf_dict() @@ -1829,12 +1828,7 @@ class TestKubernetes(base.TestCase): mock_read_namespaced_deployment, mock_deploy_k8s, mock_get_k8s_objs_from_yaml): - vnf = { - 'vnfd': { - 'attributes': { - 'vnfd': { - 'tosca_definitions_version': 'tosca_simple_yaml_1_0'} - }}} + vnf = objects.VnfInstance(vnf_metadata={'namespace': 'default'}) vim_connection_info = objects.VimConnectionInfo( access_info={'auth_url': 'http://fake-url/identity/v3'}) deployment_obj = fakes.fake_v1_deployment() @@ -2093,6 +2087,7 @@ class TestKubernetes(base.TestCase): fakes.get_fake_pod_info(kind='Pod', name='vdu2')]) instantiate_vnf_req = objects.InstantiateVnfRequest( additional_params={'lcm-kubernetes-def-files': ["dummy.yaml"]}) + self.vnf_instance.vnf_metadata['namespace'] = 'default' self.kubernetes.post_vnf_instantiation( context=self.context, vnf_instance=self.vnf_instance, @@ -2221,10 +2216,11 @@ class TestKubernetes(base.TestCase): fakes.get_vnf_resource_list(kind='Deployment') scale_status = objects.ScaleInfo( aspect_id='vdu1_aspect', scale_level=1) - mock_vnf_instance_get_by_id.return_value = ( - vnflcm_fakes.return_vnf_instance( - fields.VnfInstanceState.INSTANTIATED, - scale_status=scale_status)) + scale_vnf_instance = vnflcm_fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED, + scale_status=scale_status) + scale_vnf_instance.vnf_metadata['namespace'] = "default" + mock_vnf_instance_get_by_id.return_value = scale_vnf_instance mock_read_namespaced_deployment_scale.return_value = \ client.V1Scale(spec=client.V1ScaleSpec(replicas=2), status=client.V1ScaleStatus(replicas=2)) @@ -2251,10 +2247,11 @@ class TestKubernetes(base.TestCase): fakes.get_vnf_resource_list(kind='StatefulSet') scale_status = objects.ScaleInfo( aspect_id='vdu1_aspect', scale_level=1) - mock_vnf_instance_get_by_id.return_value = ( - vnflcm_fakes.return_vnf_instance( - fields.VnfInstanceState.INSTANTIATED, - scale_status=scale_status)) + scale_vnf_instance = vnflcm_fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED, + scale_status=scale_status) + scale_vnf_instance.vnf_metadata['namespace'] = "default" + mock_vnf_instance_get_by_id.return_value = scale_vnf_instance mock_read_namespaced_stateful_set_scale.return_value = \ client.V1Scale(spec=client.V1ScaleSpec(replicas=2), status=client.V1ScaleStatus(replicas=2)) @@ -2281,10 +2278,11 @@ class TestKubernetes(base.TestCase): fakes.get_vnf_resource_list(kind='ReplicaSet') scale_status = objects.ScaleInfo( aspect_id='vdu1_aspect', scale_level=1) - mock_vnf_instance_get_by_id.return_value = ( - vnflcm_fakes.return_vnf_instance( - fields.VnfInstanceState.INSTANTIATED, - scale_status=scale_status)) + scale_vnf_instance = vnflcm_fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED, + scale_status=scale_status) + scale_vnf_instance.vnf_metadata['namespace'] = "default" + mock_vnf_instance_get_by_id.return_value = scale_vnf_instance mock_read_namespaced_replica_set_scale.return_value = \ client.V1Scale(spec=client.V1ScaleSpec(replicas=2), status=client.V1ScaleStatus(replicas=2)) @@ -2311,10 +2309,11 @@ class TestKubernetes(base.TestCase): fakes.get_vnf_resource_list(kind='Deployment') scale_status = objects.ScaleInfo( aspect_id='vdu1_aspect', scale_level=1) - mock_vnf_instance_get_by_id.return_value = ( - vnflcm_fakes.return_vnf_instance( - fields.VnfInstanceState.INSTANTIATED, - scale_status=scale_status)) + scale_vnf_instance = vnflcm_fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED, + scale_status=scale_status) + scale_vnf_instance.vnf_metadata['namespace'] = "default" + mock_vnf_instance_get_by_id.return_value = scale_vnf_instance mock_read_namespaced_deployment_scale.return_value = \ client.V1Scale(spec=client.V1ScaleSpec(replicas=1), status=client.V1ScaleStatus(replicas=1)) @@ -2335,9 +2334,10 @@ class TestKubernetes(base.TestCase): policy = fakes.get_scale_policy(type='in') mock_vnf_resource_list.return_value = \ fakes.get_vnf_resource_list(kind='Depoyment', name='other_name') - mock_vnf_instance_get_by_id.return_value = ( - vnflcm_fakes.return_vnf_instance( - fields.VnfInstanceState.INSTANTIATED)) + scale_vnf_instance = vnflcm_fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED) + scale_vnf_instance.vnf_metadata['namespace'] = "default" + mock_vnf_instance_get_by_id.return_value = scale_vnf_instance self.assertRaises(vnfm.CNFScaleFailed, self.kubernetes.scale, self.context, None, @@ -2350,9 +2350,10 @@ class TestKubernetes(base.TestCase): policy = fakes.get_scale_policy(type='in') mock_vnf_resource_list.return_value = \ fakes.get_vnf_resource_list(kind='Pod') - mock_vnf_instance_get_by_id.return_value = ( - vnflcm_fakes.return_vnf_instance( - fields.VnfInstanceState.INSTANTIATED)) + scale_vnf_instance = vnflcm_fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED) + scale_vnf_instance.vnf_metadata['namespace'] = "default" + mock_vnf_instance_get_by_id.return_value = scale_vnf_instance self.assertRaises(vnfm.CNFScaleFailed, self.kubernetes.scale, self.context, None, @@ -2369,10 +2370,11 @@ class TestKubernetes(base.TestCase): fakes.get_vnf_resource_list(kind='Deployment') scale_status = objects.ScaleInfo( aspect_id='vdu1_aspect', scale_level=1) - mock_vnf_instance_get_by_id.return_value = ( - vnflcm_fakes.return_vnf_instance( - fields.VnfInstanceState.INSTANTIATED, - scale_status=scale_status)) + scale_vnf_instance = vnflcm_fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED, + scale_status=scale_status) + scale_vnf_instance.vnf_metadata['namespace'] = "default" + mock_vnf_instance_get_by_id.return_value = scale_vnf_instance mock_read_namespaced_deployment_scale.return_value = \ client.V1Scale(spec=client.V1ScaleSpec(replicas=1), status=client.V1ScaleStatus(replicas=1)) @@ -2392,10 +2394,11 @@ class TestKubernetes(base.TestCase): fakes.get_vnf_resource_list(kind='Deployment') scale_status = objects.ScaleInfo( aspect_id='vdu1_aspect', scale_level=1) - mock_vnf_instance_get_by_id.return_value = ( - vnflcm_fakes.return_vnf_instance( - fields.VnfInstanceState.INSTANTIATED, - scale_status=scale_status)) + scale_vnf_instance = vnflcm_fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED, + scale_status=scale_status) + scale_vnf_instance.vnf_metadata['namespace'] = "default" + mock_vnf_instance_get_by_id.return_value = scale_vnf_instance mock_read_namespaced_deployment_scale.return_value = \ client.V1Scale(spec=client.V1ScaleSpec(replicas=3), status=client.V1ScaleStatus(replicas=3)) @@ -2506,12 +2509,14 @@ class TestKubernetes(base.TestCase): mock_read_namespaced_horizontal_pod_autoscaler.assert_called_once() mock_patch_namespaced_deployment_scale.assert_called_once() + @mock.patch.object(objects.VnfInstance, "get_by_id") @mock.patch.object(client.AppsV1Api, 'read_namespaced_deployment_scale') @mock.patch.object(client.CoreV1Api, 'list_namespaced_pod') @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_scale_wait_deployment(self, mock_vnf_resource_list, mock_list_namespaced_pod, - mock_read_namespaced_deployment_scale): + mock_read_namespaced_deployment_scale, + mock_vnf_instance): policy = fakes.get_scale_policy(type='out') mock_vnf_resource_list.return_value = \ fakes.get_vnf_resource_list(kind='Deployment') @@ -2528,12 +2533,14 @@ class TestKubernetes(base.TestCase): last_event_id=None) mock_list_namespaced_pod.assert_called_once() + @mock.patch.object(objects.VnfInstance, "get_by_id") @mock.patch.object(client.AppsV1Api, 'read_namespaced_stateful_set_scale') @mock.patch.object(client.CoreV1Api, 'list_namespaced_pod') @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_scale_wait_stateful_set(self, mock_vnf_resource_list, mock_list_namespaced_pod, - mock_read_namespaced_stateful_set_scale): + mock_read_namespaced_stateful_set_scale, + mock_vnf_instance): policy = fakes.get_scale_policy(type='out') mock_vnf_resource_list.return_value = \ fakes.get_vnf_resource_list(kind='StatefulSet') @@ -2550,12 +2557,14 @@ class TestKubernetes(base.TestCase): last_event_id=None) mock_list_namespaced_pod.assert_called_once() + @mock.patch.object(objects.VnfInstance, "get_by_id") @mock.patch.object(client.AppsV1Api, 'read_namespaced_replica_set_scale') @mock.patch.object(client.CoreV1Api, 'list_namespaced_pod') @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_scale_wait_replica_set(self, mock_vnf_resource_list, mock_list_namespaced_pod, - mock_read_namespaced_replica_set_scale): + mock_read_namespaced_replica_set_scale, + mock_vnf_instance): policy = fakes.get_scale_policy(type='out') mock_vnf_resource_list.return_value = \ fakes.get_vnf_resource_list(kind='ReplicaSet') @@ -2572,8 +2581,10 @@ class TestKubernetes(base.TestCase): last_event_id=None) mock_list_namespaced_pod.assert_called_once() + @mock.patch.object(objects.VnfInstance, "get_by_id") @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") - def test_scale_wait_target_not_found(self, mock_vnf_resource_list): + def test_scale_wait_target_not_found( + self, mock_vnf_resource_list, mock_vnf_instance): policy = fakes.get_scale_policy(type='out') mock_vnf_resource_list.return_value = \ fakes.get_vnf_resource_list(kind='Depoyment', name='other_name') @@ -2582,12 +2593,14 @@ class TestKubernetes(base.TestCase): self.context, None, utils.get_vim_auth_obj(), policy, None, None) + @mock.patch.object(objects.VnfInstance, "get_by_id") @mock.patch.object(client.AppsV1Api, 'read_namespaced_deployment_scale') @mock.patch.object(client.CoreV1Api, 'list_namespaced_pod') @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_scale_wait_retry_over(self, mock_vnf_resource_list, mock_list_namespaced_pod, - mock_read_namespaced_deployment_scale): + mock_read_namespaced_deployment_scale, + mock_vnf_instance): policy = fakes.get_scale_policy(type='out') mock_vnf_resource_list.return_value = \ fakes.get_vnf_resource_list(kind='Deployment') @@ -2603,12 +2616,14 @@ class TestKubernetes(base.TestCase): self.context, None, utils.get_vim_auth_obj(), policy, None, None) + @mock.patch.object(objects.VnfInstance, "get_by_id") @mock.patch.object(client.AppsV1Api, 'read_namespaced_deployment_scale') @mock.patch.object(client.CoreV1Api, 'list_namespaced_pod') @mock.patch.object(objects.VnfResourceList, "get_by_vnf_instance_id") def test_scale_wait_status_unknown(self, mock_vnf_resource_list, mock_list_namespaced_pod, - mock_read_namespaced_deployment_scale): + mock_read_namespaced_deployment_scale, + mock_vnf_instance): policy = fakes.get_scale_policy(type='out') mock_vnf_resource_list.return_value = \ fakes.get_vnf_resource_list(kind='Deployment') @@ -2692,10 +2707,11 @@ class TestKubernetes(base.TestCase): "SCALE_OUT", "vdu1_aspect", 1, "False") scale_status = objects.ScaleInfo( aspect_id='vdu1_aspect', scale_level=1) - mock_vnf_instance_get_by_id.return_value = \ - vnflcm_fakes.return_vnf_instance( - fields.VnfInstanceState.INSTANTIATED, - scale_status=scale_status) + scale_vnf_instance = vnflcm_fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED, + scale_status=scale_status) + scale_vnf_instance.vnf_metadata['namespace'] = "default" + mock_vnf_instance_get_by_id.return_value = scale_vnf_instance mock_vnf_resource_list.return_value = \ fakes.get_vnf_resource_list(kind='Deployment', name='vdu1') mock_vnf_package_vnfd_get_by_id.return_value = \ @@ -2733,10 +2749,11 @@ class TestKubernetes(base.TestCase): vnf_info['vnf_lcm_op_occ'] = vnflcm_fakes.vnflcm_scale_out_cnf() scale_status = objects.ScaleInfo( aspect_id='vdu1_aspect', scale_level=1) - mock_vnf_instance_get_by_id.return_value = \ - vnflcm_fakes.return_vnf_instance( - fields.VnfInstanceState.INSTANTIATED, - scale_status=scale_status) + scale_vnf_instance = vnflcm_fakes.return_vnf_instance( + fields.VnfInstanceState.INSTANTIATED, + scale_status=scale_status) + scale_vnf_instance.vnf_metadata['namespace'] = "default" + mock_vnf_instance_get_by_id.return_value = scale_vnf_instance mock_vnf_resource_list.return_value = \ fakes.get_vnf_resource_list(kind='Deployment', name='vdu1') mock_vnf_package_vnfd_get_by_id.return_value = \ @@ -2768,10 +2785,10 @@ class TestKubernetes(base.TestCase): vnf_resource_list = [] vnf_resource_list.append(models.VnfResource()) vnf_resource_list[0].vnf_instance_id = self.vnf_instance.id - vnf_resource_list[0].resource_name = "default,vdu0" + vnf_resource_list[0].resource_name = "vdu0" vnf_resource_list[0].resource_type = "apps/v1,Deployment" vnf_resource_list.append(copy.deepcopy(vnf_resource_list[0])) - vnf_resource_list[1].resource_name = "default,vdu1" + vnf_resource_list[1].resource_name = "vdu1" mock_vnf_resource_list.return_value = vnf_resource_list vnfc_resource_info = [] vnfc_resource_info.append( @@ -2834,7 +2851,7 @@ class TestKubernetes(base.TestCase): vnflcm_fakes.return_vnf_package_vnfd() vnf_resource = models.VnfResource() vnf_resource.vnf_instance_id = self.vnf_instance.id - vnf_resource.resource_name = "default,vdu1" + vnf_resource.resource_name = "vdu1" vnf_resource.resource_type = "apps/v1,Deployment" mock_vnf_resource_list.return_value = [vnf_resource] vnfc_resource_info = [] @@ -2888,7 +2905,7 @@ class TestKubernetes(base.TestCase): vnflcm_fakes.return_vnf_package_vnfd() vnf_resource = models.VnfResource() vnf_resource.vnf_instance_id = self.vnf_instance.id - vnf_resource.resource_name = "default,vdu1" + vnf_resource.resource_name = "vdu1" vnf_resource.resource_type = "apps/v1,Deployment" mock_vnf_resource_list.return_value = [vnf_resource] vnfc_resource_info = [] @@ -2914,6 +2931,7 @@ class TestKubernetes(base.TestCase): client.rest.ApiException(status=500) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info(rsc_kind='Pod') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ [vnfc_resource_info_obj] @@ -2941,6 +2959,7 @@ class TestKubernetes(base.TestCase): mock_delete_namespaced_pod.return_value = client.V1Status() vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info(rsc_kind='Pod') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ [vnfc_resource_info_obj] @@ -2973,6 +2992,7 @@ class TestKubernetes(base.TestCase): mock_create_namespaced_pod.return_value = client.V1Status() vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info(rsc_kind='Pod') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ [vnfc_resource_info_obj] @@ -3004,6 +3024,7 @@ class TestKubernetes(base.TestCase): mock_create_namespaced_pod.return_value = client.V1Status() vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info(rsc_kind='Pod') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ [vnfc_resource_info_obj] @@ -3029,6 +3050,7 @@ class TestKubernetes(base.TestCase): mock_delete_namespaced_pod.return_value = client.V1Status() vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='Deployment') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ @@ -3056,6 +3078,7 @@ class TestKubernetes(base.TestCase): client.rest.ApiException(status=404) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='Deployment') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ @@ -3085,6 +3108,7 @@ class TestKubernetes(base.TestCase): client.rest.ApiException(status=500) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='Deployment') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ @@ -3107,6 +3131,7 @@ class TestKubernetes(base.TestCase): fakes.get_fake_pod_info(kind='ReplicaSet')]) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='ReplicaSet') # change Kubernetes resource kind to Job (for illegal route) @@ -3144,6 +3169,7 @@ class TestKubernetes(base.TestCase): fields.VnfInstanceState.INSTANTIATED) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info = [] vnfc_resource_info.append(fakes.fake_vnfc_resource_info( vdu_id='VDU1', rsc_kind='Deployment', rsc_name='fake_name', @@ -3181,6 +3207,7 @@ class TestKubernetes(base.TestCase): client.rest.ApiException(status=500) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info(rsc_kind='Pod') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ [vnfc_resource_info_obj] @@ -3201,6 +3228,7 @@ class TestKubernetes(base.TestCase): fakes.get_fake_pod_info(kind='Pod')]) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info(rsc_kind='Pod') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ [vnfc_resource_info_obj] @@ -3225,6 +3253,7 @@ class TestKubernetes(base.TestCase): status=client.V1ScaleStatus(replicas=1)) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='Deployment') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ @@ -3245,6 +3274,7 @@ class TestKubernetes(base.TestCase): fakes.get_fake_pod_info(kind='DaemonSet')]) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='DaemonSet') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ @@ -3270,6 +3300,7 @@ class TestKubernetes(base.TestCase): status=client.V1ScaleStatus(replicas=1)) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='StatefulSet') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ @@ -3295,6 +3326,7 @@ class TestKubernetes(base.TestCase): status=client.V1ScaleStatus(replicas=1)) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='ReplicaSet') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ @@ -3321,6 +3353,7 @@ class TestKubernetes(base.TestCase): status=client.V1ScaleStatus(replicas=1)) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_list = [ fakes.fake_vnfc_resource_info(rsc_kind='Deployment'), fakes.fake_vnfc_resource_info( @@ -3343,6 +3376,7 @@ class TestKubernetes(base.TestCase): mock_list_namespaced_pod): vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='Deployment', pod_name="POD_NOT_FOUND") vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ @@ -3368,6 +3402,7 @@ class TestKubernetes(base.TestCase): status=client.V1ScaleStatus(replicas=1)) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = \ fakes.fake_vnfc_resource_info(rsc_kind='Deployment') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ @@ -3394,6 +3429,7 @@ class TestKubernetes(base.TestCase): status=client.V1ScaleStatus(replicas=1)) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = \ fakes.fake_vnfc_resource_info(rsc_kind='Deployment') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ @@ -3421,6 +3457,7 @@ class TestKubernetes(base.TestCase): status=client.V1ScaleStatus(replicas=1)) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = \ fakes.fake_vnfc_resource_info(rsc_kind='Deployment') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ @@ -3442,6 +3479,7 @@ class TestKubernetes(base.TestCase): client.rest.ApiException(status=500) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='Deployment') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ @@ -3469,6 +3507,7 @@ class TestKubernetes(base.TestCase): name='fake_name', pod_name="fake_name-1234567890-actp3")]) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_list = [ fakes.fake_vnfc_resource_info(rsc_kind='Deployment', rsc_name='fake_name', pod_name="fake_name-1234567890-strp1"), @@ -3509,6 +3548,7 @@ class TestKubernetes(base.TestCase): name='fake_name', pod_name="fake_name-1234567890-abcdf")]) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_list = [ fakes.fake_vnfc_resource_info(rsc_kind='Deployment', rsc_name='fake_name', pod_name="POD_NOT_FOUND")] @@ -3535,6 +3575,7 @@ class TestKubernetes(base.TestCase): name='fake_name', pod_name="fake_name-12346")]) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='DaemonSet', rsc_name='fake_name') @@ -3564,6 +3605,7 @@ class TestKubernetes(base.TestCase): name='fake_name')]) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='Deployment', rsc_name='fake_name') @@ -3594,6 +3636,7 @@ class TestKubernetes(base.TestCase): fakes.get_fake_pod_info(kind='DaemonSet')]) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='DaemonSet') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info = \ @@ -3614,6 +3657,7 @@ class TestKubernetes(base.TestCase): fakes.get_fake_pod_info(kind='Pod')]) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='Pod') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info =\ @@ -3634,6 +3678,7 @@ class TestKubernetes(base.TestCase): fakes.get_fake_pod_info(kind='StatefulSet')]) vnf_instance_obj = vnflcm_fakes.return_vnf_instance( fields.VnfInstanceState.INSTANTIATED) + vnf_instance_obj.vnf_metadata['namespace'] = "default" vnfc_resource_info_obj = fakes.fake_vnfc_resource_info( rsc_kind='StatefulSet') vnf_instance_obj.instantiated_vnf_info.vnfc_resource_info =\ diff --git a/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_kubernetes_driver_helm.py b/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_kubernetes_driver_helm.py index 2d085b85e..969305656 100644 --- a/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_kubernetes_driver_helm.py +++ b/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_kubernetes_driver_helm.py @@ -161,10 +161,12 @@ class TestKubernetesHelm(base.TestCase): self.helm_client.get_value, 'fake_release_name', '', 'foo.bar') + @mock.patch('tacker.objects.vnf_instance.VnfInstance.save') @mock.patch.object(objects.VnfPackageVnfd, "get_by_id") @mock.patch('tacker.vnflcm.utils._get_vnfd_dict') def test_pre_instantiation_vnf_helm(self, mock_vnfd_dict, - mock_vnf_package_vnfd_get_by_id): + mock_vnf_package_vnfd_get_by_id, + mock_save): vnf_instance = fd_utils.get_vnf_instance_object() vim_connection_info = fakes.fake_vim_connection_info_with_extra() vnf_software_images = None @@ -179,10 +181,12 @@ class TestKubernetesHelm(base.TestCase): instantiate_vnf_req, vnf_package_path) self.assertEqual(vnf_resources, {}) + @mock.patch('tacker.objects.vnf_instance.VnfInstance.save') @mock.patch.object(objects.VnfPackageVnfd, "get_by_id") @mock.patch('tacker.vnflcm.utils._get_vnfd_dict') def test_pre_helm_install_with_bool_param(self, mock_vnfd_dict, - mock_vnf_package_vnfd_get_by_id): + mock_vnf_package_vnfd_get_by_id, + mock_save): vnf_instance = fd_utils.get_vnf_instance_object() vim_connection_info = fakes.fake_vim_connection_info_with_extra() vnf_software_images = None @@ -334,7 +338,7 @@ class TestKubernetesHelm(base.TestCase): base_hot_dict) self.assertEqual( result, - "{'namespace': '', 'name': 'vdu1', " + + "{'namespace': 'default', 'name': 'vdu1', " + "'apiVersion': 'apps/v1', 'kind': 'Deployment', " + "'status': 'Create_complete'}") self.assertEqual(mock_read_namespaced_deployment.call_count, 1) @@ -351,6 +355,7 @@ class TestKubernetesHelm(base.TestCase): mock_connect, mock_from_transport, mock_put, mock_close, mock_vnf_resource_create): vnf_instance = fd_utils.get_vnf_instance_object() + vnf_instance.vnf_metadata['namespace'] = 'dummy_namespace' vim_connection_info = fakes.fake_vim_connection_info_with_extra() deployment_obj = fakes.fake_v1_deployment_for_helm() mock_read_namespaced_deployment.return_value = deployment_obj @@ -401,7 +406,7 @@ class TestKubernetesHelm(base.TestCase): base_hot_dict) self.assertEqual( result, - "{'namespace': '', 'name': 'vdu1', " + + "{'namespace': 'default', 'name': 'vdu1', " + "'apiVersion': 'apps/v1', 'kind': 'Deployment', " + "'status': 'Create_complete'}") self.assertEqual(mock_read_namespaced_deployment.call_count, 1) diff --git a/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_translate_outputs.py b/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_translate_outputs.py index 132b10d81..e50099b30 100644 --- a/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_translate_outputs.py +++ b/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_translate_outputs.py @@ -62,7 +62,7 @@ class TestTransformer(base.TestCase): def test_deployment(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['deployment.yaml'], self.yaml_path) + ['deployment.yaml'], self.yaml_path, '') k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) self.assertEqual(k8s_objs[0].get('namespace'), '') @@ -83,7 +83,7 @@ class TestTransformer(base.TestCase): def test_api_service(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['api-service.yaml'], self.yaml_path + ['api-service.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -97,7 +97,7 @@ class TestTransformer(base.TestCase): def test_cluster_role(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['cluster-role.yaml'], self.yaml_path + ['cluster-role.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -109,7 +109,7 @@ class TestTransformer(base.TestCase): def test_cluster_role_binding(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['cluster-role-binding.yaml'], self.yaml_path + ['cluster-role-binding.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -129,7 +129,7 @@ class TestTransformer(base.TestCase): def test_config_map(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['config-map.yaml'], self.yaml_path + ['config-map.yaml'], self.yaml_path, 'curryns' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -139,7 +139,7 @@ class TestTransformer(base.TestCase): def test_daemon_set(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['daemon-set.yaml'], self.yaml_path + ['daemon-set.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -160,7 +160,7 @@ class TestTransformer(base.TestCase): def test_horizontal_pod_autoscaler(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['horizontal-pod-autoscaler.yaml'], self.yaml_path + ['horizontal-pod-autoscaler.yaml'], self.yaml_path, 'default' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -180,7 +180,7 @@ class TestTransformer(base.TestCase): def test_job(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['job.yaml'], self.yaml_path + ['job.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -195,7 +195,7 @@ class TestTransformer(base.TestCase): def test_lease(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['lease.yaml'], self.yaml_path + ['lease.yaml'], self.yaml_path, 'default' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -205,7 +205,7 @@ class TestTransformer(base.TestCase): def test_local_subject_access_review(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['local-subject-access-review.yaml'], self.yaml_path + ['local-subject-access-review.yaml'], self.yaml_path, 'curry-ns' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -216,7 +216,7 @@ class TestTransformer(base.TestCase): def test_namespace(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['namespace.yaml'], self.yaml_path + ['namespace.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -230,7 +230,7 @@ class TestTransformer(base.TestCase): def test_network_policy(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['network-policy.yaml'], self.yaml_path + ['network-policy.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -246,7 +246,7 @@ class TestTransformer(base.TestCase): def test_node(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['node.yaml'], self.yaml_path + ['node.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -293,7 +293,7 @@ class TestTransformer(base.TestCase): def test_persistent_volume(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['persistent-volume.yaml'], self.yaml_path + ['persistent-volume.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -345,7 +345,7 @@ class TestTransformer(base.TestCase): def test_persistent_volume_claim(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['persistent-volume-claim.yaml'], self.yaml_path + ['persistent-volume-claim.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -364,7 +364,7 @@ class TestTransformer(base.TestCase): def test_pod(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['pod.yaml'], self.yaml_path + ['pod.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -479,7 +479,7 @@ class TestTransformer(base.TestCase): def test_priority_class(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['priority-class.yaml'], self.yaml_path + ['priority-class.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -491,7 +491,7 @@ class TestTransformer(base.TestCase): def test_replica_set(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['replica-set.yaml'], self.yaml_path + ['replica-set.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -510,7 +510,7 @@ class TestTransformer(base.TestCase): def test_resource_quota(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['resource-quota.yaml'], self.yaml_path + ['resource-quota.yaml'], self.yaml_path, 'curryns' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -525,7 +525,7 @@ class TestTransformer(base.TestCase): def test_role(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['role.yaml'], self.yaml_path + ['role.yaml'], self.yaml_path, 'curry-ns' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -535,7 +535,7 @@ class TestTransformer(base.TestCase): def test_role_binding(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['role-bindings.yaml'], self.yaml_path + ['role-bindings.yaml'], self.yaml_path, 'curry-ns' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -547,7 +547,7 @@ class TestTransformer(base.TestCase): def test_secret(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['secret.yaml'], self.yaml_path + ['secret.yaml'], self.yaml_path, 'default' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -557,7 +557,7 @@ class TestTransformer(base.TestCase): def test_self_subject_access_review(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['self-subject-access-review.yaml'], self.yaml_path + ['self-subject-access-review.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -569,7 +569,7 @@ class TestTransformer(base.TestCase): def test_self_subject_rules_review(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['self-subject-rule-review.yaml'], self.yaml_path + ['self-subject-rule-review.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -589,7 +589,7 @@ class TestTransformer(base.TestCase): def test_service(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['service.yaml'], self.yaml_path + ['service.yaml'], self.yaml_path, 'default' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -601,7 +601,7 @@ class TestTransformer(base.TestCase): def test_service_account(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['service-account.yaml'], self.yaml_path + ['service-account.yaml'], self.yaml_path, 'default' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -611,7 +611,7 @@ class TestTransformer(base.TestCase): def test_stateful_set(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['stateful-set.yaml'], self.yaml_path + ['stateful-set.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -630,7 +630,7 @@ class TestTransformer(base.TestCase): def test_storage_class(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['storage-class.yaml'], self.yaml_path + ['storage-class.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -649,7 +649,7 @@ class TestTransformer(base.TestCase): def test_subject_access_review(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['subject-access-review.yaml'], self.yaml_path + ['subject-access-review.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -663,7 +663,7 @@ class TestTransformer(base.TestCase): def test_token_review(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['token-review.yaml'], self.yaml_path + ['token-review.yaml'], self.yaml_path, '' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -675,7 +675,7 @@ class TestTransformer(base.TestCase): def test_limit_range(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['limit-range.yaml'], self.yaml_path + ['limit-range.yaml'], self.yaml_path, 'curryns' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -688,7 +688,7 @@ class TestTransformer(base.TestCase): def test_pod_template(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['pod-template.yaml'], self.yaml_path + ['pod-template.yaml'], self.yaml_path, 'curryns' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -812,7 +812,7 @@ class TestTransformer(base.TestCase): def test_volume_attachment(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['volume-attachment.yaml'], self.yaml_path + ['volume-attachment.yaml'], self.yaml_path, 'curryns' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -830,7 +830,7 @@ class TestTransformer(base.TestCase): def test_bindings(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['bindings.yaml'], self.yaml_path + ['bindings.yaml'], self.yaml_path, 'curryns' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) @@ -842,7 +842,7 @@ class TestTransformer(base.TestCase): def test_controller_revision(self): k8s_objs = self.transfromer.get_k8s_objs_from_yaml( - ['controller-revision.yaml'], self.yaml_path + ['controller-revision.yaml'], self.yaml_path, 'curryns' ) k8s_obj = k8s_objs[0].get('object') self.assertIsNotNone(k8s_obj) diff --git a/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_utils.py b/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_utils.py new file mode 100644 index 000000000..b7d6d98ca --- /dev/null +++ b/tacker/tests/unit/vnfm/infra_drivers/kubernetes/test_utils.py @@ -0,0 +1,70 @@ +# 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 tacker.common import exceptions +from tacker import objects +from tacker.tests.unit import base +from tacker.tests.unit.vnfm.infra_drivers.openstack.fixture_data import ( + fixture_data_utils as fd_utils +) +from tacker.vnfm.infra_drivers.kubernetes import utils as k8s_utils +from unittest import mock + + +class KubernetesUtilsTestCase(base.TestCase): + + @mock.patch('tacker.objects.vnf_instance.VnfInstance.save') + def test_check_and_save_namespace_multi_namespace(self, mock_save): + instantiate_vnf_req = objects.InstantiateVnfRequest( + additional_params=None) + chk_namespaces = [{"namespace": "a", "kind": "CronJob"}, + {"namespace": "b", "kind": "Deployment"}, + {"namespace": "c", "kind": "Service"}] + vnf_instance = fd_utils.get_vnf_instance_object() + + self.assertRaises( + exceptions.NamespaceIsNotUnique, + k8s_utils.check_and_save_namespace, instantiate_vnf_req, + chk_namespaces, vnf_instance) + + @mock.patch('tacker.objects.vnf_instance.VnfInstance.save') + def test_check_and_save_namespace_no_namespace(self, mock_save): + instantiate_vnf_req = objects.InstantiateVnfRequest( + additional_params=None) + chk_namespaces = [] + vnf_instance = fd_utils.get_vnf_instance_object() + vnf_instance.vnf_metadata['namespace'] = '' + k8s_utils.check_and_save_namespace( + instantiate_vnf_req, chk_namespaces, vnf_instance) + self.assertEqual('default', vnf_instance.vnf_metadata['namespace']) + + @mock.patch('tacker.objects.vnf_instance.VnfInstance.save') + def test_check_and_save_namespace_additional_params(self, mock_save): + instantiate_vnf_req = objects.InstantiateVnfRequest( + additional_params={'namespace': 'ns1'}) + chk_namespaces = [] + vnf_instance = fd_utils.get_vnf_instance_object() + vnf_instance.vnf_metadata['namespace'] = '' + k8s_utils.check_and_save_namespace( + instantiate_vnf_req, chk_namespaces, vnf_instance) + self.assertEqual('ns1', vnf_instance.vnf_metadata['namespace']) + + @mock.patch('tacker.objects.vnf_instance.VnfInstance.save') + def test_check_and_save_namespace_manifests(self, mock_save): + instantiate_vnf_req = objects.InstantiateVnfRequest( + additional_params=None) + chk_namespaces = [{"namespace": "ns2", "kind": "Deployment"}] + vnf_instance = fd_utils.get_vnf_instance_object() + vnf_instance.vnf_metadata = {} + k8s_utils.check_and_save_namespace( + instantiate_vnf_req, chk_namespaces, vnf_instance) + self.assertEqual('ns2', vnf_instance.vnf_metadata['namespace']) diff --git a/tacker/tests/unit/vnfm/infra_drivers/openstack/fixture_data/fixture_data_utils.py b/tacker/tests/unit/vnfm/infra_drivers/openstack/fixture_data/fixture_data_utils.py index 95d2d38c0..1eecf388d 100644 --- a/tacker/tests/unit/vnfm/infra_drivers/openstack/fixture_data/fixture_data_utils.py +++ b/tacker/tests/unit/vnfm/infra_drivers/openstack/fixture_data/fixture_data_utils.py @@ -90,7 +90,8 @@ def get_vnf_instance_object(instantiated_vnf_info=None, instantiation_state=instantiation_state, vnfd_id=uuidsentinel.vnfd_id, vnf_provider="sample provider", vnf_product_name="vnf product name", vnf_software_version='1.0', vnfd_version="2", - instantiated_vnf_info=inst_vnf_info) + instantiated_vnf_info=inst_vnf_info, + vnf_metadata={'namespace': 'default'}) return vnf_instance diff --git a/tacker/vnfm/infra_drivers/kubernetes/k8s/translate_outputs.py b/tacker/vnfm/infra_drivers/kubernetes/k8s/translate_outputs.py index 453a0be48..44ab2763b 100644 --- a/tacker/vnfm/infra_drivers/kubernetes/k8s/translate_outputs.py +++ b/tacker/vnfm/infra_drivers/kubernetes/k8s/translate_outputs.py @@ -341,20 +341,15 @@ class Transformer(object): kind=file_content_dict.get('kind', ''), reason=e) LOG.error(msg) raise exceptions.InitApiFalse(error=msg) - if not file_content_dict.get('metadata', '') and not namespace: - k8s_obj['namespace'] = '' - elif file_content_dict.get('metadata', '').\ - get('namespace', ''): - k8s_obj['namespace'] = \ - file_content_dict.get('metadata', '').get( - 'namespace', '') - elif namespace: - k8s_obj['namespace'] = namespace - else: - k8s_obj['namespace'] = '' + + k8s_obj['namespace'] = namespace + if k8s_obj['object'].metadata: + k8s_obj['object'].metadata.namespace = namespace + return k8s_obj - def get_k8s_objs_from_yaml(self, artifact_files, vnf_package_path): + def get_k8s_objs_from_yaml(self, artifact_files, vnf_package_path, + namespace=None): k8s_objs = [] for artifact_file in artifact_files: if ((urlparse(artifact_file).scheme == 'file') or @@ -369,11 +364,11 @@ class Transformer(object): file_content_dicts = list(yaml.safe_load_all(file_content)) for file_content_dict in file_content_dicts: k8s_obj = self._get_k8s_obj_from_file_content_dict( - file_content_dict) + file_content_dict, namespace) k8s_objs.append(k8s_obj) return k8s_objs - def get_k8s_objs_from_manifest(self, mf_content, namespace=None): + def get_k8s_objs_from_manifest(self, mf_content, namespace): mkobj_kind_list = [ "Pod", "Service", diff --git a/tacker/vnfm/infra_drivers/kubernetes/kubernetes_driver.py b/tacker/vnfm/infra_drivers/kubernetes/kubernetes_driver.py index 5950bfcbe..1ce33ba44 100644 --- a/tacker/vnfm/infra_drivers/kubernetes/kubernetes_driver.py +++ b/tacker/vnfm/infra_drivers/kubernetes/kubernetes_driver.py @@ -42,6 +42,7 @@ from tacker.vnfm.infra_drivers import abstract_driver from tacker.vnfm.infra_drivers.kubernetes.helm import helm_client from tacker.vnfm.infra_drivers.kubernetes.k8s import translate_outputs from tacker.vnfm.infra_drivers.kubernetes import translate_template +from tacker.vnfm.infra_drivers.kubernetes import utils as k8s_utils from tacker.vnfm.infra_drivers import scale_driver from urllib.parse import urlparse @@ -760,11 +761,9 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, return pvc_list_for_delete @log.log - def _delete_k8s_obj(self, kind, k8s_client_dict, vnf_resource, body): - namespace = vnf_resource.resource_name.\ - split(COMMA_CHARACTER)[0] - name = vnf_resource.resource_name.\ - split(COMMA_CHARACTER)[1] + def _delete_k8s_obj(self, kind, k8s_client_dict, vnf_resource, body, + namespace): + name = vnf_resource.resource_name api_version = vnf_resource.resource_type.\ split(COMMA_CHARACTER)[0] @@ -820,7 +819,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, def _helm_uninstall(self, context, vnf_instance): inst_vnf_info = vnf_instance.instantiated_vnf_info additional_params = inst_vnf_info.additional_params - namespace = additional_params.get('namespace', '') + namespace = vnf_instance.vnf_metadata['namespace'] helm_inst_param_list = additional_params.get( 'using_helm_install_param') vim_info = vnflcm_utils._get_vim(context, @@ -897,6 +896,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, # 7. Delete `Namespace` finally 'Namespace' ] + namespace = vnf_instance.vnf_metadata['namespace'] for kind in ordered_kind: for vnf_resource in vnf_resources: obj_kind = vnf_resource.resource_type.\ @@ -906,7 +906,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, kind=obj_kind, k8s_client_dict=k8s_client_dict, vnf_resource=vnf_resource, - body=body) + body=body, namespace=namespace) except Exception as e: LOG.error('Deleting VNF got an error due to %s', e) raise @@ -987,8 +987,9 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, name_with_underscores).lower() snake_case_kind = convert(kind) + kubernetes = translate_outputs.Transformer(None, None, None, None) try: - if namespace: + if 'namespaced' in kubernetes.method_value.get(kind): read_api = eval('k8s_client_dict[api_version].' 'read_namespaced_%s' % snake_case_kind) response = read_api(name=name, namespace=namespace) @@ -1049,6 +1050,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, get_by_vnf_instance_id(context, vnf_instance.id) k8s_client_dict = self.kubernetes.\ get_k8s_client_dict(auth=auth_cred) + namespace = vnf_instance.vnf_metadata['namespace'] keep_going = True stack_retries = self.STACK_RETRIES @@ -1057,10 +1059,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, count = 0 for vnf_resource in vnf_resources: - namespace = vnf_resource.resource_name.\ - split(COMMA_CHARACTER)[0] - name = vnf_resource.resource_name.\ - split(COMMA_CHARACTER)[1] + name = vnf_resource.resource_name api_version = vnf_resource.resource_type.\ split(COMMA_CHARACTER)[0] kind = vnf_resource.resource_type.\ @@ -1192,7 +1191,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, vdu_defs = policy['vdu_defs'] inst_additional_params = (vnf_instance.instantiated_vnf_info .additional_params) - namespace = inst_additional_params.get('namespace', '') + namespace = vnf_instance.vnf_metadata['namespace'] helm_install_params = inst_additional_params.get( 'using_helm_install_param', []) # Get releasename and chartname from Helm install params in Instantiate @@ -1279,6 +1278,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, if self._is_use_helm_flag(inst_vnf_info.additional_params): self._helm_scale(context, vnf_instance, policy) return + namespace = vnf_instance.vnf_metadata['namespace'] vnf_resources = objects.VnfResourceList.get_by_vnf_instance_id( context, policy['vnf_instance_id']) app_v1_api_client = self.kubernetes.get_app_v1_api_client( @@ -1295,15 +1295,10 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, # name defined in `metadata.name` of Kubernetes object # file) matches the value of `properties.name` of VDU # defined in VNFD. - name = vnf_resource.resource_name.\ - split(COMMA_CHARACTER)[1] + name = vnf_resource.resource_name for vdu_id, vdu_def in vdu_defs.items(): vdu_properties = vdu_def.get('properties') if name == vdu_properties.get('name'): - namespace = vnf_resource.resource_name.\ - split(COMMA_CHARACTER)[0] - if not namespace: - namespace = "default" kind = vnf_resource.resource_type.\ split(COMMA_CHARACTER)[1] if kind in target_kinds: @@ -1440,6 +1435,9 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, # execute legacy scale_wait method self._scale_wait_legacy(policy, auth_cred) else: + vnf_instance = objects.VnfInstance.get_by_id( + context, policy['vnf_instance_id']) + namespace = vnf_instance.vnf_metadata['namespace'] vnf_resources = objects.VnfResourceList.get_by_vnf_instance_id( context, policy['vnf_instance_id']) core_v1_api_client = self.kubernetes.get_core_v1_api_client( @@ -1452,15 +1450,10 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, error_reason = None target_kinds = ["Deployment", "ReplicaSet", "StatefulSet"] for vnf_resource in vnf_resources: - name = vnf_resource.resource_name.\ - split(COMMA_CHARACTER)[1] + name = vnf_resource.resource_name for vdu_id, vdu_def in vdu_defs.items(): vdu_properties = vdu_def.get('properties') if name == vdu_properties.get('name'): - namespace = vnf_resource.resource_name.\ - split(COMMA_CHARACTER)[0] - if not namespace: - namespace = "default" kind = vnf_resource.resource_type.\ split(COMMA_CHARACTER)[1] if kind in target_kinds: @@ -1644,20 +1637,12 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, target_k8s_files = list() return target_k8s_files - def _create_vnf_resource(self, context, vnf_instance, file_content_dict, - namespace=None): + def _create_vnf_resource(self, context, vnf_instance, file_content_dict): vnf_resource = vnf_resource_obj.VnfResource( context=context) vnf_resource.vnf_instance_id = vnf_instance.id metadata = file_content_dict.get('metadata', {}) - if metadata and metadata.get('namespace', ''): - namespace = metadata.get('namespace', '') - elif namespace: - namespace = namespace - else: - namespace = '' - vnf_resource.resource_name = ','.join([ - namespace, metadata.get('name', '')]) + vnf_resource.resource_name = metadata.get('name', ' ') vnf_resource.resource_type = ','.join([ file_content_dict.get('apiVersion', ''), file_content_dict.get('kind', '')]) @@ -1675,6 +1660,16 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, instantiate_vnf_req, vnf_package_path) # NOTE: In case of using helm, vnf_resources is created # after `helm install` command is executed. + + namespace = (instantiate_vnf_req.additional_params + .get('namespace', '')) + if not namespace: + namespace = 'default' + if not vnf_instance.vnf_metadata: + vnf_instance.vnf_metadata = {} + vnf_instance.vnf_metadata['namespace'] = namespace + vnf_instance.save() + return {} vnf_resources = dict() @@ -1713,6 +1708,9 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, setattr(vnf_instance, 'task_state', None) vnf_instance.save() raise exceptions.VnfArtifactNotFound(id=vnf_package.id) + + chk_namespaces = [] + for target_k8s_index, target_k8s_file \ in enumerate(target_k8s_files): if ((urlparse(target_k8s_file).scheme == 'file') or @@ -1730,7 +1728,18 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, vnf_resource = self._create_vnf_resource( context, vnf_instance, file_content_dict) vnf_resources_temp.append(vnf_resource) + + metadata = file_content_dict.get('metadata', {}) + chk_namespaces.append( + {'namespace': metadata.get('namespace', ''), + 'kind': file_content_dict.get('kind', '')}) + vnf_resources[target_k8s_index] = vnf_resources_temp + + LOG.debug(f"all manifest namespace and kind: {chk_namespaces}") + k8s_utils.check_and_save_namespace( + instantiate_vnf_req, chk_namespaces, vnf_instance) + return vnf_resources def delete_vnf_instance_resource(self, context, vnf_instance, @@ -1740,7 +1749,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, def _helm_install(self, context, vnf_instance, vim_connection_info, instantiate_vnf_req, vnf_package_path, transformer): additional_params = instantiate_vnf_req.additional_params - namespace = additional_params.get('namespace', '') + namespace = vnf_instance.vnf_metadata['namespace'] helm_inst_param_list = additional_params.get( 'using_helm_install_param') ips, username, password = self._get_helm_info(vim_connection_info) @@ -1787,7 +1796,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, mf_content_dicts = list(yaml.safe_load_all(mf_content)) for mf_content_dict in mf_content_dicts: vnf_resource = self._create_vnf_resource( - context, vnf_instance, mf_content_dict, namespace) + context, vnf_instance, mf_content_dict) vnf_resources.append(vnf_resource) helmclient.close_session() # save the vnf resources in the db @@ -1800,6 +1809,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, grant_response, vnf_package_path, plugin=None): target_k8s_files = self._get_target_k8s_files(instantiate_vnf_req) + namespace = vnf_instance.vnf_metadata['namespace'] auth_attr = vim_connection_info.access_info use_helm_flag = self._is_use_helm_flag( instantiate_vnf_req.additional_params) @@ -1821,7 +1831,8 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, instantiate_vnf_req, vnf_package_path, transformer) else: k8s_objs = transformer.\ - get_k8s_objs_from_yaml(target_k8s_files, vnf_package_path) + get_k8s_objs_from_yaml(target_k8s_files, vnf_package_path, + namespace) k8s_objs = transformer.deploy_k8s(k8s_objs) vnfd_dict['current_error_point'] = EP.POST_VIM_CONTROL k8s_objs = self.create_wait_k8s( @@ -1848,9 +1859,8 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, return resource_info_str def _post_helm_install(self, context, vim_connection_info, - instantiate_vnf_req, transformer): + instantiate_vnf_req, transformer, namespace): additional_params = instantiate_vnf_req.additional_params - namespace = additional_params.get('namespace', '') helm_inst_param_list = additional_params.get( 'using_helm_install_param') ips, username, password = self._get_helm_info(vim_connection_info) @@ -1877,6 +1887,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, """ auth_attr = vim_connection_info.access_info auth_cred, file_descriptor = self._get_auth_creds(auth_attr) + namespace = vnf_instance.vnf_metadata['namespace'] try: # get Kubernetes object files target_k8s_files = self._get_target_k8s_files(instantiate_vnf_req) @@ -1887,11 +1898,12 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, None, None, None, None) if self._is_use_helm_flag(instantiate_vnf_req.additional_params): k8s_objs = self._post_helm_install(context, - vim_connection_info, instantiate_vnf_req, transformer) + vim_connection_info, instantiate_vnf_req, transformer, + namespace) else: # get Kubernetes object k8s_objs = transformer.get_k8s_objs_from_yaml( - target_k8s_files, vnf_package_path) + target_k8s_files, vnf_package_path, namespace) # get TOSCA node templates vnfd_dict = vnflcm_utils._get_vnfd_dict( context, vnf_instance.vnfd_id, @@ -1920,9 +1932,6 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, # Skip if rsc_kind is not target kind continue rsc_name = k8s_obj.get('object').metadata.name - namespace = k8s_obj.get('object').metadata.namespace - if not namespace: - namespace = "default" # get V1PodList by namespace if namespace in pod_list_dict.keys(): pod_list = pod_list_dict.get(namespace) @@ -1976,14 +1985,11 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, return vnfc_resources def _get_added_pod_names(self, core_v1_api_client, inst_vnf_info, vdu_id, - vnfc_resource, pod_list_dict): + vnfc_resource, pod_list_dict, namespace): compute_resource = vnfc_resource.compute_resource rsc_kind = compute_resource.vim_level_resource_type rsc_metadata = jsonutils.loads( vnfc_resource.metadata.get(rsc_kind)) - namespace = rsc_metadata.get('namespace') - if not namespace: - namespace = "default" rsc_name = rsc_metadata.get('name') # Get pod list from kubernetes if namespace in pod_list_dict.keys(): @@ -2028,6 +2034,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, auth_attr = vim_connection_info.access_info auth_cred, file_descriptor = self._get_auth_creds(auth_attr) inst_vnf_info = vnf_instance.instantiated_vnf_info + namespace = vnf_instance.vnf_metadata['namespace'] try: core_v1_api_client = self.kubernetes.get_core_v1_api_client( auth=auth_cred) @@ -2049,7 +2056,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, continue actual_pod_names, added_pod_names = self._get_added_pod_names( core_v1_api_client, inst_vnf_info, vdu_id, vnfc_resource, - pod_list_dict) + pod_list_dict, namespace) if added_pod_names: heal_target_ids = heal_vnf_request.vnfc_instance_id @@ -2078,9 +2085,6 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, pod_name = compute_resource.resource_id rsc_metadata = jsonutils.loads( vnfc_resource.metadata.get(rsc_kind)) - namespace = rsc_metadata.get('namespace') - if not namespace: - namespace = "default" if rsc_kind == 'Pod': rsc_name = rsc_metadata.get('name') @@ -2185,6 +2189,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, # initialize Kubernetes APIs auth_attr = vim_connection_info.access_info auth_cred, file_descriptor = self._get_auth_creds(auth_attr) + namespace = vnf_instance.vnf_metadata['namespace'] try: core_v1_api_client = self.kubernetes.get_core_v1_api_client( auth=auth_cred) @@ -2211,7 +2216,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, rsc_metadata = jsonutils.loads( vnfc_resource.metadata.get(info['kind'])) info['name'] = rsc_metadata.get('name') - info['namespace'] = rsc_metadata.get('namespace') + info['namespace'] = namespace if not info['namespace']: info['namespace'] = "default" k8s_resources.append(info) @@ -2301,6 +2306,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, auth_attr = vim_connection_info.access_info auth_cred, file_descriptor = self._get_auth_creds(auth_attr) inst_vnf_info = vnf_instance.instantiated_vnf_info + namespace = vnf_instance.vnf_metadata['namespace'] try: core_v1_api_client = self.kubernetes.get_core_v1_api_client( auth=auth_cred) @@ -2328,7 +2334,7 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, # (Deployment, DaemonSet, ReplicaSet) actual_pod_names, added_pod_names = self._get_added_pod_names( core_v1_api_client, inst_vnf_info, vdu_id, vnfc_resource, - pod_list_dict) + pod_list_dict, namespace) updated_vnfc_ids = [] # Update entries that pod was not found when heal_vnf method @@ -2430,18 +2436,18 @@ class Kubernetes(abstract_driver.VnfAbstractDriver, extract_policy_infos=extract_policy_infos, aspect_id=scale_vnf_request.aspect_id, tosca=tosca) + namespace = vnf_instance.vnf_metadata['namespace'] is_found = False target_kinds = ["Deployment", "ReplicaSet", "StatefulSet"] for vnf_resource in vnf_resources: # For CNF operations, Kubernetes resource information is # stored in vnfc_resource as follows: - # - resource_name : "namespace,name" + # - resource_name : "name" # - resource_type : "api_version,kind" - rsc_name = vnf_resource.resource_name.split(',')[1] + rsc_name = vnf_resource.resource_name for vdu_id, vdu_def in vdu_defs.items(): vdu_properties = vdu_def.get('properties') if rsc_name == vdu_properties.get('name'): - namespace = vnf_resource.resource_name.split(',')[0] rsc_kind = vnf_resource.resource_type.split(',')[1] target_vdu_id = vdu_id if rsc_kind in target_kinds: diff --git a/tacker/vnfm/infra_drivers/kubernetes/utils.py b/tacker/vnfm/infra_drivers/kubernetes/utils.py new file mode 100644 index 000000000..a67251a88 --- /dev/null +++ b/tacker/vnfm/infra_drivers/kubernetes/utils.py @@ -0,0 +1,83 @@ +# All Rights Reserved. +# +# +# 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. + +"""Utilities and helper functions.""" + +from oslo_log import log as logging + +from tacker.common import exceptions + +LOG = logging.getLogger(__name__) + +supported_k8s_resource_kinds = { + "Pod", + "Binding", + "ConfigMap", + "LimitRange", + "PersistentVolumeClaim", + "PodTemplate", + "ResourceQuota", + "Secret", + "ServiceAccount", + "Service", + "ControllerRevision", + "DaemonSet", + "Deployment", + "ReplicaSet", + "StatefulSet", + "LocalSubjectAccessReview", + "HorizontalPodAutoscaler", + "Job", + "Lease", + "NetworkPolicy", + "RoleBinding", + "Role" +} + + +def check_and_save_namespace( + instantiate_vnf_req, chk_namespaces, vnf_instance): + namespace = '' + if instantiate_vnf_req.additional_params: + namespace = instantiate_vnf_req.additional_params.get('namespace', '') + if not namespace: + try: + namespace = get_namespace_from_manifests(chk_namespaces) + except exceptions.NamespaceIsNotUnique as e: + LOG.error(e) + raise e + if not namespace: + namespace = 'default' + + if not vnf_instance.vnf_metadata: + vnf_instance.vnf_metadata = {} + vnf_instance.vnf_metadata['namespace'] = namespace + vnf_instance.save() + + +def get_namespace_from_manifests(chk_namespaces): + namespaces = { + chk_namespace['namespace'] for chk_namespace in + chk_namespaces if (chk_namespace['kind'] in + supported_k8s_resource_kinds) + } + + if len(namespaces) > 1: + LOG.error(f'Multiple namespaces found: {namespaces}') + raise exceptions.NamespaceIsNotUnique() + + if namespaces: + return namespaces.pop() + return None