Add osmclient commands for cluster mgmt: get-creds, register 08/14608/4
authorgarciadeblas <gerardo.garciadeblas@telefonica.com>
Mon, 30 Sep 2024 22:42:04 +0000 (00:42 +0200)
committergarciadeblas <gerardo.garciadeblas@telefonica.com>
Sun, 13 Oct 2024 20:26:20 +0000 (22:26 +0200)
Change-Id: I6a15751e612d929afa67c7b03a78b8808ecb8507
Signed-off-by: garciadeblas <gerardo.garciadeblas@telefonica.com>
osmclient/cli_commands/cluster.py
osmclient/scripts/osm.py
osmclient/sol005/cluster.py
osmclient/sol005/osm_api_object.py

index 15c83bc..53991b7 100755 (executable)
@@ -16,6 +16,7 @@
 import click
 from osmclient.cli_commands import common
 import logging
+import yaml
 
 logger = logging.getLogger("osmclient")
 
@@ -145,3 +146,50 @@ def cluster_get_credentials(ctx, name, **kwargs):
     """
     logger.debug("")
     ctx.obj.cluster.get_credentials(name)
+
+
+@click.command(name="cluster-register", short_help="registers a K8s cluster to OSM")
+@click.argument("name")
+@click.option(
+    "--vim-account",
+    "--vim",
+    prompt=True,
+    help="VIM target or cloud account where the cluster will be created",
+)
+@click.option(
+    "--creds", prompt=True, help="credentials file, i.e. a valid `.kube/config` file"
+)
+@click.option("--description", default="", help="human readable description")
+@click.pass_context
+def cluster_register(
+    ctx,
+    name,
+    vim_account,
+    creds,
+    description,
+):
+    """registers a K8s cluster to OSM
+
+    NAME: name of the K8s cluster
+    """
+    logger.debug("")
+    # kwargs = {k: v for k, v in kwargs.items() if v is not None}
+    cluster = {}
+    cluster["name"] = name
+    with open(creds, "r") as cf:
+        cluster["credentials"] = yaml.safe_load(cf.read())
+    # cluster["k8s_version"] = version
+    cluster["vim_account"] = vim_account
+    # cluster["nets"] = yaml.safe_load(k8s_nets)
+    # if not (init_jujubundle and init_helm3):
+    #     cluster["deployment_methods"] = {
+    #         "juju-bundle": init_jujubundle,
+    #         "helm-chart-v3": init_helm3,
+    #     }
+    if description:
+        cluster["description"] = description
+    # if namespace:
+    #     cluster["namespace"] = namespace
+    # if cni:
+    #     cluster["cni"] = yaml.safe_load(cni)
+    ctx.obj.cluster.register(name, cluster)
index 78d3fff..c90e513 100755 (executable)
@@ -193,6 +193,8 @@ def cli():
         cli_osm.add_command(cluster.cluster_list)
         cli_osm.add_command(cluster.cluster_show)
         cli_osm.add_command(cluster.cluster_update)
+        cli_osm.add_command(cluster.cluster_get_credentials)
+        cli_osm.add_command(cluster.cluster_register)
 
         cli_osm.add_command(netslice_instance.nsi_create1)
         cli_osm.add_command(netslice_instance.nsi_create2)
index 9aebeab..bc961a3 100644 (file)
@@ -20,8 +20,9 @@ OSM Cluster API handling
 """
 
 from osmclient.sol005.osm_api_object import GenericOSMAPIObject
-from osmclient.common.exceptions import ClientException
+from osmclient.common.exceptions import ClientException, NotFound
 import json
+import yaml
 
 
 class Cluster(GenericOSMAPIObject):
@@ -61,5 +62,33 @@ class Cluster(GenericOSMAPIObject):
         elif http_code == 204:
             print("Updated")
 
-    # def get_credentials(self, cluster_id):
-    #     # TODO:
+    def get_credentials(self, name):
+        """
+        Gets and shows an individual Generic OSM API Object
+        from the list of all objects of the same kind
+        """
+        self._logger.debug("")
+        item = self.get(name)
+        resp = ""
+        try:
+            _, resp = self._http.get2_cmd(f"{self._apiBase}/{item['_id']}/get_creds")
+            if resp:
+                resp = json.loads(resp)
+                item = self.get(name)
+                print(
+                    yaml.safe_dump(
+                        item["credentials"], indent=4, default_flow_style=False
+                    )
+                )
+        except NotFound:
+            raise NotFound(f"{self._logObjectName} '{name}' not found")
+        except Exception as e:
+            raise ClientException(f"{e}: unexpected response from server - {resp}")
+
+    def register_cluster(self, name, cluster):
+        """
+        Registers a K8s cluster
+        """
+        self._logger.debug("")
+        endpoint = f"{self._apiBase}/register"
+        self.create(name, cluster, None, endpoint=endpoint)
index 0c1ba1e..0e4b8cb 100644 (file)
@@ -127,7 +127,7 @@ class GenericOSMAPIObject(ABC):
 
     def get_individual(self, name):
         """Gets and shows an individual Generic OSM API Object"""
-        # It is redundant, since the method getalready gets the whole item
+        # It is redundant, since the method `get` already gets the whole item
         # The only difference is that a different primitive is exercised
         self._logger.debug("")
         item = self.get(name)
@@ -222,10 +222,12 @@ class GenericOSMAPIObject(ABC):
                 f"failed to create {self._logObjectName}. Http code: {http_code}. Message: {msg}"
             )
 
-    def create(self, name, content_dict=None, filename=None):
+    def create(self, name, content_dict=None, filename=None, endpoint=None):
         """Creates a new Generic OSM API Object"""
         self._logger.debug(f"Creating Generic OSM API Object {name}")
         self._client.get_token()
+        if not endpoint:
+            endpoint = self._apiBase
         # If filename is dir, generate a tar.gz file
         tempdir = None
         if filename:
@@ -238,7 +240,7 @@ class GenericOSMAPIObject(ABC):
             # Typical case. Only a dict
             self._logger.debug("Sending only a dict")
             _, resp = self._http.post_cmd(
-                endpoint=self._apiBase,
+                endpoint=endpoint,
                 postfields_dict=content_dict,
                 skip_query_admin=True,
             )
@@ -260,13 +262,13 @@ class GenericOSMAPIObject(ABC):
             self._logger.debug(f"formfile: {formfile}")
             self.set_http_headers(filename, multipart=True)
             _, resp = self._http.post_cmd(
-                endpoint=self._apiBase, postdata=content_dict, formfile=formfile
+                endpoint=endpoint, postdata=content_dict, formfile=formfile
             )
         elif not content_dict and filename:
             self._logger.debug("Sending only a file")
             # Only a file to be sent
             self.set_http_headers(filename)
-            _, resp = self._http.post_cmd(endpoint=self._apiBase, filename=filename)
+            _, resp = self._http.post_cmd(endpoint=endpoint, filename=filename)
         if resp:
             resp = json.loads(resp)
             self._logger.debug(f"Resp: {resp}")