--- /dev/null
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# 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.
+#######################################################################################
+
+import logging
+import click
+import yaml
+from osmclient.cli_commands import common, utils
+from osmclient.common.exceptions import ClientException
+from osmclient.common import print_output
+
+logger = logging.getLogger("osmclient")
+
+
+def get_oka_id(ctx, oka_name):
+ """Get the ID of an OKA by name or ID"""
+ logger.debug("")
+ resp = ctx.obj.oka.get(oka_name)
+ logger.debug("OKA obtained: %s", resp)
+ if "_id" in resp:
+ return resp["_id"]
+ else:
+ raise ClientException("Unexpected failure when reading the OKA")
+
+
+def get_profile_id(ctx, profile, profile_type):
+ """Get the ID of a profile of a specifc profile_type by name or ID"""
+ logger.debug("")
+ get_function = {
+ "infra-controller-profile": ctx.obj.infra_controller_profile.get,
+ "infra-config-profile": ctx.obj.infra_config_profile.get,
+ "app-profile": ctx.obj.app_profile.get,
+ "resource-profile": ctx.obj.resource_profile.get,
+ }
+ resp = get_function[profile_type](profile)
+ logger.debug("Profile obtained: %s", resp)
+ if "_id" in resp:
+ return resp["_id"]
+ else:
+ raise ClientException("Unexpected failure when reading the profile")
+
+
+@click.command(name="app-create", short_help="creates an App Instance")
+@utils.require_hostname
+@click.argument("name")
+@click.option("--description", default="", help="human readable description")
+@click.option(
+ "--oka",
+ default="",
+ help="name or ID of the OKA that the App Instance will be based on",
+)
+@click.option(
+ "--sw-catalog-path",
+ default="",
+ help="folder in the SW catalog (git repo) that the App Instance will be based on",
+)
+@click.option(
+ "--profile",
+ default="",
+ help="name or ID of the profile the App Instance will belong to",
+)
+@click.option(
+ "--profile-type",
+ type=click.Choice(
+ [
+ "infra-controller-profile",
+ "infra-config-profile",
+ "app-profile",
+ "resource-profile",
+ ]
+ ),
+ default="app-profile",
+ help="type of profile. Default: app-profile",
+)
+@click.option(
+ "--model",
+ default=None,
+ help="specific yaml file with App Instance model file (to be merged with App blueprint model file)",
+)
+@click.option(
+ "--params",
+ default=None,
+ help="specific yaml file with clear params for the App Instance",
+)
+@click.option(
+ "--secret-params",
+ default=None,
+ help="specific yaml file with secret params for the App Instance",
+)
+@click.pass_context
+def app_create(
+ ctx,
+ name,
+ description,
+ oka,
+ sw_catalog_path,
+ profile,
+ profile_type,
+ model,
+ params,
+ secret_params,
+):
+ """creates an App Instance
+
+ NAME: name of the App Instance to be created
+ """
+ logger.debug("")
+ profile_type_mapping = {
+ "infra-controller-profile": "infra_controller_profiles",
+ "infra-config-profile": "infra_config_profiles",
+ "app-profile": "app_profiles",
+ "resource-profile": "resource_profiles",
+ }
+ app = {}
+ app["name"] = name
+ if description:
+ app["description"] = description
+ if oka and sw_catalog_path:
+ raise ClientException(
+ '"--oka" option is incompatible with "--sw-catalog-path" option'
+ )
+ if oka:
+ app["oka"] = get_oka_id(ctx, oka)
+ if sw_catalog_path:
+ app["sw_catalog_path"] = sw_catalog_path
+ app["profile_type"] = profile_type_mapping[profile_type]
+ app["profile"] = get_profile_id(ctx, profile, profile_type)
+ if model:
+ with open(model, "r", encoding="utf-8") as cf:
+ model_data = cf.read()
+ try:
+ app["model"] = yaml.safe_load(model_data)
+ except yaml.YAMLError as e:
+ raise ClientException(f"Error parsing YAML configuration: {e}") from e
+ if params:
+ with open(params, "r", encoding="utf-8") as cf:
+ params_data = cf.read()
+ try:
+ app["params"] = yaml.safe_load(params_data)
+ except yaml.YAMLError as e:
+ raise ClientException(f"Error parsing YAML configuration: {e}") from e
+ if secret_params:
+ with open(secret_params, "r", encoding="utf-8") as cf:
+ secret_params_data = cf.read()
+ try:
+ app["secret_params"] = yaml.safe_load(secret_params_data)
+ except yaml.YAMLError as e:
+ raise ClientException(f"Error parsing YAML configuration: {e}") from e
+ ctx.obj.app.create(name, content_dict=app)
+
+
+@click.command(name="app-delete", short_help="deletes an App Instance cluster")
+@utils.require_hostname
+@click.argument("name")
+@click.option(
+ "--force", is_flag=True, help="forces the deletion from the DB (not recommended)"
+)
+@click.pass_context
+def app_delete(ctx, name, force):
+ """deletes an App Instance
+
+ NAME: name or ID of the App Instance to be deleted
+ """
+ logger.debug("")
+ ctx.obj.app.delete(name, force=force)
+
+
+@click.command(name="app-list")
+@utils.require_hostname
+@click.option(
+ "--filter",
+ help="restricts the list to the items matching the filter",
+)
+@print_output.output_option
+@click.pass_context
+def app_list(ctx, filter, output):
+ """list all App instances"""
+ logger.debug("")
+ common.generic_list(callback=ctx.obj.app.list, filter=filter, format=output)
+
+
+@click.command(name="app-show", short_help="shows the details of an app instance")
+@utils.require_hostname
+@click.argument("name")
+@print_output.output_option
+@click.pass_context
+def app_show(ctx, name, output):
+ """shows the details of an App instance
+
+ NAME: name or ID of the App instance to be shown
+ """
+ logger.debug("")
+ common.generic_show(callback=ctx.obj.app.get, name=name, format=output)
+
+
+@click.command(
+ name="app-edit", short_help="updates name or description of an App Instance"
+)
+@utils.require_hostname
+@click.argument("name")
+@click.option("--newname", help="New name for the App Instance")
+@click.option("--description", help="human readable description")
+@click.pass_context
+def app_edit(ctx, name, newname, description, **kwargs):
+ """updates the name or description of an App Instance
+
+ NAME: name or ID of the App Instance to be updated
+ """
+ logger.debug("")
+ app_changes = common.generic_update(newname, description, kwargs)
+ ctx.obj.app.update(name, changes_dict=app_changes)
+
+
+@click.command(name="app-update", short_help="updates an App Instance")
+@utils.require_hostname
+@click.argument("name")
+@click.option("--newname", help="New name for the App Instance")
+@click.option("--description", default="", help="human readable description")
+@click.option(
+ "--oka",
+ default="",
+ help="name or ID of the OKA that the App Instance will be based on",
+)
+@click.option(
+ "--sw-catalog-path",
+ default="",
+ help="folder in the SW catalog (git repo) that the App Instance will be based on",
+)
+@click.option(
+ "--profile",
+ default="",
+ help="name or ID of the profile the App Instance will belong to",
+)
+@click.option(
+ "--profile-type",
+ type=click.Choice(
+ [
+ "infra-controller-profile",
+ "infra-config-profile",
+ "app-profile",
+ "resource-profile",
+ ]
+ ),
+ default="app-profile",
+ help="type of profile. Default: app-profile",
+)
+@click.option(
+ "--model",
+ default=None,
+ help="specific yaml file with App Instance model file (to be merged with App blueprint model file)",
+)
+@click.option(
+ "--params",
+ default=None,
+ help="specific yaml file with clear params for the App Instance",
+)
+@click.option(
+ "--secret-params",
+ default=None,
+ help="specific yaml file with secret params for the App Instance",
+)
+@click.pass_context
+def app_update(
+ ctx,
+ name,
+ oka,
+ sw_catalog_path,
+ profile,
+ profile_type,
+ model,
+ params,
+ secret_params,
+):
+ """updates an App Instance
+
+ NAME: name or ID of the App Instance to be updated
+ """
+ logger.debug("")
+ app_changes = {}
+ profile_type_mapping = {
+ "infra-controller-profile": "infra_controller_profiles",
+ "infra-config-profile": "infra_config_profiles",
+ "app-profile": "app_profiles",
+ "resource-profile": "resource_profiles",
+ }
+ if oka and sw_catalog_path:
+ raise ClientException(
+ '"--oka" option is incompatible with "--sw-catalog-path" option'
+ )
+ if oka:
+ app_changes["oka"] = get_oka_id(ctx, oka)
+ if sw_catalog_path:
+ app_changes["sw_catalog_path"] = sw_catalog_path
+ app_changes["profile_type"] = profile_type_mapping[profile_type]
+ app_changes["profile"] = get_profile_id(ctx, profile, profile_type)
+ if model:
+ with open(model, "r", encoding="utf-8") as cf:
+ model_data = cf.read()
+ try:
+ app_changes["model"] = yaml.safe_load(model_data)
+ except yaml.YAMLError as e:
+ raise ClientException(f"Error parsing YAML configuration: {e}") from e
+ if params:
+ with open(params, "r", encoding="utf-8") as cf:
+ params_data = cf.read()
+ try:
+ app_changes["params"] = yaml.safe_load(params_data)
+ except yaml.YAMLError as e:
+ raise ClientException(f"Error parsing YAML configuration: {e}") from e
+ if secret_params:
+ with open(secret_params, "r", encoding="utf-8") as cf:
+ secret_params_data = cf.read()
+ try:
+ app_changes["secret_params"] = yaml.safe_load(secret_params_data)
+ except yaml.YAMLError as e:
+ raise ClientException(f"Error parsing YAML configuration: {e}") from e
+ ctx.obj.app.fullupdate(name, app_changes)