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
This commit is contained in:
parent
81e46c6335
commit
d423353732
@ -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.
|
@ -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.')
|
||||
|
@ -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 ]
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: multi-namespace01
|
@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: multi-namespace02
|
@ -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
|
@ -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'])
|
@ -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]
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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'])
|
@ -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
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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:
|
||||
|
83
tacker/vnfm/infra_drivers/kubernetes/utils.py
Normal file
83
tacker/vnfm/infra_drivers/kubernetes/utils.py
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user