diff --git a/IM/connectors/Kubernetes.py b/IM/connectors/Kubernetes.py index b0d9befe..1fd74d40 100644 --- a/IM/connectors/Kubernetes.py +++ b/IM/connectors/Kubernetes.py @@ -47,12 +47,8 @@ class KubernetesCloudConnector(CloudConnector): } """Dictionary with a map with the Kubernetes POD states to the IM states.""" - def __init__(self, cloud_info, inf): - self.apiVersion = None - CloudConnector.__init__(self, cloud_info, inf) - def create_request(self, method, url, auth_data, headers=None, body=None): - auth_header = self.get_auth_header(auth_data) + auth_header, _ = self.get_auth_header(auth_data) if auth_header: if headers is None: headers = {} @@ -91,7 +87,11 @@ def get_auth_header(self, auth_data): else: raise Exception("No correct auth data has been specified to Kubernetes: username and password or token.") - return auth_header + namespace = None + if 'namespace' in auth: + namespace = auth['namespace'] + + return auth_header, namespace def concrete_system(self, radl_system, str_url, auth_data): url = urlparse(str_url) @@ -494,20 +494,20 @@ def _generate_pod_data(self, namespace, name, outports, system, volumes, configm return pod_data - @staticmethod - def _get_namespace(inf): - namespace = inf.id - if inf.radl.description and inf.radl.description.getValue('namespace'): - namespace = inf.radl.description.getValue('namespace') - return namespace - def launch(self, inf, radl, requested_radl, num_vm, auth_data): system = radl.systems[0] res = [] - # First create the namespace for the infrastructure - namespace = self._get_namespace(inf) + _, namespace = self.get_auth_header(auth_data) + # If the namespace is set in the auth_data use it + if not namespace: + # If not by default use the Inf ID as namespace + namespace = inf.id + if inf.radl.description and inf.radl.description.getValue('namespace'): + # finally if it is set in the RADL use it + namespace = inf.radl.description.getValue('namespace') + # First create the namespace for the infrastructure headers = {'Content-Type': 'application/json'} uri = "/api/v1/namespaces/" with inf._lock: @@ -577,7 +577,7 @@ def launch(self, inf, radl, requested_radl, num_vm, auth_data): else: output = json.loads(resp.text) - vm.id = output["metadata"]["name"] + vm.id = namespace + "/" + output["metadata"]["name"] vm.info.systems[0].setValue('instance_id', str(vm.id)) vm.info.systems[0].setValue('instance_name', str(vm.id)) vm.destroy = False @@ -612,8 +612,8 @@ def launch(self, inf, radl, requested_radl, num_vm, auth_data): def _get_pod(self, vm, auth_data): try: - namespace = self._get_namespace(vm.inf) - pod_name = vm.id + namespace = vm.id.split("/")[0] + pod_name = vm.id.split("/")[1] uri = "/api/v1/namespaces/%s/%s/%s" % (namespace, "pods", pod_name) resp = self.create_request('GET', uri, auth_data) @@ -716,7 +716,7 @@ def finalize(self, vm, last, auth_data): return success, msg def _delete_namespace(self, vm, auth_data): - namespace = self._get_namespace(vm.inf) + namespace = vm.id.split("/")[0] self.log_debug("Deleting Namespace: %s" % namespace) uri = "/api/v1/namespaces/%s" % namespace @@ -740,8 +740,8 @@ def _delete_namespace(self, vm, auth_data): def _delete_service(self, vm, auth_data): try: - namespace = self._get_namespace(vm.inf) - service_name = vm.id + namespace = vm.id.split("/")[0] + service_name = vm.id.split("/")[1] self.log_debug("Deleting Service: %s/%s" % (namespace, service_name)) uri = "/api/v1/namespaces/%s/%s/%s" % (namespace, "services", service_name) @@ -760,8 +760,8 @@ def _delete_service(self, vm, auth_data): def _delete_ingress(self, vm, auth_data): try: - namespace = self._get_namespace(vm.inf) - ingress_name = vm.id + namespace = vm.id.split("/")[0] + ingress_name = vm.id.split("/")[1] self.log_debug("Deleting Ingress: %s/%s" % (namespace, ingress_name)) uri = "/apis/networking.k8s.io/v1/namespaces/%s/ingresses/%s" % (namespace, ingress_name) @@ -780,8 +780,8 @@ def _delete_ingress(self, vm, auth_data): def _delete_pod(self, vm, auth_data): try: - namespace = self._get_namespace(vm.inf) - pod_name = vm.id + namespace = vm.id.split("/")[0] + pod_name = vm.id.split("/")[1] self.log_debug("Deleting POD: %s/%s" % (namespace, pod_name)) uri = "/api/v1/namespaces/%s/%s/%s" % (namespace, "pods", pod_name) @@ -833,8 +833,8 @@ def alterVM(self, vm, radl, auth_data): return (True, vm) # Create the container - namespace = self._get_namespace(vm.inf) - pod_name = vm.id + namespace = vm.id.split("/")[0] + pod_name = vm.id.split("/")[1] headers = {'Content-Type': 'application/json-patch+json'} uri = "/api/v1/namespaces/%s/%s/%s" % (namespace, "pods", pod_name) diff --git a/doc/source/client.rst b/doc/source/client.rst index 6cbb8f40..128c3245 100644 --- a/doc/source/client.rst +++ b/doc/source/client.rst @@ -365,6 +365,8 @@ The available keys are: mandatory and it indicates the arn of the IAM role created to correcly execute Lambda functions (see `here `_ how to configure it). +* ``namespace`` indicates a namespace name to be associated to the Kubernetes credential (from version 1.7.1). + Vault Credentials support ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/unit/connectors/Kubernetes.py b/test/unit/connectors/Kubernetes.py index 72d9e7a9..0921f0d5 100755 --- a/test/unit/connectors/Kubernetes.py +++ b/test/unit/connectors/Kubernetes.py @@ -137,7 +137,7 @@ def test_20_launch(self, save_data, requests): radl_data = """ description desc ( name = 'Infrastructure Name' and - namespace = 'somenamespace' + namespace = 'somenamespace2' ) network net (outbound = 'yes' and outports = '38080-8080') system test ( @@ -161,7 +161,7 @@ def test_20_launch(self, save_data, requests): radl = radl_parse.parse_radl(radl_data) radl.check() - auth = Authentication([{'id': 'kube', 'type': 'Kubernetes', + auth = Authentication([{'id': 'kube', 'type': 'Kubernetes', 'namespace': 'somenamespace', 'host': 'http://server.com:8080', 'token': 'token'}]) kube_cloud = self.get_kube_cloud() @@ -351,8 +351,7 @@ def test_30_updateVMInfo(self, requests): kube_cloud = self.get_kube_cloud() inf = MagicMock() - inf.id = "namespace" - vm = VirtualMachine(inf, "1", kube_cloud.cloud, radl, radl, kube_cloud, 1) + vm = VirtualMachine(inf, "namespace/1", kube_cloud.cloud, radl, radl, kube_cloud, 1) requests.side_effect = self.get_response @@ -386,8 +385,7 @@ def test_55_alter(self, requests): kube_cloud = self.get_kube_cloud() inf = MagicMock() - inf.id = "namespace" - vm = VirtualMachine(inf, "1", kube_cloud.cloud, radl, radl, kube_cloud, 1) + vm = VirtualMachine(inf, "namespace/1", kube_cloud.cloud, radl, radl, kube_cloud, 1) requests.side_effect = self.get_response @@ -404,10 +402,7 @@ def test_60_finalize(self, requests): inf = MagicMock() inf.id = "infid" - inf.radl = MagicMock() - inf.radl.description = MagicMock(["getValue"]) - inf.radl.description.getValue.return_value = "somenamespace" - vm = VirtualMachine(inf, "1", kube_cloud.cloud, "", "", kube_cloud, 1) + vm = VirtualMachine(inf, "somenamespace/1", kube_cloud.cloud, "", "", kube_cloud, 1) requests.side_effect = self.get_response