Addition of PaaS
[osm/osmclient.git] / osmclient / scripts / osm.py
index 397d932..de121b1 100755 (executable)
@@ -1014,7 +1014,7 @@ def ns_op_list(ctx, name, long):
             action_name = op["operationParams"]["primitive"]
         detail = "-"
         if op["operationState"] == "PROCESSING":
-            if op["queuePosition"] is not None and op["queuePosition"] > 0:
+            if op.get("queuePosition") is not None and op.get("queuePosition") > 0:
                 detail = "In queue. Current position: {}".format(op["queuePosition"])
             elif op["lcmOperationType"] in ("instantiate", "terminate"):
                 if op["stage"]:
@@ -3082,6 +3082,20 @@ def pdu_delete(ctx, name, force):
 #################
 
 
+def _check_ca_cert(vim_config: dict) -> None:
+    """
+    Checks if the VIM has a CA certificate.
+    In that case, reads the content and add it to the config
+    : param vim_config: configuration provided with the VIM creation
+    : return: None
+    """
+
+    if vim_config.get("ca_cert"):
+        with open(vim_config["ca_cert"], "r") as cert_f:
+            vim_config["ca_cert_content"] = str(cert_f.read())
+            del vim_config["ca_cert"]
+
+
 @cli_osm.command(name="vim-create", short_help="creates a new VIM account")
 @click.option("--name", required=True, help="Name to create datacenter")
 @click.option("--user", default=None, help="VIM username")
@@ -3166,6 +3180,7 @@ def vim_create(
     if vca:
         vim["vca"] = vca
     vim_config = create_config(config_file, config)
+    _check_ca_cert(vim_config)
     if creds:
         with open(creds, "r") as cf:
             vim_config["credentials"] = yaml.safe_load(cf.read())
@@ -3263,6 +3278,7 @@ def vim_update(
     vim_config = None
     if config or config_file:
         vim_config = create_config(config_file, config)
+        _check_ca_cert(vim_config)
     if creds:
         with open(creds, "r") as cf:
             vim_config["credentials"] = yaml.safe_load(cf.read())
@@ -3614,7 +3630,7 @@ def wim_show(ctx, name):
     check_client_version(ctx.obj, ctx.command.name)
     resp = ctx.obj.wim.get(name)
     if "password" in resp:
-        resp["wim_password"] = "********"
+        resp["password"] = "********"
     # except ClientException as e:
     #     print(str(e))
     #     exit(1)
@@ -3863,16 +3879,10 @@ def sdnc_show(ctx, name):
     accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"''',
 )
 @click.option(
-    "--init-helm2/--skip-helm2",
-    required=False,
-    default=True,
-    help="Initialize helm v2",
+    "--init-helm2/--skip-helm2", required=False, default=True, help="Initialize helm v2"
 )
 @click.option(
-    "--init-helm3/--skip-helm3",
-    required=False,
-    default=True,
-    help="Initialize helm v3",
+    "--init-helm3/--skip-helm3", required=False, default=True, help="Initialize helm v3"
 )
 @click.option(
     "--init-jujubundle/--skip-jujubundle",
@@ -4192,11 +4202,7 @@ def k8scluster_show(ctx, name, literal):
     prompt=True,
     help="Name of the cloud credentialsto be used for the K8s cloud",
 )
-@click.option(
-    "--model-config",
-    default={},
-    help="Configuration options for the models",
-)
+@click.option("--model-config", default={}, help="Configuration options for the models")
 @click.option("--description", default=None, help="human readable description")
 @click.pass_context
 def vca_add(
@@ -4285,10 +4291,7 @@ def load_file(file_path: str) -> Dict:
     "--k8s-credentials",
     help="Name of the cloud credentialsto be used for the K8s cloud",
 )
-@click.option(
-    "--model-config",
-    help="Configuration options for the models",
-)
+@click.option("--model-config", help="Configuration options for the models")
 @click.option("--description", default=None, help="human readable description")
 @click.pass_context
 def vca_update(
@@ -4424,6 +4427,193 @@ def vca_show(ctx, name, literal):
     print(table)
 
 
+###########################
+# PaaS operations
+###########################
+
+
+@cli_osm.command(name="paas-add", short_help="adds a PaaS to OSM.")
+@click.argument("name")
+@click.option(
+    "--paas_type",
+    type=click.Choice(["juju"]),
+    default="juju",
+    prompt=True,
+    help="Type of PaaS that can be used. (For the moment, only juju is supported).",
+)
+@click.option(
+    "--endpoints",
+    prompt=True,
+    help="Comma-separated list of IP or hostnames of the PaaS.",
+)
+@click.option("--user", prompt=True, help="Username with admin priviledges.")
+@click.option("--secret", prompt=True, help="Password of the specified username.")
+@click.option(
+    "--config", default={}, help="Extra configuration needed by PaaS service."
+)
+@click.option("--description", default=None, help="Human readable description.")
+@click.pass_context
+def paas_add(ctx, name, paas_type, endpoints, user, secret, config, description):
+    """adds a PaaS to OSM.
+    Args:
+        name (str): Name of the new PaaS.
+    """
+    check_client_version(ctx.obj, ctx.command.name)
+    paas = {
+        "name": name,
+        "paas_type": paas_type,
+        "endpoints": endpoints.split(","),
+        "user": user,
+        "secret": secret,
+    }
+    if description:
+        paas["description"] = description
+    if config:
+        config = load(config)
+        paas["config"] = config
+    ctx.obj.paas.create(paas)
+
+
+@cli_osm.command(name="paas-update", short_help="updates a PaaS")
+@click.argument("name")
+@click.option("--newname", help="New name for the PaaS")
+@click.option(
+    "--paas_type",
+    type=click.Choice(["juju"]),
+    help="Type of PaaS that can be used. (For the moment, only juju is supported)",
+)
+@click.option(
+    "--endpoints", help="Comma-separated list of IP or hostnames of the Juju controller"
+)
+@click.option("--user", help="Username with admin priviledges")
+@click.option("--secret", help="Password of the specified username")
+@click.option("--config", help="Extra configuration needed by PaaS service")
+@click.option("--description", default=None, help="Human readable description")
+@click.pass_context
+def paas_update(
+    ctx, name, newname, paas_type, endpoints, user, secret, config, description
+):
+    """updates a PaaS.
+    Args:
+        name (str): Name or ID of the PaaS to update.
+    """
+    check_client_version(ctx.obj, ctx.command.name)
+    paas = {}
+    if newname:
+        paas["name"] = newname
+    if paas_type:
+        paas["paas_type"] = paas_type
+    if endpoints:
+        paas["endpoints"] = endpoints.split(",")
+    if user:
+        paas["user"] = user
+    if secret:
+        paas["secret"] = secret
+    if description:
+        paas["description"] = description
+    if config:
+        config = load(config)
+        paas["config"] = config
+    ctx.obj.paas.update(name, paas)
+
+
+@cli_osm.command(name="paas-delete", short_help="deletes a PaaS")
+@click.argument("name")
+@click.option(
+    "--force", is_flag=True, help="forces the deletion from the DB (not recommended)"
+)
+@click.pass_context
+def paas_delete(ctx, name, force):
+    """deletes a PaaS.
+
+    Args:
+        name (str): Name or ID of the PaaS to delete.
+    """
+    check_client_version(ctx.obj, ctx.command.name)
+    ctx.obj.paas.delete(name, force=force)
+
+
+@cli_osm.command(name="paas-list")
+@click.option(
+    "--filter",
+    default=None,
+    multiple=True,
+    help="Restricts the list to the PaaS matching the filter",
+)
+@click.option("--literal", is_flag=True, help="Print literally, no pretty table")
+@click.option("--long", is_flag=True, help="get more details")
+@click.pass_context
+def paas_list(ctx, filter, literal, long):
+    """List PaaSs"""
+    check_client_version(ctx.obj, ctx.command.name)
+    if filter:
+        filter = "&".join(filter)
+    resp = ctx.obj.paas.list(filter)
+    if literal:
+        print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
+        return
+
+    table = _get_paas_table_header(long)
+    project_list = ctx.obj.project.list()
+    for paas in resp:
+        logger.debug("PaaS details: {}".format(yaml.safe_dump(paas)))
+        if long:
+            _add_paas_long_row(table, paas, project_list)
+        else:
+            _add_paas_row(table, paas)
+    table.align = "l"
+    print(table)
+
+
+def _get_paas_table_header(long):
+    if long:
+        return PrettyTable(
+            ["Name", "Id", "Project", "Operational State", "Detailed Status"]
+        )
+    return PrettyTable(["Name", "Id", "Operational State"])
+
+
+def _add_paas_long_row(table, paas, project_list):
+    _, project_name = get_project(project_list, paas)
+    detailed_status = paas.get("_admin", {}).get("detailed-status", "-")
+    table.add_row(
+        [
+            paas["name"],
+            paas["_id"],
+            project_name,
+            paas.get("_admin", {}).get("operationalState", "-"),
+            wrap_text(text=detailed_status, width=40),
+        ]
+    )
+
+
+def _add_paas_row(table, paas):
+    table.add_row(
+        [paas["name"], paas["_id"], paas.get("_admin", {}).get("operationalState", "-")]
+    )
+
+
+@cli_osm.command(name="paas-show", short_help="Shows the details of a PaaS")
+@click.argument("name")
+@click.option("--literal", is_flag=True, help="Print literally, no pretty table")
+@click.pass_context
+def paas_show(ctx, name, literal):
+    """Shows the details of a PaaS.
+
+    Args:
+        name (str): Name or ID of the PaaS to show.
+    """
+    resp = ctx.obj.paas.get(name)
+    if literal:
+        print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
+        return
+    table = PrettyTable(["key", "attribute"])
+    for k, v in list(resp.items()):
+        table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)])
+    table.align = "l"
+    print(table)
+
+
 ###########################
 # Repo operations
 ###########################
@@ -5618,10 +5808,7 @@ def update(ctx, ns_name, updatetype, config, timeout, wait):
     NS_NAME: Network service instance name or ID.
 
     """
-    op_data = {
-        "timeout": timeout,
-        "updateType": updatetype,
-    }
+    op_data = {"timeout": timeout, "updateType": updatetype}
     if config:
         op_data["config"] = yaml.safe_load(config)
 
@@ -5753,16 +5940,11 @@ def process_ns_heal_params(ctx, param, value):
 @cli_osm.command(
     name="ns-heal",
     short_help="heals (recreates) VNFs or VDUs of a NS instance",
-    context_settings=dict(
-        ignore_unknown_options=True,
-    ),
+    context_settings=dict(ignore_unknown_options=True),
 )
 @click.argument("ns_name")
 @click.argument(
-    "args",
-    nargs=-1,
-    type=click.UNPROCESSED,
-    callback=process_ns_heal_params,
+    "args", nargs=-1, type=click.UNPROCESSED, callback=process_ns_heal_params
 )
 @click.option("--timeout", type=int, default=None, help="timeout in seconds")
 @click.option(
@@ -5845,16 +6027,11 @@ def process_vnf_heal_params(ctx, param, value):
 @cli_osm.command(
     name="vnf-heal",
     short_help="heals (recreates) a VNF instance or the VDUs of a VNF instance",
-    context_settings=dict(
-        ignore_unknown_options=True,
-    ),
+    context_settings=dict(ignore_unknown_options=True),
 )
 @click.argument("vnf_name")
 @click.argument(
-    "args",
-    nargs=-1,
-    type=click.UNPROCESSED,
-    callback=process_vnf_heal_params,
+    "args", nargs=-1, type=click.UNPROCESSED, callback=process_vnf_heal_params
 )
 @click.option("--timeout", type=int, default=None, help="timeout in seconds")
 @click.option(
@@ -5864,14 +6041,7 @@ def process_vnf_heal_params(ctx, param, value):
     help="do not return the control immediately, but keep it until the operation is completed, or timeout",
 )
 @click.pass_context
-def vnf_heal2(
-    ctx,
-    vnf_name,
-    args,
-    heal_params,
-    timeout,
-    wait,
-):
+def vnf_heal2(ctx, vnf_name, args, heal_params, timeout, wait):
     """heals (recreates) a VNF instance or the VDUs of a VNF instance
 
     VNF_NAME: name or ID of the VNF instance
@@ -6410,7 +6580,7 @@ def cli():
         print(
             'Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified'
         )
-    except ClientException as exc:
+    except (ClientException, NotFound) as exc:
         print("ERROR: {}".format(exc))
     except (FileNotFoundError, PermissionError) as exc:
         print("Cannot open file: {}".format(exc))