From a112ebd160d3acc20e6766d8550d757a0581797d Mon Sep 17 00:00:00 2001 From: Lukasz Rajewski Date: Tue, 22 Mar 2022 00:52:38 +0100 Subject: [PATCH] [APACHE] Add Apache CNF use case files Issue-ID: INT-2094 Signed-off-by: Lukasz Rajewski Signed-off-by: Michal Chabiera Signed-off-by: Michal Grzesik Change-Id: Ie8f72b9804f1055f49e1bc85dd0d712841eb0f5d --- .coafile | 5 +- tutorials/ApacheCNF/README.txt | 13 + tutorials/ApacheCNF/automation/Pipfile | 14 + tutorials/ApacheCNF/automation/README.md | 32 + tutorials/ApacheCNF/automation/__init__.py | 19 + .../automation/artifacts/cluster_kubeconfig | 0 tutorials/ApacheCNF/automation/config.py | 142 ++ .../ApacheCNF/automation/create_cloud_regions.py | 202 +++ tutorials/ApacheCNF/automation/delete.py | 131 ++ tutorials/ApacheCNF/automation/healthcheck.py | 92 ++ tutorials/ApacheCNF/automation/instantiate.py | 474 ++++++ tutorials/ApacheCNF/automation/k8s_client.py | 59 + tutorials/ApacheCNF/automation/onap_settings.py | 73 + tutorials/ApacheCNF/automation/onboard.py | 213 +++ tutorials/ApacheCNF/automation/update_cba.py | 57 + .../automation/update_connectivity_info.py | 40 + tutorials/ApacheCNF/automation/vsp/.gitkeep | 0 tutorials/ApacheCNF/automation/vsp/.keep | 0 tutorials/ApacheCNF/service_config.yaml | 94 ++ tutorials/ApacheCNF/templates/.gitattributes | 1 + tutorials/ApacheCNF/templates/.gitignore | 2 + tutorials/ApacheCNF/templates/Makefile | 42 + tutorials/ApacheCNF/templates/README.txt | 1 + .../ApacheCNF/templates/base_native/MANIFEST.json | 15 + tutorials/ApacheCNF/templates/cba-dev/bootstrap.sh | 23 + tutorials/ApacheCNF/templates/cba-dev/build.sh | 39 + tutorials/ApacheCNF/templates/cba-dev/deploy.sh | 22 + tutorials/ApacheCNF/templates/cba-dev/enrich.sh | 23 + .../ApacheCNF/templates/cba-dev/run-vf-base-ra.sh | 65 + .../ApacheCNF/templates/cba-dev/run-vnf-config.sh | 49 + .../ApacheCNF/templates/cba-dev/run-vnf-ra.sh | 57 + .../ApacheCNF/templates/cba/Definitions/CNF.json | 853 +++++++++++ .../templates/cba/Definitions/artifact_types.json | 30 + .../templates/cba/Definitions/data_types.json | 363 +++++ .../templates/cba/Definitions/node_types.json | 676 +++++++++ .../templates/cba/Definitions/policy_types.json | 3 + .../cba/Definitions/relationship_types.json | 3 + .../Definitions/resources_definition_types.json | 1516 ++++++++++++++++++++ .../cba/Scripts/kotlin/CollectorScript.kt | 53 + .../templates/cba/Scripts/kotlin/ConfigDeploy.kt | 48 + .../cba/Scripts/kotlin/ConfigDeploySetup.kt | 145 ++ .../templates/cba/Scripts/kotlin/K8sHealthCheck.kt | 125 ++ .../templates/cba/Scripts/kotlin/README.md | 1 + .../cba/Scripts/kotlin/SimpleErrorCheck.kt | 41 + .../cba/Scripts/kotlin/SimpleStatusCheck.kt | 81 ++ .../templates/cba/TOSCA-Metadata/TOSCA.meta | 8 + .../templates/cba/Templates/cnf-mapping.json | 314 ++++ .../templates/cba/Templates/cnf-template.vtl | 67 + .../cba/Templates/config-setup-mapping.json | 105 ++ .../cba/Templates/config-setup-template.vtl | 1 + .../Templates/k8s-configs/deployment-config.tar.gz | Bin 0 -> 13406 bytes .../k8s-configs/deployment-config/Chart.yaml | 6 + .../deployment-config/charts/common/.helmignore | 22 + .../deployment-config/charts/common/Chart.yaml | 22 + .../deployment-config/charts/common/README.md | 286 ++++ .../charts/common/templates/_affinities.tpl | 94 ++ .../charts/common/templates/_capabilities.tpl | 33 + .../charts/common/templates/_errors.tpl | 20 + .../charts/common/templates/_images.tpl | 43 + .../charts/common/templates/_labels.tpl | 18 + .../charts/common/templates/_names.tpl | 32 + .../charts/common/templates/_secrets.tpl | 57 + .../charts/common/templates/_storage.tpl | 23 + .../charts/common/templates/_tplvalues.tpl | 13 + .../charts/common/templates/_utils.tpl | 45 + .../charts/common/templates/_validations.tpl | 278 ++++ .../charts/common/templates/_warnings.tpl | 14 + .../deployment-config/charts/common/values.yaml | 3 + .../deployment-config/templates/_helpers.tpl | 263 ++++ .../deployment-config/templates/deployment.yaml | 172 +++ .../k8s-configs/deployment-config/values.yaml | 310 ++++ .../deployment-values/default-values.yaml | 3 + .../deployment-values/restore-values.yaml | 3 + .../deployment-values/values-mapping.json | 14 + .../k8s-configs/deployment-values/values.yaml.vtl | 3 + .../k8s-profiles/cnf-cds-base-profile.tar.gz | Bin 0 -> 213 bytes .../k8s-profiles/node-port-profile.tar.gz | Bin 0 -> 225 bytes .../templates/cba/Templates/vnf-mapping.json | 104 ++ .../templates/cba/Templates/vnf-template.vtl | 22 + tutorials/ApacheCNF/templates/cba/pom.xml | 68 + tutorials/ApacheCNF/templates/cba2dd.py | 91 ++ tutorials/ApacheCNF/templates/helm/.gitignore | 1 + tutorials/ApacheCNF/templates/helm/Makefile | 17 + tutorials/ApacheCNF/templates/helm/README.txt | 7 + tutorials/ApacheCNF/templates/tools/tail_all.sh | 161 +++ tutorials/ApacheCNF/templates/tools/tail_config | 18 + 86 files changed, 8696 insertions(+), 2 deletions(-) create mode 100644 tutorials/ApacheCNF/README.txt create mode 100644 tutorials/ApacheCNF/automation/Pipfile create mode 100644 tutorials/ApacheCNF/automation/README.md create mode 100644 tutorials/ApacheCNF/automation/__init__.py create mode 100644 tutorials/ApacheCNF/automation/artifacts/cluster_kubeconfig create mode 100644 tutorials/ApacheCNF/automation/config.py create mode 100644 tutorials/ApacheCNF/automation/create_cloud_regions.py create mode 100644 tutorials/ApacheCNF/automation/delete.py create mode 100644 tutorials/ApacheCNF/automation/healthcheck.py create mode 100644 tutorials/ApacheCNF/automation/instantiate.py create mode 100644 tutorials/ApacheCNF/automation/k8s_client.py create mode 100644 tutorials/ApacheCNF/automation/onap_settings.py create mode 100644 tutorials/ApacheCNF/automation/onboard.py create mode 100644 tutorials/ApacheCNF/automation/update_cba.py create mode 100644 tutorials/ApacheCNF/automation/update_connectivity_info.py create mode 100644 tutorials/ApacheCNF/automation/vsp/.gitkeep create mode 100644 tutorials/ApacheCNF/automation/vsp/.keep create mode 100644 tutorials/ApacheCNF/service_config.yaml create mode 100644 tutorials/ApacheCNF/templates/.gitattributes create mode 100644 tutorials/ApacheCNF/templates/.gitignore create mode 100644 tutorials/ApacheCNF/templates/Makefile create mode 100644 tutorials/ApacheCNF/templates/README.txt create mode 100644 tutorials/ApacheCNF/templates/base_native/MANIFEST.json create mode 100644 tutorials/ApacheCNF/templates/cba-dev/bootstrap.sh create mode 100644 tutorials/ApacheCNF/templates/cba-dev/build.sh create mode 100644 tutorials/ApacheCNF/templates/cba-dev/deploy.sh create mode 100644 tutorials/ApacheCNF/templates/cba-dev/enrich.sh create mode 100644 tutorials/ApacheCNF/templates/cba-dev/run-vf-base-ra.sh create mode 100644 tutorials/ApacheCNF/templates/cba-dev/run-vnf-config.sh create mode 100644 tutorials/ApacheCNF/templates/cba-dev/run-vnf-ra.sh create mode 100644 tutorials/ApacheCNF/templates/cba/Definitions/CNF.json create mode 100644 tutorials/ApacheCNF/templates/cba/Definitions/artifact_types.json create mode 100644 tutorials/ApacheCNF/templates/cba/Definitions/data_types.json create mode 100644 tutorials/ApacheCNF/templates/cba/Definitions/node_types.json create mode 100644 tutorials/ApacheCNF/templates/cba/Definitions/policy_types.json create mode 100644 tutorials/ApacheCNF/templates/cba/Definitions/relationship_types.json create mode 100644 tutorials/ApacheCNF/templates/cba/Definitions/resources_definition_types.json create mode 100644 tutorials/ApacheCNF/templates/cba/Scripts/kotlin/CollectorScript.kt create mode 100644 tutorials/ApacheCNF/templates/cba/Scripts/kotlin/ConfigDeploy.kt create mode 100644 tutorials/ApacheCNF/templates/cba/Scripts/kotlin/ConfigDeploySetup.kt create mode 100644 tutorials/ApacheCNF/templates/cba/Scripts/kotlin/K8sHealthCheck.kt create mode 100644 tutorials/ApacheCNF/templates/cba/Scripts/kotlin/README.md create mode 100644 tutorials/ApacheCNF/templates/cba/Scripts/kotlin/SimpleErrorCheck.kt create mode 100644 tutorials/ApacheCNF/templates/cba/Scripts/kotlin/SimpleStatusCheck.kt create mode 100644 tutorials/ApacheCNF/templates/cba/TOSCA-Metadata/TOSCA.meta create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/cnf-mapping.json create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/cnf-template.vtl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/config-setup-mapping.json create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/config-setup-template.vtl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config.tar.gz create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/Chart.yaml create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/.helmignore create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/Chart.yaml create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/README.md create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_affinities.tpl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_capabilities.tpl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_errors.tpl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_images.tpl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_labels.tpl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_names.tpl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_secrets.tpl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_storage.tpl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_tplvalues.tpl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_utils.tpl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_validations.tpl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_warnings.tpl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/values.yaml create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/templates/_helpers.tpl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/templates/deployment.yaml create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/values.yaml create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/default-values.yaml create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/restore-values.yaml create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/values-mapping.json create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/values.yaml.vtl create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-profiles/cnf-cds-base-profile.tar.gz create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/k8s-profiles/node-port-profile.tar.gz create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/vnf-mapping.json create mode 100644 tutorials/ApacheCNF/templates/cba/Templates/vnf-template.vtl create mode 100644 tutorials/ApacheCNF/templates/cba/pom.xml create mode 100644 tutorials/ApacheCNF/templates/cba2dd.py create mode 100644 tutorials/ApacheCNF/templates/helm/.gitignore create mode 100644 tutorials/ApacheCNF/templates/helm/Makefile create mode 100644 tutorials/ApacheCNF/templates/helm/README.txt create mode 100644 tutorials/ApacheCNF/templates/tools/tail_all.sh create mode 100644 tutorials/ApacheCNF/templates/tools/tail_config diff --git a/.coafile b/.coafile index 0d741e60..47cd835f 100644 --- a/.coafile +++ b/.coafile @@ -1,10 +1,11 @@ [yaml] bears = YAMLLintBear yamllint_config = .yamllint -#[vFW_CNF_CDS] Helm tests use go template conditionals that are not yaml-compliant +# [vFW_CNF_CDS][APACHE] Helm uses go template conditionals that are not yaml-compliant ignore = .tox/**, - heat/vFW_CNF_CDS/templates/helm/**/templates/tests/* + heat/vFW_CNF_CDS/templates/helm/**/templates/tests/*, + tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/templates/* [json] bears = JSONFormatBear diff --git a/tutorials/ApacheCNF/README.txt b/tutorials/ApacheCNF/README.txt new file mode 100644 index 00000000..d1130908 --- /dev/null +++ b/tutorials/ApacheCNF/README.txt @@ -0,0 +1,13 @@ +Demo directory structure: + +/templates/ #Base directory containing vFW resources + |- /base_dummy #Directory containing base payload of VSP package in OpenStack VSP format, doesn't need further proceeding + |- /base_native #Directory containing base payload of VSP package in Helm VSP, doesn't need further proceeding + |- /helm #Directory containing helm charts that need to be packaged and attached to VSP package + \- /cba #Directory containing CBA content to be included to csar package. It is prepared for +/examples/ #Directory with context-specific overrides over general resources +/automation/ #Directory with automation scripts. For more details read README file inside. + +Note: Makefile script generates two VSP packages, one in Frankfurt format with helm associated with dummy heat templates and second +with native Helm VSP format where helm packages are standalone. CBA folder contains CBA Definition for native VSP format but +make is coverting the definition into Frankfurt format for Frankfurt VSP. Frankfurt VSP is still supported in Guilin. diff --git a/tutorials/ApacheCNF/automation/Pipfile b/tutorials/ApacheCNF/automation/Pipfile new file mode 100644 index 00000000..a8e79269 --- /dev/null +++ b/tutorials/ApacheCNF/automation/Pipfile @@ -0,0 +1,14 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] + +[packages] +onapsdk = "==9.3.0" +markupsafe = "==2.0.1" +kubernetes = "*" + +[requires] +python_version = "3.8" diff --git a/tutorials/ApacheCNF/automation/README.md b/tutorials/ApacheCNF/automation/README.md new file mode 100644 index 00000000..5b2b80b3 --- /dev/null +++ b/tutorials/ApacheCNF/automation/README.md @@ -0,0 +1,32 @@ +# CNF automation + +0. Make sure you have python 3.8.x installed and default interpreter, what is required by onap-pythonsdk +1. Install required packages with pipenv `pipenv install` +2. Run virtual environment `pipenv shell`. In case of problems you maye try also `--fancy` option + + **In case of problems with pipenv:** `venv` can be used as well. In that case, please install all required python packages in correct version according the list in `Pipfile` +3. Add kubeconfig file for k8s cluster that will host your CNF. Apache can be deployed on any standard cluster but with defult values it need LoadBlanacer + - `artifacts/kubeconfig` +4. Prepare onboarding packages `cd ../templates/ && make && cd ../automation/` +5. Modify `service_config.yaml`. Please note that the configuration file has yaml syntax but also is jinja templated + and values defined in the configuration file may be used also in the jinja templaring process. Templating is an iterative process unless all the values are + not resolved. Please not that in most cases you don't have to modify this file at all, despite the configuration of your k8s cluster. + We recommend to modify only values from the 'UserParams' section: + - cnf_name - name of CNF + - k8s_namespace - k8s namespace to use for deployment of CNF + - k8s_version - version of the k8s cluster (important for proper helm templating) + - k8s_region - name of the k8s region that we want to create in ONAP + - release_name - name of the rleease of the helm application (user for naming of k8s resources) + - profile_source - source of the k8s profile with values - in our case it may be used to change from LoandBalanser to NodePort service type + - skip_day_2 - it defined the SKIP_POST_INSTANTIATION flag in SDC models. The value is used in the SDC service model name +6. Verify service_config.yaml by running `python config.py` +7. __Important:__ Before running python scripts, some settings for `onapsdk` with information about ONAP endpoints (and socks) have to be exported. + All settings for ONAP instance are located in `automation/onap_settings.py` file. To export that settings please run command inside `pipenv` or `venv` shell + ```shell + (automation) ubuntu@onap:~/automation$ export ONAP_PYTHON_SDK_SETTINGS="onap_settings" + ``` +8. Run script `python create_cloud_regions.py` in order to create **k8s or openstack cloud region** +9. Onboard CNF `python onboard.py` +10. Instantiate CNF `python instantiate.py` +11. Once test is done, CNF service instance can be deleted with `python delete.py` command + diff --git a/tutorials/ApacheCNF/automation/__init__.py b/tutorials/ApacheCNF/automation/__init__.py new file mode 100644 index 00000000..9525040e --- /dev/null +++ b/tutorials/ApacheCNF/automation/__init__.py @@ -0,0 +1,19 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2021 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +from .config import Config +from .k8s_client import K8sClient diff --git a/tutorials/ApacheCNF/automation/artifacts/cluster_kubeconfig b/tutorials/ApacheCNF/automation/artifacts/cluster_kubeconfig new file mode 100644 index 00000000..e69de29b diff --git a/tutorials/ApacheCNF/automation/config.py b/tutorials/ApacheCNF/automation/config.py new file mode 100644 index 00000000..24983671 --- /dev/null +++ b/tutorials/ApacheCNF/automation/config.py @@ -0,0 +1,142 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2021 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= +from typing import Dict, Union, List +import oyaml as yaml +import os +from jinja2 import Template + + +class VariablesDict: + env_variable = dict(os.environ) + + +class Config: + def __init__(self, filename: str = "service_config.yaml", env_dict=None, print_final_file=False): + if env_dict is None: + env_dict = {} + self.filepath = os.path.join(os.path.dirname(os.path.dirname( + os.path.realpath(__file__))), filename) + self.content_env: Dict = env_dict + self.service_instance: Union[None, Dict] = None + self.service_model: Union[None, Dict] = None + self.user_params: Union[None, Dict] = None + self.cloud_regions: Union[None, List] = None + self.so_input: Union[None, Dict] = None + self.render(print_final_file) + self.so_input = self.create_so_input() + + def _load_file(self) -> dict: + with open(self.filepath) as file: + file_content = yaml.safe_load(file) + return file_content + + @staticmethod + def templating(rend_dict: dict, render_keys: dict): + for k, v in rend_dict.items(): + if isinstance(v, str): + t = Template(v) + rend_dict[k] = t.render(**render_keys).strip() + elif isinstance(v, dict): + Config.templating(rend_dict=v, render_keys=render_keys) + elif isinstance(v, list): + for i in v: + Config.templating(rend_dict=i, render_keys=render_keys) + else: + pass + return rend_dict + + def render(self, print_final_file=False): + raw_file = self._load_file() + config_dict = self._render(templated_file=raw_file) + + while not self._completed(templated_file=config_dict): + config_dict = self._render(templated_file=config_dict) + + self.__dict__.update(**config_dict) + if print_final_file: + print(yaml.dump(config_dict, sort_keys=False)) + + def _render(self, templated_file: dict) -> dict: + config_dict = self.templating( + rend_dict=templated_file, + render_keys={**self.content_env, **templated_file}) + + return config_dict + + def _completed(self, templated_file: dict) -> bool: + for v in templated_file.values(): + if isinstance(v, str): + if "{{" in v and "}}" in v: + return False + elif isinstance(v, dict): + return self._completed(templated_file=v) + elif isinstance(v, list): + for i in v: + return self._completed(templated_file=i) + else: + pass + return True + + def create_so_input(self, other_cluster=False) -> dict: + so_input_dict = dict() + so_input_dict["subscription_service_type"] = self.service_instance.get("model_name") + _vnfs = self.service_instance.get("vnfs") + vnfs = list() + + for vnf in _vnfs: + _vnf_raw = dict() + # filter vnfs with cloud_region, code block not required with ONAP Jakrta+ + if vnf.get("cloud_region") and vnf.get("tenant_name"): + if not other_cluster: + continue + _vnf_raw["cloud_region"] = vnf.get("cloud_region") + _vnf_raw["tenant_name"] = vnf.get("tenant_name") + else: + if other_cluster: + continue + # end of filter, end of code block + _vnf_raw["model_name"] = vnf.get("model_name") + if vnf.get("vnf_name_suffix"): + _vnf_raw["instance_name"] = "Instance_" + vnf.get("model_name") + "_" + vnf.get("vnf_name_suffix") + else: + _vnf_raw["instance_name"] = "Instance_" + vnf.get("model_name") + "_" + str(_vnfs.index(vnf)) + if vnf.get("processing_priority"): + _vnf_raw["processing_priority"] = vnf.get("processing_priority") + _vnf_raw["parameters"] = vnf.get("parameters") + _vnf_raw["vf_modules"] = list() + _vf_modules = vnf.get("vf_modules") + for vf_module in _vf_modules: + _vf_module_raw = dict() + _vf_module_raw["model_name"] = vf_module.get("model_name") + if vf_module.get("vf_module_name_suffix"): + _vf_module_raw["instance_name"] = \ + "Instance_" + vf_module.get("model_name") + "_" + vf_module.get("vf_module_name_suffix") + else: + _vf_module_raw["instance_name"] = \ + "Instance_" + vf_module.get("model_name") + "_" + str(_vnfs.index(vnf)) + \ + "_" + str(_vf_modules.index(vf_module)) + if vf_module.get("processing_priority"): + _vf_module_raw["processing_priority"] = vf_module["processing_priority"] + _vf_module_raw["parameters"] = vf_module.get("parameters") + _vnf_raw["vf_modules"].append(_vf_module_raw) + vnfs.append(_vnf_raw) + so_input_dict["vnfs"] = vnfs + + return so_input_dict + +if __name__ == "__main__": + config = Config(env_dict=VariablesDict.env_variable, print_final_file=True) diff --git a/tutorials/ApacheCNF/automation/create_cloud_regions.py b/tutorials/ApacheCNF/automation/create_cloud_regions.py new file mode 100644 index 00000000..9cf94f12 --- /dev/null +++ b/tutorials/ApacheCNF/automation/create_cloud_regions.py @@ -0,0 +1,202 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2021 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +import logging +import os +from uuid import uuid4 + +from onapsdk.so.so_db_adapter import SoDbAdapter, IdentityService + +from config import Config, VariablesDict +from onapsdk.exceptions import ResourceNotFound, APIError +from onapsdk.aai.cloud_infrastructure import Complex, CloudRegion +from onapsdk.msb.k8s import ConnectivityInfo + +logger = logging.getLogger() +logger.setLevel(logging.DEBUG) + + +def create_complex(complex_id): + logger.info("******** Complex *******") + try: + region_complex = next(Complex.get_all(physical_location_id=complex_id)) + logger.info("Complex exists") + return region_complex + except ResourceNotFound: + logger.info("Complex does not exist") + region_complex = Complex.create(physical_location_id=complex_id, + name=complex_id, + physical_location_type="office", + street1="DummyStreet 1", + city="DummyCity", + postal_code="00-000", + country="DummyCountry", + region="DummyRegion") + logger.info("Complex created") + return region_complex + + +def create_cloud_region(cloud_region): + logger.info("******** Cloud Region *******") + region_id = cloud_region["name"] + cloud_owner = cloud_region["cloud_owner"] + cloud_type = cloud_region["cloud_type"] + complex_id = cloud_region["complex_id"] + cloud_region_version = "1.0" if cloud_type == "k8s" else "v2.5" + try: + region = next(CloudRegion.get_all(cloud_owner=cloud_owner, cloud_region_id=region_id)) + logger.info("Cloud region exists") + return region + except ResourceNotFound: + logger.info("Cloud region does not exist") + region = CloudRegion.create(cloud_owner=cloud_owner, + cloud_region_id=region_id, + cloud_type=cloud_type, + owner_defined_type="t1", + cloud_region_version=cloud_region_version, + complex_name=complex_id, + cloud_zone="CloudZone", + sriov_automation="false", + orchestration_disabled=False, + in_maint=False) + logger.info("Cloud region created") + return region + + +def link_region_to_complex(cloud_region, complx): + logger.info("******** Cloud region <-> Complex *******") + cloud_region.link_to_complex(complex_object=complx) + + +def add_tenant(cloud_region, tenant_id, tenant_name): + logger.info("Tenant does not exist") + cloud_region.add_tenant(tenant_id=tenant_id, + tenant_name=tenant_name) + logger.info(f"Tenant {tenant_name} added to region") + + +def add_tenants(cloud_region, k8s_region, tenants): + logger.info("******** Tenants *******") + for tenant in tenants: + tenant_name = tenant["name"] + if k8s_region: + try: + next(_tenant for _tenant in cloud_region.tenants if _tenant.name == tenant_name) + logger.info("Tenant exists") + except (StopIteration, ResourceNotFound): + tenant_id = str(uuid4()) + add_tenant(cloud_region=cloud_region, tenant_id=tenant_id, tenant_name=tenant_name) + else: + tenant_id = tenant["id"] + try: + cloud_region.get_tenant(tenant_id) + logger.info("Tenant exists") + except ResourceNotFound: + add_tenant(cloud_region=cloud_region, tenant_id=tenant_id, tenant_name=tenant_name) + + +def update_connectivity_info(region): + logger.info("******** Connectivity Info *******") + kubeconfig_path = region["kubeconfig_file"] + cloud_owner = region["cloud_owner"] + region_id = region["name"] + try: + with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), kubeconfig_path), 'rb') as kubeconfig_file: + kubeconfig = kubeconfig_file.read() + + connectivity_info = ConnectivityInfo.get_connectivity_info_by_region_id(cloud_region_id=region_id) + logger.info("Connectivity Info exists ") + logger.info("Delete Connectivity Info ") + connectivity_info.delete() + ConnectivityInfo.create(cloud_region_id=region_id, + cloud_owner=cloud_owner, + kubeconfig=kubeconfig) + logger.info("Connectivity Info created ") + except (APIError, ResourceNotFound): + logger.info("Connectivity Info does not exists ") + ConnectivityInfo.create(cloud_region_id=region_id, + cloud_owner=cloud_owner, + kubeconfig=kubeconfig) + logger.info("Connectivity Info created ") + except FileNotFoundError: + logger.error("Error - File Not Found") + logger.info("Please check if kubeconfig file exists") + exit(1) + + +def add_region_to_so_db(region): + logger.info("******** SO Database *******") + if is_k8s_region(region): + identity_service = IdentityService(identity_id="Keystone_K8s", + url="http://test:5000/v3", + mso_id="onapsdk_user", + mso_pass="mso_pass_onapsdk", + project_domain_name="NULL", + user_domain_name="NULL", + identity_server_type="KEYSTONE") + + SoDbAdapter.add_cloud_site(cloud_region_id=region["name"], + complex_id=region["complex_id"], + identity_service=identity_service, + orchestrator="multicloud") + else: + identity_url = region["identity_url"] + mso_id = region["mso_id"] + mso_pass = region["mso_pass"] + identity_server_type = region["identity_server_type"] + identity_service = IdentityService(identity_id=region["name"] + "_KEYSTONE", + url=identity_url, + mso_id=mso_id, + mso_pass=mso_pass, + project_domain_name="Default", + user_domain_name="Default", + identity_server_type=identity_server_type) + + SoDbAdapter.add_cloud_site(cloud_region_id=region["name"], + complex_id=region["complex_id"], + identity_service=identity_service, + orchestrator="NULL") + + +def is_k8s_region(region): + is_k8s = False + if region["cloud_type"] == "k8s": + is_k8s = True + return is_k8s + + +######################################################################################################################## +def main(): + config = Config(env_dict=VariablesDict.env_variable) + + for region in config.cloud_regions: + complx = create_complex(region["complex_id"]) + cloud_region = create_cloud_region(region) + link_region_to_complex(cloud_region, complx) + add_tenants(cloud_region, is_k8s_region(region), region.get("tenants")) + if is_k8s_region(region): + update_connectivity_info(region) + add_region_to_so_db(region) + + +if __name__ == "__main__": + sh = logging.StreamHandler() + sh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s') + sh.setFormatter(sh_formatter) + logger.addHandler(sh) + + main() diff --git a/tutorials/ApacheCNF/automation/delete.py b/tutorials/ApacheCNF/automation/delete.py new file mode 100644 index 00000000..00d0418b --- /dev/null +++ b/tutorials/ApacheCNF/automation/delete.py @@ -0,0 +1,131 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2021 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +import logging + +from config import Config, VariablesDict +from instantiate import get_customer, check_orchestration_status + +from onapsdk.exceptions import ResourceNotFound, APIError +from onapsdk.aai.business import ServiceInstance + +logger = logging.getLogger() +logger.setLevel(logging.DEBUG) + + +def get_service_subscription(customer, service_type): + try: + service_subscription = customer.get_service_subscription_by_service_type( + service_type=service_type) + return service_subscription + except ResourceNotFound: + logger.error("Service Subscription not found") + exit(1) + + +def get_service_instance(service_subscription, service_instance_name): + try: + service_instance = service_subscription.get_service_instance_by_name( + service_instance_name=service_instance_name) + return service_instance + except ResourceNotFound: + logger.error("Service Instance not found") + exit(1) + + +def delete_service_macro(service_instance: ServiceInstance, service_instance_info): + vnf_infos_list = [] + for index, vnf_info in enumerate(service_instance_info["vnfs"]): + if not vnf_info.get("vnf_name_suffix"): + vnf_info["vnf_name_suffix"] = str(index) + vnf_info["instance_name"] = f"Instance_{vnf_info['model_name']}_{vnf_info['vnf_name_suffix']}" + vnf_infos_list.append(vnf_info) + + ordered_vnf_instances = sorted(vnf_infos_list, + key=lambda _vnf: _vnf.get("processing_priority", 100), + reverse=True) + + delete_vnfs_instances(service_instance, ordered_vnf_instances) + + return check_orchestration_status(service_instance.delete(a_la_carte=False)) + + +def delete_vnfs_instances(service_instance: ServiceInstance, ordered_vnf_instances): + for vnf in ordered_vnf_instances: + vnf_name = vnf.get("instance_name") + vnf_instance = next((vnf_instance + for vnf_instance in service_instance.vnf_instances + if vnf_instance.vnf_name == vnf_name), None) + if not vnf_instance: + continue + + try: + vnf_deletion = vnf_instance.delete(a_la_carte=False) + except APIError: + logger.error("Operation not supported, whole service instance will be deleted with random order") + break + check_orchestration_status(vnf_deletion) + return + + +def delete_service_alacarte(service_instance): + for vnf in service_instance.vnf_instances: + for vf_module in vnf.vf_modules: + vf_module_deletion = vf_module.delete() + check_orchestration_status(vf_module_deletion) + vnf_deletion = vnf.delete() + check_orchestration_status(vnf_deletion) + service_deletion = service_instance.delete(a_la_carte=True) + check_orchestration_status(service_deletion) + + +def main(): + logger.info("*******************************") + logger.info("**** SERVICE DELETION ****") + logger.info("*******************************") + + config = Config(env_dict=VariablesDict.env_variable) + logger.info("******** GET Customer *******") + customer = get_customer(config.service_instance["customer_id"]) + + logger.info("******** Check Service Subscription *******") + service_subscription = get_service_subscription(customer, config.service_instance["model_name"]) + + logger.info("******** Get Service Instance details *******") + service_instance = get_service_instance(service_subscription, config.service_instance["instance_name"]) + + logger.info("******** Delete Service %s *******", service_instance.instance_name) + if config.service_model["macro_orchestration"]: + # if config.service_instance.get("deletion_policy") in ('InstantiationOrder', 'ReverseInstantiationOrder'): + # delete_service_macro_delete_policy(service_instance, config.service_instance) + # else: + delete_service_macro(service_instance, config.service_instance) + else: + logger.error("A_la_carte orchestration method not updated") + if config.service_model["pnfs"] is not None: + raise NotImplementedError + else: + delete_service_alacarte(service_instance) + + +if __name__ == "__main__": + sh = logging.StreamHandler() + sh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s') + sh.setFormatter(sh_formatter) + logger.addHandler(sh) + + main() diff --git a/tutorials/ApacheCNF/automation/healthcheck.py b/tutorials/ApacheCNF/automation/healthcheck.py new file mode 100644 index 00000000..aee101dd --- /dev/null +++ b/tutorials/ApacheCNF/automation/healthcheck.py @@ -0,0 +1,92 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2021 Samsung +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= +#todo update when onapsdk > 9.3.0 +import logging +import zipfile + +from onapsdk.aai.business import Customer +from onapsdk.cds.blueprint import Workflow, Blueprint + +from config import Config + +#FIXME remove from global scope +logger = logging.getLogger("") +logger.setLevel(logging.INFO) +fh = logging.StreamHandler() +fh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s') +fh.setFormatter(fh_formatter) +logger.addHandler(fh) + + +def resolve_hc_inputs(): + logger.info("******** Check Customer *******") + customer = None + for found_customer in list(Customer.get_all()): + logger.debug("Customer %s found", found_customer.subscriber_name) + if found_customer.subscriber_name == Config.GLOBAL_CUSTOMER_ID: + logger.info("Customer %s found", found_customer.subscriber_name) + customer = found_customer + break + if customer is None: + raise Exception("Customer %s wasn't found in ONAP" % Config.GLOBAL_CUSTOMER_ID) + logger.info("******** Check Service Subscription *******") + service_subscription = None + for service_sub in customer.service_subscriptions: + logger.debug("Service subscription %s is found", service_sub.service_type) + if service_sub.service_type == Config.SERVICENAME: + logger.info("Service %s subscribed", Config.SERVICENAME) + service_subscription = service_sub + break + logger.info("******** Retrieve Service Metadata *******") + service_instance = None + for single_service in service_subscription.service_instances: + if single_service.instance_name == Config.SERVICE_INSTANCE_NAME: + service_instance = single_service + break + service_id = service_instance.instance_id + vnfs = list(service_instance.vnf_instances) + if len(vnfs) > 1: + raise NotImplementedError("Service %s is composed of more than one vnf!" % service_id) + if not vnfs: + raise Exception("Service %s doesn't contain any vnfs" % service_id) + vnf_id = vnfs[0].vnf_id + return service_id, vnf_id + +def main(): + blueprint = None + with zipfile.ZipFile(Config.VSPFILE, 'r') as package: + with package.open("CBA.zip", 'r') as cba: + blueprint = Blueprint(cba.read()) + + healthcheck = Workflow('health-check', None, blueprint) + serv_id, vnf_id = resolve_hc_inputs() + cds_input = {"health-check-properties": + { + "service-instance-id": serv_id, + "vnf-id": vnf_id + } + } + logger.info("Requesting Healthcheck for CBA %s:%s with inputs:\n%s", + blueprint.metadata.template_name, + blueprint.metadata.template_version, + cds_input) + result = healthcheck.execute(cds_input) + logger.info("Healthcheck process completed with result: %s", result) + logger.info("Please check cds-blueprints-processor logs to see exact status") + +if __name__ == "__main__": + main() diff --git a/tutorials/ApacheCNF/automation/instantiate.py b/tutorials/ApacheCNF/automation/instantiate.py new file mode 100644 index 00000000..0d9dc5ef --- /dev/null +++ b/tutorials/ApacheCNF/automation/instantiate.py @@ -0,0 +1,474 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2021 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +import logging +from time import sleep + +from config import Config, VariablesDict +from onapsdk.aai.cloud_infrastructure import ( + CloudRegion +) +from onapsdk.aai.business import ( + Customer, + OwningEntity as AaiOwningEntity +) +from onapsdk.exceptions import ResourceNotFound, APIError +from onapsdk.msb.k8s import Definition +from onapsdk.so.instantiation import ( + ServiceInstantiation, + InstantiationParameter, SoService, SoServiceVnf) +from onapsdk.sdc.service import Service +# from onapsdk.vid import LineOfBusiness, OwningEntity, Platform, Project +from onapsdk.so.so_element import OrchestrationRequest +from onapsdk.aai.service_design_and_creation import Service as AaiService + +logger = logging.getLogger() +logger.setLevel(logging.DEBUG) + + +def get_customer(global_customer_id: str = "customer_cnf"): + logger.info("******** Customer *******") + try: + customer = Customer.get_by_global_customer_id(global_customer_id) + logger.info("Customer exists") + except ResourceNotFound: + logger.info("Customer does not exist") + customer = Customer.create(global_customer_id, global_customer_id, "INFRA") + logger.info("Customer created") + return customer + + +def get_service_model(model_name): + try: + service_model = next(model for model in Service.get_all() if model.name == model_name) + logger.info( + f"Found Service {service_model.name} in SDC, distribution status: {service_model.distribution_status}") + return service_model + except StopIteration: + logger.error(f"Service model {model_name} not found in SDC") + exit(1) + + +def check_service_customer_subscription(customer, service): + try: + customer.get_service_subscription_by_service_type( + service_type=service.name) + except ResourceNotFound: + return False + + logger.info(f"Customer {customer.subscriber_name} subscribed for {service.name}") + return True + + +def subscribe_service_customer(customer, service): + if not check_service_customer_subscription(customer, service): + logger.info("******** Subscribe Service *******") + customer.subscribe_service(service.name) + + +def get_cloud_region(cloud_owner, cloud_region): + try: + cloud_region_object = next(cr for cr in CloudRegion.get_all() if + cr.cloud_region_id == cloud_region and cr.cloud_owner == cloud_owner) + return cloud_region_object + except (StopIteration, ResourceNotFound): + logging.error("Cloud region not found!!!") + exit(1) + + +def get_tenant(cloud_region, tenant_name): + try: + tenant = next(tenant for tenant in cloud_region.tenants if tenant.name == tenant_name) + return tenant + except (StopIteration, ResourceNotFound): + logger.error(f"Tenant {tenant_name} not found") + exit(1) + + +def add_owning_entity(owning_entity): + logger.info("******** Add Owning Entity to AAI *******") + try: + aai_owning_entity = AaiOwningEntity.get_by_owning_entity_name(owning_entity) + except ResourceNotFound: + logger.info("******** Owning Entity not existing: create *******") + aai_owning_entity = AaiOwningEntity.create(owning_entity) + + return aai_owning_entity + + +def delete_old_profiles(service, service_config): + for vnf in service.vnfs: + vnf_config_details = next( + (_vnf for _vnf in service_config["vnfs"] if _vnf["model_name"] == vnf.model_name), None) + if not vnf_config_details: + continue + for vf_module in vnf.vf_modules: + vf_module_label = next(vfm_prop.value for vfm_prop in vf_module.properties if + vfm_prop.name == "vf_module_label") + if vf_module_label == "base_template_dummy_ignore": + continue + vf_module_config_details = next((_vf_module for _vf_module in vnf_config_details["vf_modules"] if + _vf_module["model_name"] == vf_module_label), None) + if not vf_module_config_details: + continue + if "k8s-rb-profile-name" not in vf_module_config_details["parameters"]: + continue + try: + definition = Definition.get_definition_by_name_version( + rb_name=vf_module.model_invariant_uuid, + rb_version=vf_module.model_customization_id) + except APIError: + definition = Definition.get_definition_by_name_version( + rb_name=vf_module.model_invariant_uuid, + rb_version=vf_module.model_version_id) + profile_name = vf_module_config_details["parameters"]["k8s-rb-profile-name"] + try: + profile = definition.get_profile_by_name(profile_name) + namespace = None + if "k8s-rb-profile-namespace" in vnf_config_details["parameters"]: + namespace = vnf_config_details["parameters"]["k8s-rb-profile-namespace"] + if "k8s-rb-profile-namespace" in vf_module_config_details["parameters"]: + namespace = vf_module_config_details["parameters"]["k8s-rb-profile-namespace"] + if namespace is not None and profile.namespace != namespace: + profile.delete() + logger.info("Profile: " + profile_name + " for " + vf_module.name + " deleted") + else: + logger.info("No need to delete Profile " + profile_name + + " for " + vf_module.name + ". Namespace is fine") + except ResourceNotFound: + logger.info("Profile: " + profile_name + " for " + vf_module.name + " not found") + + +def check_service_instance_exists(service_subscription, service_instance_name): + try: + service_instance = next((instance for instance in service_subscription.service_instances + if instance.instance_name == service_instance_name), None) + return service_instance + except ResourceNotFound: + return None + + +def get_instantiation_parameters(properties, vnf_vf_module_config): + instantiation_parameters = [] + for property_name, property_value in properties: + instantiation_parameters.append(InstantiationParameter(name=property_name, value=property_value)) + + for instantiation_parameter_key, instantiation_parameter_value in vnf_vf_module_config["parameters"]: + instantiation_parameters.append(InstantiationParameter(name=instantiation_parameter_key, + value=instantiation_parameter_value)) + + return instantiation_parameters + + +def check_orchestration_status(instantiation): + status = None + while not (status == OrchestrationRequest.StatusEnum.COMPLETED + or status == OrchestrationRequest.StatusEnum.FAILED): + sleep(10) + status = instantiation.status + logger.info(f"Orchestration status is: {status.value}") + + if status == OrchestrationRequest.StatusEnum.FAILED: + logger.error("Orchestration was failed!") + exit(1) + else: + logger.info("Orchestration was succeed") + return + + +def get_aai_service(service_type): + logging.info("******** Retrieve product family for service *******") + try: + aai_service = next(service for service in AaiService.get_all() if service.service_id == service_type) + except (ResourceNotFound, StopIteration): + logging.info("******** Service design and creation in AAI not existing: create *******") + AaiService.create(service_id=service_type, service_description=service_type) + aai_service = next(service for service in AaiService.get_all() if service.service_id == service_type) + + return aai_service + + +def instantiate_service_macro(config, service, cloud_region, tenant, customer, owning_entity, + vid_project, vid_line_of_business, vid_platform): + service_instance_name = config.service_instance["instance_name"] + so_input = config.so_input + for vnf in so_input["vnfs"]: + _vnf = next(nf for nf in service.vnfs if nf.model_name == vnf["model_name"]) + sdnc_model_name = next(prop.value for prop in _vnf.properties if prop.name == "sdnc_model_name") + sdnc_model_version = next(prop.value for prop in _vnf.properties if prop.name == "sdnc_model_version") + sdnc_artifact_name = next(prop.value for prop in _vnf.properties if prop.name == "sdnc_artifact_name") + + vnf["parameters"]["sdnc_model_name"] = sdnc_model_name + vnf["parameters"]["sdnc_model_version"] = sdnc_model_version + vnf["parameters"]["sdnc_artifact_name"] = sdnc_artifact_name + for vf_module in vnf["vf_modules"]: + vf_module_label = vf_module["model_name"] + vf_module["parameters"]["sdnc_model_name"] = sdnc_model_name + vf_module["parameters"]["sdnc_model_version"] = sdnc_model_version + vf_module["parameters"]["vf_module_label"] = vf_module_label + + # TODO: PNF support in so_input -> first ONAPSDK + + so_service = SoService.load(so_input) + + aai_service = get_aai_service(service.name) + service_instantiation = ServiceInstantiation.instantiate_macro( + sdc_service=service, + cloud_region=cloud_region, + tenant=tenant, + customer=customer, + owning_entity=owning_entity, + project=vid_project, + line_of_business=vid_line_of_business, + platform=vid_platform, + service_instance_name=service_instance_name, + aai_service=aai_service, + so_service=so_service + ) + check_orchestration_status(service_instantiation) + + +def instantiate_vnfs_macro(config, service_subscription, line_of_business, platform): + + service_instance = check_service_instance_exists(service_subscription, config.service_instance["instance_name"]) + + so_input_vnfs_locations = config.create_so_input(other_cluster=True) + + if not so_input_vnfs_locations["vnfs"]: + return + + so_input_vnfs_by_priority = sorted(so_input_vnfs_locations["vnfs"], + key=lambda _vnf: _vnf.get("processing_priority", 100)) + + for vnf in so_input_vnfs_by_priority: + + cloud_owner_name = next( + region["cloud_owner"] for region in config.cloud_regions if region["name"] == vnf["cloud_region"]) + cloud_region = get_cloud_region(cloud_owner=cloud_owner_name, cloud_region=vnf["cloud_region"]) + + vnf_model = next(nf for nf in service_instance.sdc_service.vnfs + if nf.model_name == vnf["model_name"]) + + sdnc_model_name = next(prop.value for prop in vnf_model.properties if prop.name == "sdnc_model_name") + sdnc_model_version = next(prop.value for prop in vnf_model.properties if prop.name == "sdnc_model_version") + sdnc_artifact_name = next(prop.value for prop in vnf_model.properties if prop.name == "sdnc_artifact_name") + + vnf["parameters"]["sdnc_model_name"] = sdnc_model_name + vnf["parameters"]["sdnc_model_version"] = sdnc_model_version + vnf["parameters"]["sdnc_artifact_name"] = sdnc_artifact_name + for vf_module in vnf["vf_modules"]: + vf_module_label = vf_module["model_name"] + vf_module["parameters"]["sdnc_model_name"] = sdnc_model_name + vf_module["parameters"]["sdnc_model_version"] = sdnc_model_version + vf_module["parameters"]["vf_module_label"] = vf_module_label + + so_vnf = SoServiceVnf.load(vnf) + + vnf_instantiation = service_instance.add_vnf( + vnf=vnf_model, + line_of_business=line_of_business, + platform=platform, + cloud_region=cloud_region, + tenant=get_tenant(cloud_region=cloud_region, tenant_name=vnf["tenant_name"]), + vnf_instance_name=vnf["instance_name"], + so_vnf=so_vnf, + a_la_carte=False + ) + + check_orchestration_status(vnf_instantiation) + + +def instantiate_vf_module(vf_module, vf_module_param_list, vnf_instance, sdnc_model_name, sdnc_model_version): + vf_module_label = next(vfm_prop.value for vfm_prop in vf_module.properties if vfm_prop.name == "vf_module_label") + region_id = vf_module_param_list[vf_module_label]["cloud_configuration"] + cloud_region = get_cloud_region( + Config.CLOUD_REGIONS[region_id]["cloud_owner"], + region_id) + tenant = get_tenant(cloud_region, Config.CLOUD_REGIONS[region_id]["tenant"]["name"]) + + vfmodule_instantiation_parameters = vf_module_param_list[vf_module_label]["instantiation_parameters"].items() + + base_parameters = [ + InstantiationParameter(name="sdnc_model_name", value=sdnc_model_name), + InstantiationParameter(name="sdnc_model_version", value=sdnc_model_version), + InstantiationParameter(name="vf_module_label", value=vf_module_label)] + + for instantiation_parameter_key, instantiation_parameter_value in vfmodule_instantiation_parameters: + base_parameters.append(InstantiationParameter(name=instantiation_parameter_key, + value=instantiation_parameter_value)) + + vf_module_instantiation = vnf_instance.add_vf_module( + vf_module=vf_module, + cloud_region=cloud_region, + tenant=tenant, + vnf_parameters=base_parameters, + use_preload=False + ) + check_orchestration_status(vf_module_instantiation) + + +def check_vf_module_list_correct(vf_modules, vf_modules_config_list): + model_labels = set() + config_labels = set() + for vf_module in vf_modules: + _model_label = next(_prop.value for _prop in vf_module.properties if _prop.name == "vf_module_label") + model_labels.add(_model_label) + for vf_module in vf_modules_config_list: + config_labels.add(vf_module.model_name) + if model_labels == config_labels: + return True + else: + return False + + +def get_properties(vnf): + properties = dict() + + properties["sdnc_model_name"] = next(prop.value for prop in vnf.properties if prop.name == "sdnc_model_name") + properties["sdnc_model_version"] = next(prop.value for prop in vnf.properties if prop.name == "sdnc_model_version") + properties["sdnc_artifact_name"] = next(prop.value for prop in vnf.properties if prop.name == "sdnc_artifact_name") + + return properties + + +def instantiate_service_alacarte(config, service_subscription, service_model, cloud_region, tenant, customer, + owning_entity, + vid_project, vid_line_of_business, vid_platform): + raise NotImplementedError("Not supported since 2022") + + service_instance_name = config.service_instance["instance_name"] + # Service creation + service_instantiation = ServiceInstantiation.instantiate_ala_carte( + sdc_service=service_model, + cloud_region=cloud_region, + tenant=tenant, + customer=customer, + owning_entity=owning_entity, + project=vid_project, + service_instance_name=service_instance_name + ) + check_orchestration_status(service_instantiation) + # End of service creation + + service_instance = service_subscription.get_service_instance_by_name(service_instance_name) + # Add VNFs + for vnf in service_model.vnfs: + # TODO: priority + properties = get_properties(vnf) + vnf_config = next(_vnf for _vnf in config.service_instance["vnfs"] + if config.service_instance["vnfs"]["model_name"] == vnf.name) + vnf_parameters = get_instantiation_parameters(properties, vnf_config) + # TODO: instance name + vnf_instantiation = service_instance.add_vnf( + vnf=vnf, + line_of_business=vid_line_of_business, + platform=vid_platform, + vnf_parameters=vnf_parameters + ) + check_orchestration_status(vnf_instantiation) + + # Add vf_modules + vnf_type = service_model.name + "/" + vnf.name + vnf_instance = next((vnf for vnf in service_instance.vnf_instances if vnf.vnf_type == vnf_type), None) + + if check_vf_module_list_correct(vnf.vf_modules, vnf_config["vf_modules"]): + for vf_module in vnf.vf_modules: + vf_module_config = next(_vf for _vf in vnf_config["vf_modules"] + if _vf["model_name"] == vf_module.properties["vf_module_label"]) + vf_module_parameters = get_instantiation_parameters(properties, vf_module_config) + vf_module_instantiation = vnf_instance.add_vf_module( + vf_module=vf_module, + cloud_region=cloud_region, + tenant=tenant, + vnf_parameters=vf_module_parameters, + use_preload=False + ) + check_orchestration_status(vf_module_instantiation) + else: + logger.error("VF_MODULE_PARAM_LIST error. ") + # End of vf_modules + # End of VNFs + + +def main(): + logger.info("*******************************") + logger.info("**** SERVICE INSTANTIATION ****") + logger.info("*******************************") + + config = Config(env_dict=VariablesDict.env_variable) + + logger.info("******** GET Customer *******") + customer = get_customer(config.service_instance["customer_id"]) + + logger.info("******** GET Service Model from SDC *******") + service = get_service_model(config.service_instance["model_name"]) + + logger.info("******** Subscribe Customer for Service *******") + subscribe_service_customer(customer, service) + + logger.info("******** Get Tenant *******") + region_details = next( + region for region in config.cloud_regions if region["name"] == config.service_instance["cloud_region"]) + cloud_region = get_cloud_region(region_details["cloud_owner"], region_details["name"]) + tenant = get_tenant(cloud_region, + config.service_instance["tenant_name"]) + + ###### + logger.info("******** Connect Service to Tenant *******") + service_subscription = None + try: + service_subscription = customer.get_service_subscription_by_service_type( + service_type=config.service_instance["model_name"]) + except ResourceNotFound: + logger.error("Service subscription %s is not found", config.service_instance["model_name"]) + exit(1) + + service_subscription.link_to_cloud_region_and_tenant(cloud_region, tenant) + #### + + logger.info("******** Business Objects (OE, P, Pl, LoB) *******") + project = "Project-Demonstration" + platform = "Platform-test" + line_of_business = "Orange-LOB" + owning_entity = add_owning_entity("Orange") + + logger.info("******** Delete old profiles ********") + delete_old_profiles(service, config.service_instance) + + logger.info("******** Instantiate Service *******") + service_instance = check_service_instance_exists(service_subscription, config.service_instance["instance_name"]) + if service_instance: + logger.info("******** Service Instance exists, do not instantiate *******") + else: + logger.info("******** Service Instance not existing: Instantiate *******") + if config.service_model["macro_orchestration"]: + instantiate_service_macro(config, service, cloud_region, tenant, customer, owning_entity, + project, line_of_business, platform) + instantiate_vnfs_macro(config=config, service_subscription=service_subscription, + line_of_business=line_of_business, platform=platform) + else: + instantiate_service_alacarte(config, service_subscription, service, cloud_region, tenant, customer, + owning_entity, project, line_of_business, platform) + + +if __name__ == "__main__": + sh = logging.StreamHandler() + sh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s') + sh.setFormatter(sh_formatter) + logger.addHandler(sh) + + main() diff --git a/tutorials/ApacheCNF/automation/k8s_client.py b/tutorials/ApacheCNF/automation/k8s_client.py new file mode 100644 index 00000000..98b451bc --- /dev/null +++ b/tutorials/ApacheCNF/automation/k8s_client.py @@ -0,0 +1,59 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2021 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +import os +from pprint import pprint + +import oyaml as yaml +from kubernetes import config, client +from kubernetes.client import OpenApiException + + +class K8sClient: + def __init__(self, kubeconfig_path): + self.mypath = os.path.dirname(os.path.realpath(__file__)) + config.load_kube_config(config_file=os.path.join(self.mypath, kubeconfig_path)) + self.api_instance = client.CustomObjectsApi() + + def read_custom_object_file(self, file_path): + with open(file_path) as crd_file: + crd_body = yaml.load(crd_file, Loader=yaml.FullLoader) + return crd_body + + def get_custom_object_details(self, crd_body): + group = crd_body["apiVersion"].split("/")[0] + version = crd_body["apiVersion"].split("/")[1] + plural = crd_body["kind"].lower() + "s" + #name = crd_body["metadata"]["name"] + + return group, version, plural #, name + + def create_custom_object(self, file_path): + crd_body = self.read_custom_object_file(file_path) + #group, version, plural, name = self.get_custom_object_details(crd_body) + group, version, plural = self.get_custom_object_details(crd_body) + api_response = None + try: + api_response = self.api_instance.create_cluster_custom_object(group=group, + version=version, + plural=plural, + body=crd_body, + pretty="true") + except OpenApiException as error: + print(str(error.status) + " " + error.reason) + pprint(error.body) + return api_response diff --git a/tutorials/ApacheCNF/automation/onap_settings.py b/tutorials/ApacheCNF/automation/onap_settings.py new file mode 100644 index 00000000..e0bad35d --- /dev/null +++ b/tutorials/ApacheCNF/automation/onap_settings.py @@ -0,0 +1,73 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2021 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +"""Global settings module.""" # pylint: disable=bad-whitespace +# uncomment if socks is used +#from onapsdk.onap_service import OnapService + +###################### +# # +# ONAP SERVICES URLS # +# # +###################### + +AAI_URL = "https://aai.api.sparky.simpledemo.onap.org:30233" +AAI_API_VERSION = "v23" +AAI_AUTH = "Basic QUFJOkFBSQ==" +CDS_URL = "http://portal.api.simpledemo.onap.org:30449" +CDS_AUTH = ("ccsdkapps", "ccsdkapps") +MSB_URL = "https://msb.api.simpledemo.onap.org:30283" +SDC_BE_URL = "https://sdc.api.be.simpledemo.onap.org:30204" +SDC_FE_URL = "https://sdc.api.fe.simpledemo.onap.org:30207" +SDC_AUTH = "Basic YWFpOktwOGJKNFNYc3pNMFdYbGhhazNlSGxjc2UyZ0F3ODR2YW9HR21KdlV5MlU=" +SDNC_URL = "https://sdnc.api.simpledemo.onap.org:30267" +SDNC_AUTH = "Basic YWRtaW46S3A4Yko0U1hzek0wV1hsaGFrM2VIbGNzZTJnQXc4NHZhb0dHbUp2VXkyVQ==" +SO_URL = "http://so.api.simpledemo.onap.org:30277" +SO_API_VERSION = "v7" +SO_AUTH = "Basic SW5mcmFQb3J0YWxDbGllbnQ6cGFzc3dvcmQxJA==" +SO_CAT_DB_AUTH = "Basic YnBlbDpwYXNzd29yZDEk" +VID_URL = "https://vid.api.simpledemo.onap.org:30200" +VID_API_VERSION = "/vid" +CLAMP_URL = "https://clamp.api.simpledemo.onap.org:30258" +CLAMP_AUTH = "Basic ZGVtb0BwZW9wbGUub3NhYWYub3JnOmRlbW8xMjM0NTYh" +VES_URL = "http://ves.api.simpledemo.onap.org:30417" +DMAAP_URL = "http://dmaap.api.simpledemo.onap.org:3904" +NBI_URL = "https://nbi.api.simpledemo.onap.org:30274" +NBI_API_VERSION = "/nbi/api/v4" +DCAEMOD_URL = "" +HOLMES_URL = "https://aai.api.sparky.simpledemo.onap.org:30293" +POLICY_URL = "" + +## GUI +AAI_GUI_URL = "https://aai.api.sparky.simpledemo.onap.org:30220" +AAI_GUI_SERVICE = f"{AAI_GUI_URL}/services/aai/webapp/index.html#/browse" +CDS_GUI_SERVICE = f"{CDS_URL}/" +SO_MONITOR_GUI_SERVICE = f"{SO_URL}/" +SDC_GUI_SERVICE = f"{SDC_FE_URL}/sdc1/portal" +SDNC_DG_GUI_SERVICE = f"{SDNC_URL}/nifi/" +SDNC_ODL_GUI_SERVICE = f"{SDNC_URL}/odlux/index.html" + +DCAEMOD_GUI_SERVICE = f"{DCAEMOD_URL}/" +HOLMES_GUI_SERVICE = f"{HOLMES_URL}/iui/holmes/default.html" +POLICY_GUI_SERVICE = f"{POLICY_URL}/onap/login.html" +POLICY_CLAMP_GUI_SERVICE = f"{CLAMP_URL}/" + +# uncomment if socks is used +#OnapService.set_proxy({'http': 'socks5h://127.0.0.1:8081', 'https': 'socks5h://127.0.0.1:8081'}) + +# execute in the shell to apply these settings +# export ONAP_PYTHON_SDK_SETTINGS="onap_settings" diff --git a/tutorials/ApacheCNF/automation/onboard.py b/tutorials/ApacheCNF/automation/onboard.py new file mode 100644 index 00000000..7e27419c --- /dev/null +++ b/tutorials/ApacheCNF/automation/onboard.py @@ -0,0 +1,213 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2021 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +import logging +import os +import time +import zipfile +from io import BytesIO + +import yaml + +from config import Config, VariablesDict +import onapsdk.constants as const + +from onapsdk.sdc.vendor import Vendor +from onapsdk.sdc.vsp import Vsp +from onapsdk.sdc.vf import Vf +from onapsdk.sdc.pnf import Pnf +from onapsdk.sdc.service import Service, ServiceInstantiationType +from onapsdk.exceptions import ResourceNotFound + +logger = logging.getLogger() +logger.setLevel(logging.DEBUG) + + +def retrieve_service(service_name: str): + logger.info("Retrieve service from SDC before onboarding") + services = Service.get_all() + + for found_service in services: + if found_service.name == service_name: + logging.info(f"Service {found_service.name} found in SDC, onboarding will not be executed") + exit(0) + return + + +def onboard_vendor(vendor_name: str = "demo_vendor"): + logger.info("******** Onboard Vendor *******") + try: + vendor = next(vendor for vendor in Vendor.get_all() if vendor.name.lower() == vendor_name.lower()) + except (StopIteration, ResourceNotFound): + vendor = Vendor(vendor_name) + vendor.onboard() + return vendor + + +def onboard_vsp(vsp_name, vsp_file, vendor): + logger.info(f"******** Onboard VSP - {vsp_name} *******") + mypath = os.path.dirname(os.path.realpath(__file__)) + vsp_path = os.path.join(mypath, vsp_file) + vsp = None + try: + vsp = Vsp(name=vsp_name, vendor=vendor, package=open(vsp_path, 'rb')) + except FileNotFoundError: + logger.error(f"No vsp file was found for {vsp_name}!") + exit(1) + vsp.onboard() + return vsp + + +def onboard_pnf(pnf_name, vsp_name, vsp_file, vendor_name): + logger.info(f"******** Onboard PNF - {pnf_name} *******") + vendor = onboard_vendor(vendor_name=vendor_name) + try: + pnf = next(_pnf for _pnf in Pnf.get_all() if _pnf.name == pnf_name) + logger.info("PNF with provided name exists in ONAP SDC, onboarding will not be executed") + except (StopIteration, ResourceNotFound): + pnf_vsp = onboard_vsp(vsp_name=vsp_name, vsp_file=vsp_file, vendor=vendor) + pnf = Pnf(name=pnf_name, vsp=pnf_vsp) + pnf.onboard() + return pnf + + +def onboard_vnf(vnf_name, vsp_name, vsp_file, vendor_name): + logger.info(f"******** Onboard VNF - {vnf_name} *******") + vendor = onboard_vendor(vendor_name=vendor_name) + try: + vnf = next(_vf for _vf in Vf.get_all() if _vf.name == vnf_name) + if vnf.status != "Certified": + logger.error("Selected VNF is not certified. Try Onboard VF with new name.") + exit(1) + logger.info("VNF with provided name exists in ONAP SDC, onboarding will not be executed") + except (StopIteration, ResourceNotFound): + vnf_vsp = onboard_vsp(vsp_name=vsp_name, vsp_file=vsp_file, vendor=vendor) + vnf = Vf(name=vnf_name, vsp=vnf_vsp) + vnf.create() + vnf.onboard() + return vnf + + +def create_service(service_name, is_macro: bool = True): + logger.info("******** Create Service *******") + if is_macro: + service = Service(name=service_name, + instantiation_type=ServiceInstantiationType.MACRO) + else: + service = Service(name=service_name, + instantiation_type=ServiceInstantiationType.A_LA_CARTE) + service.create() + return service + + +def read_sdnc_model_details(file): + mypath = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(mypath, file) + try: + with zipfile.ZipFile(file_path, 'r') as package: + try: + cba_io = BytesIO(package.read("CBA.zip")) + with zipfile.ZipFile(cba_io) as cba: + with cba.open('TOSCA-Metadata/TOSCA.meta') as meta_file: + tosca_meta = yaml.load(meta_file, Loader=yaml.SafeLoader) + sdnc_model_name = tosca_meta.get("Template-Name") + sdnc_model_version = tosca_meta.get("Template-Version") + return sdnc_model_name, sdnc_model_version + except KeyError: + logger.info("No CBA file was found") + return None, None + except FileNotFoundError: + logger.error("No vsp file was found!") + exit(1) + + +def set_properties(service, xnf, vsp_details): + sdnc_model_name, sdnc_model_version = read_sdnc_model_details(vsp_details["vsp_file"]) + if sdnc_model_name and sdnc_model_version: + if service.status == const.DRAFT: + logger.info("******** Set SDNC properties for VF ********") + component = service.get_component(xnf) + prop = component.get_property("sdnc_model_name") + prop.value = sdnc_model_name + prop = component.get_property("sdnc_model_version") + prop.value = sdnc_model_version + prop = component.get_property("controller_actor") + prop.value = "CDS" + prop = component.get_property("sdnc_artifact_name") + prop.value = vsp_details["sdnc_artifact_name"] + prop = component.get_property("skip_post_instantiation_configuration") + prop.value = vsp_details["skip_post_instantiation_configuration"] + + +def check_distribution_status(service): + logger.info("******** Check Service Distribution *******") + distribution_completed = False + nb_try = 0 + nb_try_max = 10 + while distribution_completed is False and nb_try < nb_try_max: + distribution_completed = service.distributed + if distribution_completed is True: + logger.info(f"Service Distribution for {service.name} is successfully finished") + break + logger.info(f"Service Distribution for {service.name} ongoing, Wait for 60 s") + time.sleep(60) + nb_try += 1 + + if distribution_completed is False: + logger.error(f"Service Distribution for {service.name} failed !!", ) + exit(1) + + +def main(): + config = Config(env_dict=VariablesDict.env_variable) + retrieve_service(service_name=config.service_model["model_name"]) + + logger.info("******** SERVICE DESIGN *******") + service = create_service(service_name=config.service_model["model_name"], + is_macro=config.service_model["macro_orchestration"]) + vnfs = config.service_model.get("vnfs") + if vnfs: + for vnf in vnfs: + new_vnf = onboard_vnf(vnf_name=vnf["model_name"], + vsp_name="VSP" + "_" + vnf["model_name"], + vsp_file=vnf["vsp"]["vsp_file"], + vendor_name=vnf["vsp"]["vendor"]) + service.add_resource(new_vnf) + set_properties(service=service, xnf=new_vnf, vsp_details=vnf["vsp"]) + + pnfs = config.service_model.get("pnfs") + if pnfs: + for pnf in pnfs: + new_pnf = onboard_pnf(pnf_name=pnf["model_name"], + vsp_name="VSP" + "_" + pnf["model_name"], + vsp_file=pnf["vsp"]["vsp_file"], + vendor_name=pnf["vsp"]["vendor"]) + service.add_resource(new_pnf) + set_properties(service=service, xnf=new_pnf, vsp_details=pnf["vsp"]) + + service.checkin() + service.onboard() + check_distribution_status(service) + + +if __name__ == "__main__": + sh = logging.StreamHandler() + sh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s') + sh.setFormatter(sh_formatter) + logger.addHandler(sh) + + main() diff --git a/tutorials/ApacheCNF/automation/update_cba.py b/tutorials/ApacheCNF/automation/update_cba.py new file mode 100644 index 00000000..226029f5 --- /dev/null +++ b/tutorials/ApacheCNF/automation/update_cba.py @@ -0,0 +1,57 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2021 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +import logging +import os +import zipfile +from io import BytesIO + +from onapsdk.cds import Blueprint + +from config import Config, VariablesDict + +logger = logging.getLogger() +logger.setLevel(logging.DEBUG) + + +def update_cba(file): + mypath = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(mypath, file) + try: + with zipfile.ZipFile(file_path, 'r') as package: + cba_io = BytesIO(package.read("CBA.zip")) + + blueprint = Blueprint(cba_io) + blueprint.deploy() + except FileNotFoundError: + logger.error("Error - File Not Found") + exit(1) + + +def main(): + config = Config(env_dict=VariablesDict.env_variable) + for vnf in config.service_model["vnfs"]: + update_cba(vnf["vsp"]["vsp_file"]) + + +if __name__ == "__main__": + sh = logging.StreamHandler() + sh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s') + sh.setFormatter(sh_formatter) + logger.addHandler(sh) + + main() diff --git a/tutorials/ApacheCNF/automation/update_connectivity_info.py b/tutorials/ApacheCNF/automation/update_connectivity_info.py new file mode 100644 index 00000000..d5138bc9 --- /dev/null +++ b/tutorials/ApacheCNF/automation/update_connectivity_info.py @@ -0,0 +1,40 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2021 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +import logging + +from config import Config, VariablesDict +from create_cloud_regions import update_connectivity_info, is_k8s_region + +logger = logging.getLogger() +logger.setLevel(logging.DEBUG) + + +def main(): + config = Config(env_dict=VariablesDict.env_variable) + for region in config.cloud_regions: + if is_k8s_region(region): + update_connectivity_info(region) + + +if __name__ == "__main__": + sh = logging.StreamHandler() + sh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s') + sh.setFormatter(sh_formatter) + logger.addHandler(sh) + + main() diff --git a/tutorials/ApacheCNF/automation/vsp/.gitkeep b/tutorials/ApacheCNF/automation/vsp/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/tutorials/ApacheCNF/automation/vsp/.keep b/tutorials/ApacheCNF/automation/vsp/.keep new file mode 100644 index 00000000..e69de29b diff --git a/tutorials/ApacheCNF/service_config.yaml b/tutorials/ApacheCNF/service_config.yaml new file mode 100644 index 00000000..ef88fd27 --- /dev/null +++ b/tutorials/ApacheCNF/service_config.yaml @@ -0,0 +1,94 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2022 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= +user_params: + cnf_name: &cnf_name apache + k8s_namespace: test-cnf + k8s_version: 1.18.9 + k8s_region: ®ion cnf-region + release_name: rel-1 +# profile_source: cnf-cds-base-profile + profile_source: node-port-profile + skip_day_2: &skip_day_2 True + +cloud_regions: + - name: *region + cloud_owner: K8sCloudOwner + cloud_type: k8s + complex_id: k8s-complex1 + tenants: + - name: &tenant "{{ user_params.k8s_region }}-tenant" + k8s_version: "{{ user_params.k8s_version }}" + kubeconfig_file: artifacts/kubeconfig +# - name: openstack-region-test +# cloud_owner: CloudOwner +# cloud_type: openstack +# complex_id: complex1 +# tenants: +# - name: &my_tenant1 onap-dev +# id: 5117085204e84027a8d1a0cf34abb0ba +# identity_url: http://test:5000/v4 +# mso_id: test_user +# mso_pass: test_encrypted_password +# identity_server_type: KEYSTONE_V3 + +service_model: + macro_orchestration: True + model_name: &service_model_name "{{ user_params.cnf_name }}_{{ user_params.skip_day_2 }}_k8s_cnf_demo" + vnfs: + - model_name: &vnf_1_model_name "{{ user_params.cnf_name }}" + vsp: + vsp_file: vsp/native_cnf_k8s_demo.zip + vendor: cnf_vendor + sdnc_artifact_name: vnf + skip_post_instantiation_configuration: *skip_day_2 +# pnfs: +# - model_name: pnf_example +# vsp: +# vsp_file: vsp/pnf_package.csar +# vendor: pnf_vendor +# skip_post_instantiation_configuration: False + + +service_instance: + model_name: *service_model_name + instance_name: I_{{ service_model.model_name }}_{{ user_params.release_name }} + customer_id: orange + cloud_region: *region # "{{ cloud_regions[0].name }}" + tenant_name: *tenant # "{{ cloud_regions[0].tenants[0].name }}" + service_type: *cnf_name + vnfs: + - model_name: *vnf_1_model_name + #vnf_name_suffix: "001" #needed when more than one vnf instance + parameters: + k8s-rb-profile-namespace: "{{ user_params.k8s_namespace }}" + k8s-rb-profile-k8s-version: "{{ user_params.k8s_version }}" + processing_priority: 1 # may be used to order vnf deployment + vf_modules: + - model_name: helm_apache + vf_module_name_suffix: "001" + processing_priority: 1 # may be used to order vf-module deployment + parameters: + k8s-rb-profile-name: "{{ user_params.profile_source }}-{{ user_params.k8s_namespace }}" + k8s-rb-profile-source: "{{ user_params.profile_source }}" + k8s-rb-instance-release-name: "{{ user_params.release_name }}" + k8s-rb-profile-namespace: "{{ user_params.k8s_namespace }}" + k8s-rb-config-template-name: replica-count-template + k8s-rb-config-template-source: deployment-config + k8s-rb-config-name: replica-count-change + k8s-rb-config-value-source: custom-values +# pnfs: +# - model_name: pnf_example diff --git a/tutorials/ApacheCNF/templates/.gitattributes b/tutorials/ApacheCNF/templates/.gitattributes new file mode 100644 index 00000000..4ad2a524 --- /dev/null +++ b/tutorials/ApacheCNF/templates/.gitattributes @@ -0,0 +1 @@ +/cba/Templates/k8s-profiles/*.tar.gz binary diff --git a/tutorials/ApacheCNF/templates/.gitignore b/tutorials/ApacheCNF/templates/.gitignore new file mode 100644 index 00000000..f88e099b --- /dev/null +++ b/tutorials/ApacheCNF/templates/.gitignore @@ -0,0 +1,2 @@ +package/ +vfw_k8s_demo.zip diff --git a/tutorials/ApacheCNF/templates/Makefile b/tutorials/ApacheCNF/templates/Makefile new file mode 100644 index 00000000..9866d6c5 --- /dev/null +++ b/tutorials/ApacheCNF/templates/Makefile @@ -0,0 +1,42 @@ +.PHONY: all clean helm base clean_all package cba jsonlint_cba +NATIVE_ONBOARDING_PACKAGE_NAME ?= native_cnf_k8s_demo +CBA_NAME ?= CBA +_type_files = $(wildcard cba/Definitions/*_types.json) + + +clean_all: + $(MAKE) clean + $(MAKE) all + +#Can't use .csar extension or SDC will panic +all: package helm base cba + cd package_native/ && zip -r $(NATIVE_ONBOARDING_PACKAGE_NAME).zip . + mv package_native/$(NATIVE_ONBOARDING_PACKAGE_NAME).zip . + cp $(NATIVE_ONBOARDING_PACKAGE_NAME).zip ../automation/vsp/ + +helm: package + $(MAKE) -C helm + mv helm/helm_*.tgz package_native/ + +base: package + cp base_native/* package_native/ + +cba: package + cd cba/ && zip -r $(CBA_NAME).zip . -x pom.xml .idea/\* target/\* + mv cba/$(CBA_NAME).zip package_native/ + +package: + mkdir package_native/ + +clean: + rm -rf package_native/ + rm -f $(NATIVE_ONBOARDING_PACKAGE_NAME).zip + +jsonlint_cba: $(_type_files) + @: + +#This shouldn't be PHONY, but it's easier now to define this way +.PHONY: $(_type_files) +$(_type_files): + @which jq expand unexpand sponge >/dev/null + jq -S . <$@ | unexpand -t 2 | expand -t 4 | sponge $@ diff --git a/tutorials/ApacheCNF/templates/README.txt b/tutorials/ApacheCNF/templates/README.txt new file mode 100644 index 00000000..3d7c29cf --- /dev/null +++ b/tutorials/ApacheCNF/templates/README.txt @@ -0,0 +1 @@ +cba-dd.json file is Data Dictionary file used to enrich cba model. diff --git a/tutorials/ApacheCNF/templates/base_native/MANIFEST.json b/tutorials/ApacheCNF/templates/base_native/MANIFEST.json new file mode 100644 index 00000000..cfaba8d9 --- /dev/null +++ b/tutorials/ApacheCNF/templates/base_native/MANIFEST.json @@ -0,0 +1,15 @@ +{ + "name": "simpleCNF", + "description": "", + "data": [ + { + "file": "CBA.zip", + "type": "CONTROLLER_BLUEPRINT_ARCHIVE" + }, + { + "file": "helm_apache.tgz", + "type": "HELM", + "isBase": "true" + } + ] +} diff --git a/tutorials/ApacheCNF/templates/cba-dev/bootstrap.sh b/tutorials/ApacheCNF/templates/cba-dev/bootstrap.sh new file mode 100644 index 00000000..74ec06a0 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba-dev/bootstrap.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +# ============LICENSE_START======================================================= +# Copyright (C) 2020 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +curl --location --request POST 'http://127.0.0.1:8081/api/v1/blueprint-model/bootstrap' \ +--header 'Authorization: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==' \ +--header 'Content-Type: application/json' \ +--data '{"loadModelType": true, "loadResourceDictionary": true, "loadCBA": false}' | jq diff --git a/tutorials/ApacheCNF/templates/cba-dev/build.sh b/tutorials/ApacheCNF/templates/cba-dev/build.sh new file mode 100644 index 00000000..a7a34061 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba-dev/build.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +# ============LICENSE_START======================================================= +# Copyright (C) 2020 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +cd ../cba/ + +mvn clean install + +if [ $? -eq 1 ] +then + echo "----------------" + echo "CBA BUILD FAILED" + echo "----------------" + exit 1 +fi + +CBA_NAME=`ls target/*.zip` +cp $CBA_NAME ../cba-dev/cba.zip + +echo "-----------------" +echo "CBA BUILD SUCCESS" +echo "-----------------" + +cd ../cba-dev diff --git a/tutorials/ApacheCNF/templates/cba-dev/deploy.sh b/tutorials/ApacheCNF/templates/cba-dev/deploy.sh new file mode 100644 index 00000000..59c9807d --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba-dev/deploy.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# ============LICENSE_START======================================================= +# Copyright (C) 2020 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +curl --location --request POST 'http://127.0.0.1:8081/api/v1/blueprint-model' \ +--header 'Authorization: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==' \ +--form 'file=@cba.zip' | jq diff --git a/tutorials/ApacheCNF/templates/cba-dev/enrich.sh b/tutorials/ApacheCNF/templates/cba-dev/enrich.sh new file mode 100644 index 00000000..632cb89f --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba-dev/enrich.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +# ============LICENSE_START======================================================= +# Copyright (C) 2020 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +curl --location --request POST 'http://127.0.0.1:8081/api/v1/blueprint-model/enrich' \ +--header 'Authorization: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==' \ +-o 'cba.zip' \ +--form 'file=@../package_native/CBA.zip' | jq diff --git a/tutorials/ApacheCNF/templates/cba-dev/run-vf-base-ra.sh b/tutorials/ApacheCNF/templates/cba-dev/run-vf-base-ra.sh new file mode 100644 index 00000000..6151dc75 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba-dev/run-vf-base-ra.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +# ============LICENSE_START======================================================= +# Copyright (C) 2020 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +REQ_ID=`shuf -i 1-1000000 -n 1` +SUB_REQ_ID=$REQ_ID"-"`shuf -i 1-1000 -n 1` +TEMPLATE_NAME="helm_apache" + +curl --location --request POST 'http://localhost:8081/api/v1/execution-service/process' \ +--header 'Authorization: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "commonHeader": { + "originatorId": "onap-me-cm-adapter", + "requestId": "'$REQ_ID'", + "subRequestId": "'$SUB_REQ_ID'" + }, + "actionIdentifiers": { + "blueprintName": "APACHE", + "blueprintVersion": "1.0.0", + "actionName": "resource-assignment", + "mode": "sync" + }, + "payload": { + "resource-assignment-request": { + "template-prefix": [ + "'$TEMPLATE_NAME'" + ], + "resolution-key": "ra-test-resolution", + "resource-assignment-properties": { + "replica-count": 2, + "aic-cloud-region": "RegionOne", + "vnf-model-customization-uuid": "d73864db-1f6e-4e54-a533-a96773c926a4", + "service-instance-id": "2afee7c4-8b16-4f2f-a567-48fb7948abcf", + "vnf-id": "21dcbbd2-3ec2-4a9c-bb0d-599cafc16a1f", + "vnf_name": "sample-vnf-name", + "vf-module-name": "vf-module-name", + "vf-module-label": "'$TEMPLATE_NAME'", + "vf-module-type": "vf-module-type", + "vf-module-model-customization-uuid": "d3ae2df9-95d4-48cc-a466-9f12dee80458", + "vf-module-model-invariant-uuid": "564e55dc-3b90-4c9c-9e97-42f2c97d8f11", + "vf-module-model-version": "3d55e2a6-7634-4ceb-98e9-2852d621a544", + "vf-module-id": "3e6a0375-4b92-4bf5-9910-b0b893448a9c", + "vf-naming-policy" : "SDNC_Policy.ONAP_NF_NAMING_TIMESTAMP", + "k8s-rb-profile-name": "vfw-cnf-cds-base-profile", + "management-prefix-id" : 3 + } + } + } +}' | jq '.payload | .["resource-assignment-response"] | .["meshed-template"] | .'$TEMPLATE_NAME' | fromjson | .["resource-accumulator-resolved-data"] ' diff --git a/tutorials/ApacheCNF/templates/cba-dev/run-vnf-config.sh b/tutorials/ApacheCNF/templates/cba-dev/run-vnf-config.sh new file mode 100644 index 00000000..a211a6bc --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba-dev/run-vnf-config.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +# ============LICENSE_START======================================================= +# Copyright (C) 2021 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +REQ_ID=`shuf -i 1-1000000 -n 1` +SUB_REQ_ID=$REQ_ID"-"`shuf -i 1-1000 -n 1` +ACTION=$1 + +curl --location --request POST 'http://localhost:8081/api/v1/execution-service/process' \ +--header 'Authorization: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "commonHeader": { + "originatorId": "onap-me-cm-adapter", + "requestId": "'$REQ_ID'", + "subRequestId": "'$SUB_REQ_ID'" + }, + "actionIdentifiers": { + "blueprintName": "APACHE", + "blueprintVersion": "1.0.0", + "actionName": "'config-$ACTION'", + "mode": "sync" + }, + "payload": { + "'config-$ACTION-request'": { + "resolution-key": "VF_apache_k8s_demo_CNF", + "'config-$ACTION-properties'": { + "service-instance-id": "2a2de3ec-35a4-4e1d-b313-ac5c4c8813a8", + "vnf-id": "6b6ff775-a170-4ce4-bcd0-85645d738390" + } + } + } +}' | jq '.payload | .["'config-$ACTION-response'"]' + diff --git a/tutorials/ApacheCNF/templates/cba-dev/run-vnf-ra.sh b/tutorials/ApacheCNF/templates/cba-dev/run-vnf-ra.sh new file mode 100644 index 00000000..9cf4c2a4 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba-dev/run-vnf-ra.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +# ============LICENSE_START======================================================= +# Copyright (C) 2020 Orange +# ================================================================================ +# 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. +# +# ============LICENSE_END========================================================= + +REQ_ID=`shuf -i 1-1000000 -n 1` +SUB_REQ_ID=$REQ_ID"-"`shuf -i 1-1000 -n 1` + +curl --location --request POST 'http://localhost:8081/api/v1/execution-service/process' \ +--header 'Authorization: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "commonHeader": { + "originatorId": "onap-me-cm-adapter", + "requestId": "'$REQ_ID'", + "subRequestId": "'$SUB_REQ_ID'" + }, + "actionIdentifiers": { + "blueprintName": "APACHE", + "blueprintVersion": "1.0.0", + "actionName": "resource-assignment", + "mode": "sync" + }, + "payload": { + "resource-assignment-request": { + "template-prefix": [ + "vnf" + ], + "resolution-key": "ra-test-resolution", + "resource-assignment-properties": { + "replica-count": 2, + "aic-cloud-region": "RegionOne", + "vnf-model-customization-uuid": "d73864db-1f6e-4e54-a533-a96773c926a4", + "service-instance-id": "2afee7c4-8b16-4f2f-a567-48fb7948abcf", + "vnf-id": "51274ece-55ca-4cbc-b7c4-0da0dcc65d38", + "vnf_name": "sample-vnf-name", + "k8s-rb-profile-namespace": "vfw-namespace", + "k8s-rb-profile-k8s-version": "1.18.9" + } + } + } +}' | jq '.payload | .["resource-assignment-response"] | .["meshed-template"] | .vnf | fromjson | .["resource-accumulator-resolved-data"] ' + diff --git a/tutorials/ApacheCNF/templates/cba/Definitions/CNF.json b/tutorials/ApacheCNF/templates/cba/Definitions/CNF.json new file mode 100644 index 00000000..bf1a423b --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Definitions/CNF.json @@ -0,0 +1,853 @@ +{ + "tosca_definitions_version": "controller_blueprint_1_0_0", + "metadata": { + "template_author": "Lukasz Rajewski ", + "author-email": "lukasz.rajewski@orange.com", + "user-groups": "ADMIN, OPERATION", + "template_name": "APACHE", + "template_version": "1.0.0", + "template_tags": "Lukasz Rajewski, CNF", + "template_type": "DEFAULT" + }, + "imports": [ + { + "file": "Definitions/data_types.json" + }, + { + "file": "Definitions/relationship_types.json" + }, + { + "file": "Definitions/artifact_types.json" + }, + { + "file": "Definitions/node_types.json" + }, + { + "file": "Definitions/policy_types.json" + } + ], + "dsl_definitions": { + "naming-resolution": { + "type": "basic-auth", + "url": "http://neng-serv:8080/web/service", + "username": "ccsdkapps", + "password": "ccsdkapps" + }, + "vpkg-rest-api": { + "type": "basic-auth", + "url": "http://", + "username": "admin", + "password": "admin" + }, + "config-deploy-properties": { + "resolution-key": { + "get_input": "resolution-key" + } + }, + "simple-status-properties": { + "resolution-key": { + "get_input": "resolution-key" + }, + "config-deploy-setup": { + "get_attribute": [ + "config-setup-process", + "", + "assignment-map", + "config-deploy", + "config-deploy-setup" + ] + } + } + }, + "topology_template": { + "workflows": { + "resource-assignment": { + "steps": { + "resource-assignment": { + "description": "Resource Assign Workflow", + "target": "resource-assignment", + "activities": [ + { + "call_operation": "ResourceResolutionComponent.process" + } + ], + "on_success": [ + "profile-upload" + ] + }, + "profile-upload": { + "description": "Generate and upload K8s Profile", + "target": "k8s-profile-upload", + "activities": [ + { + "call_operation": "ComponentScriptExecutor.process" + } + ] + } + }, + "inputs": { + "template-prefix": { + "required": true, + "type": "list", + "entry_schema": { + "type": "string" + } + }, + "resolution-key": { + "required": false, + "type": "string", + "entry_schema": { + "type": "" + } + }, + "resource-assignment-properties": { + "description": "Dynamic PropertyDefinition for workflow(resource-assignment).", + "required": true, + "type": "dt-resource-assignment-properties" + } + }, + "outputs": { + "meshed-template": { + "type": "json", + "value": { + "get_attribute": [ + "resource-assignment", + "assignment-params" + ] + } + } + } + }, + "config-assign": { + "steps": { + "config-setup": { + "description": "Gather necessary input for config template upload", + "target": "config-setup-process", + "activities": [ + { + "call_operation": "ResourceResolutionComponent.process" + } + ], + "on_success": [ + "config-template" + ] + }, + "config-template": { + "description": "Generate and upload K8s config template", + "target": "k8s-config-template", + "activities": [ + { + "call_operation": "K8sConfigTemplateComponent.process" + } + ] + } + }, + "inputs": { + "resolution-key": { + "required": true, + "type": "string" + }, + "store-result": { + "required": true, + "type": "boolean" + }, + "config-assign-properties": { + "description": "Dynamic PropertyDefinition for workflow(config-assign).", + "required": true, + "type": "dt-config-assign-properties" + } + } + }, + "config-deploy": { + "steps": { + "config-setup": { + "description": "Gather necessary input for config init and status verification", + "target": "config-setup-process", + "activities": [ + { + "call_operation": "ResourceResolutionComponent.process" + } + ], + "on_success": [ + "status-verification-script" + ] + }, + "status-verification-script": { + "description": "Simple status verification script", + "target": "simple-status-check", + "activities": [ + { + "call_operation": "ComponentScriptExecutor.process" + } + ], + "on_success": [ + "config-apply" + ] + }, + "config-apply": { + "description": "Activate K8s config template", + "target": "k8s-config-apply", + "activities": [ + { + "call_operation": "K8sConfigValueComponent.process" + } + ], + "on_success": [ + "status-verification-script-after" + ] + }, + "status-verification-script-after": { + "description": "Simple status verification script", + "target": "simple-status-check", + "activities": [ + { + "call_operation": "ComponentScriptExecutor.process" + } + ], + "on_success": [ + "collect-results" + ] + }, + "collect-results": { + "description": "Final collection of results", + "target": "collect-results" + } + }, + "inputs": { + "resolution-key": { + "required": true, + "type": "string" + }, + "config-deploy-properties": { + "description": "Dynamic PropertyDefinition for workflow(config-deploy).", + "required": true, + "type": "dt-config-deploy-properties" + } + } + }, + "scale-out": { + "steps": { + "config-setup": { + "description": "Gather necessary input for config init and status verification", + "target": "config-setup-process", + "activities": [ + { + "call_operation": "ResourceResolutionComponent.process" + } + ], + "on_success": [ + "config-template" + ] + }, + "config-template": { + "description": "Generate and upload K8s config template", + "target": "k8s-config-template", + "activities": [ + { + "call_operation": "K8sConfigTemplateComponent.process" + } + ], + "on_success": [ + "config-apply" + ] + }, + "config-apply": { + "description": "Activate K8s config apply", + "target": "k8s-config-apply", + "activities": [ + { + "call_operation": "K8sConfigValueComponent.process" + } + ], + "on_success": [ + "status-verification-script-after" + ] + }, + "status-verification-script-after": { + "description": "Simple status verification script", + "target": "simple-status-check", + "activities": [ + { + "call_operation": "ComponentScriptExecutor.process" + } + ], + "on_success": [ + "collect-results" + ] + }, + "collect-results": { + "description": "Final collection of results", + "target": "collect-results" + } + }, + "inputs": { + "resolution-key": { + "required": true, + "type": "string" + }, + "scale-out-properties": { + "description": "Dynamic PropertyDefinition for workflow(scale-out).", + "required": true, + "type": "dt-scale-out-properties" + } + } + }, + "scale": { + "steps": { + "config-setup": { + "description": "Gather necessary input for config init and status verification", + "target": "config-setup-process", + "activities": [ + { + "call_operation": "ResourceResolutionComponent.process" + } + ], + "on_success": [ + "config-template" + ] + }, + "config-template": { + "description": "Generate and upload K8s config template", + "target": "k8s-config-template", + "activities": [ + { + "call_operation": "K8sConfigTemplateComponent.process" + } + ], + "on_success": [ + "config-update" + ] + }, + "config-update": { + "description": "Activate K8s config restore", + "target": "k8s-config-update", + "activities": [ + { + "call_operation": "K8sConfigValueComponent.process" + } + ], + "on_success": [ + "status-verification-script-after" + ] + }, + "status-verification-script-after": { + "description": "Simple status verification script", + "target": "simple-status-check", + "activities": [ + { + "call_operation": "ComponentScriptExecutor.process" + } + ], + "on_success": [ + "collect-results" + ] + }, + "collect-results": { + "description": "Final collection of results", + "target": "collect-results" + } + }, + "inputs": { + "resolution-key": { + "required": true, + "type": "string" + }, + "scale-properties": { + "description": "Dynamic PropertyDefinition for workflow(scale).", + "required": true, + "type": "dt-scale-properties" + } + } + }, + "scale-in": { + "steps": { + "config-setup": { + "description": "Gather necessary input for config init and status verification", + "target": "config-setup-process", + "activities": [ + { + "call_operation": "ResourceResolutionComponent.process" + } + ], + "on_success": [ + "config-template" + ] + }, + "config-template": { + "description": "Generate and upload K8s config template", + "target": "k8s-config-template", + "activities": [ + { + "call_operation": "K8sConfigTemplateComponent.process" + } + ], + "on_success": [ + "config-restore" + ] + }, + "config-restore": { + "description": "Activate K8s config restore", + "target": "k8s-config-restore", + "activities": [ + { + "call_operation": "K8sConfigValueComponent.process" + } + ], + "on_success": [ + "status-verification-script-after" + ] + }, + "status-verification-script-after": { + "description": "Simple status verification script", + "target": "simple-status-check", + "activities": [ + { + "call_operation": "ComponentScriptExecutor.process" + } + ], + "on_success": [ + "collect-results" + ] + }, + "collect-results": { + "description": "Final collection of results", + "target": "collect-results" + } + }, + "inputs": { + "resolution-key": { + "required": true, + "type": "string" + }, + "scale-in-properties": { + "description": "Dynamic PropertyDefinition for workflow(scale-in).", + "required": true, + "type": "dt-scale-in-properties" + } + } + }, + "health-check": { + "steps": { + "config-setup": { + "description": "Gather necessary input for config init and status verification", + "target": "config-setup-process", + "activities": [ + { + "call_operation": "ResourceResolutionComponent.process" + } + ], + "on_success": [ + "status-verification-script" + ], + "on_failure": [ + "handle_error" + ] + }, + "status-verification-script": { + "description": "Simple status verification script", + "target": "simple-status-check", + "activities": [ + { + "call_operation": "ComponentScriptExecutor.process" + } + ], + "on_success": [ + "health-check-process" + ], + "on_failure": [ + "handle_error" + ] + }, + "health-check-process": { + "description": "Start health check script", + "target": "health-check-script", + "activities": [ + { + "call_operation": "ComponentScriptExecutor.process" + } + ], + "on_success": [ + "collect-results" + ], + "on_failure": [ + "handle_error" + ] + }, + "handle_error": { + "description": "Simple error verification script", + "target": "simple-error-check", + "activities": [ + { + "call_operation": "ComponentScriptExecutor.process" + } + ], + "on_success": [ + "collect-results" + ] + }, + "collect-results": { + "description": "Final collection of results", + "target": "collect-results" + } + }, + "inputs": { + "resolution-key": { + "required": true, + "type": "string" + }, + "health-check-properties": { + "description": "Dynamic PropertyDefinition for workflow(health-check).", + "required": true, + "type": "dt-health-check-properties" + } + } + } + }, + "node_templates": { + "resource-assignment": { + "type": "component-resource-resolution", + "interfaces": { + "ResourceResolutionComponent": { + "operations": { + "process": { + "inputs": { + "artifact-prefix-names": { + "get_input": "template-prefix" + } + } + } + } + } + }, + "artifacts": { + "helm_apache-template": { + "type": "artifact-template-velocity", + "file": "Templates/cnf-template.vtl" + }, + "helm_apache-mapping": { + "type": "artifact-mapping-resource", + "file": "Templates/cnf-mapping.json" + }, + "vnf-template": { + "type": "artifact-template-velocity", + "file": "Templates/vnf-template.vtl" + }, + "vnf-mapping": { + "type": "artifact-mapping-resource", + "file": "Templates/vnf-mapping.json" + } + } + }, + "k8s-profile-upload": { + "type": "component-k8s-profile-upload", + "interfaces": { + "K8sProfileUploadComponent": { + "operations": { + "process": { + "inputs": { + "artifact-prefix-names": { + "get_input": "template-prefix" + }, + "resource-assignment-map": { + "get_attribute": [ + "resource-assignment", + "assignment-map" + ] + } + } + } + } + } + }, + "artifacts": { + "cnf-cds-base-profile": { + "type": "artifact-k8sprofile-content", + "file": "Templates/k8s-profiles/cnf-cds-base-profile.tar.gz" + }, + "node-port-profile": { + "type": "artifact-k8sprofile-content", + "file": "Templates/k8s-profiles/node-port-profile.tar.gz" + } + } + }, + "k8s-config-template": { + "type": "component-k8s-config-template", + "interfaces": { + "K8sConfigTemplateComponent": { + "operations": { + "process": { + "inputs": { + "artifact-prefix-names": [ + "helm_apache" + ], + "resource-assignment-map": { + "get_attribute": [ + "config-setup-process", + "", + "assignment-map", + "config-deploy", + "config-deploy-setup" + ] + } + } + } + } + } + }, + "artifacts": { + "deployment-config": { + "type": "artifact-k8sconfig-content", + "file": "Templates/k8s-configs/deployment-config.tar.gz" + } + } + }, + "k8s-config-apply": { + "type": "component-k8s-config-value", + "interfaces": { + "K8sConfigValueComponent": { + "operations": { + "process": { + "inputs": { + "artifact-prefix-names": [ + "helm_apache" + ], + "k8s-config-operation-type": "create", + "resource-assignment-map": { + "get_attribute": [ + "config-setup-process", + "", + "assignment-map", + "config-deploy", + "config-deploy-setup" + ] + } + } + } + } + } + }, + "artifacts": { + "default-values": { + "type": "artifact-k8sconfig-content", + "file": "Templates/k8s-configs/deployment-values/default-values.yaml" + }, + "restore-values": { + "type": "artifact-k8sconfig-content", + "file": "Templates/k8s-configs/deployment-values/restore-values.yaml" + }, + "custom-values": { + "type": "artifact-k8sconfig-content", + "file": "Templates/k8s-configs/deployment-values/values.yaml.vtl" + }, + "custom-values-mapping": { + "type": "artifact-mapping-resource", + "file": "Templates/k8s-configs/deployment-values/values-mapping.json" + } + } + }, + "k8s-config-restore": { + "type": "component-k8s-config-value", + "interfaces": { + "K8sConfigValueComponent": { + "operations": { + "process": { + "inputs": { + "artifact-prefix-names": [ + "helm_apache" + ], + "k8s-config-operation-type": "update", + "k8s-rb-config-value-source": "restore-values", + "resource-assignment-map": { + "get_attribute": [ + "config-setup-process", + "", + "assignment-map", + "config-deploy", + "config-deploy-setup" + ] + } + } + } + } + } + }, + "artifacts": { + "restore-values": { + "type": "artifact-k8sconfig-content", + "file": "Templates/k8s-configs/deployment-values/restore-values.yaml" + } + } + }, + "k8s-config-update": { + "type": "component-k8s-config-value", + "interfaces": { + "K8sConfigValueComponent": { + "operations": { + "process": { + "inputs": { + "artifact-prefix-names": [ + "helm_apache" + ], + "k8s-config-operation-type": "update", + "k8s-rb-config-value-source": "custom-values", + "resource-assignment-map": { + "get_attribute": [ + "config-setup-process", + "", + "assignment-map", + "config-deploy", + "config-deploy-setup" + ] + } + } + } + } + } + }, + "artifacts": { + "custom-values": { + "type": "artifact-k8sconfig-content", + "file": "Templates/k8s-configs/deployment-values/values.yaml.vtl" + }, + "custom-values-mapping": { + "type": "artifact-mapping-resource", + "file": "Templates/k8s-configs/deployment-values/values-mapping.json" + } + } + }, + "simple-status-check": { + "type": "component-script-executor", + "interfaces": { + "ComponentScriptExecutor": { + "operations": { + "process": { + "inputs": { + "script-type": "kotlin", + "script-class-reference": "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts.SimpleStatusCheck", + "instance-dependencies": [ + "bluePrintPropertiesService" + ], + "dynamic-properties": "*simple-status-properties" + } + } + } + } + } + }, + "simple-error-check": { + "type": "component-script-executor", + "interfaces": { + "ComponentScriptExecutor": { + "operations": { + "process": { + "inputs": { + "script-type": "kotlin", + "script-class-reference": "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts.SimpleErrorCheck", + "instance-dependencies": [ + "bluePrintPropertiesService" + ], + "dynamic-properties": "*simple-status-properties" + } + } + } + } + } + }, + "health-check-script": { + "type": "component-script-executor", + "interfaces": { + "ComponentScriptExecutor": { + "operations": { + "process": { + "inputs": { + "script-type": "kotlin", + "script-class-reference": "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts.K8sHealthCheck", + "instance-dependencies": [ + "bluePrintPropertiesService" + ], + "dynamic-properties": "*simple-status-properties" + } + } + } + } + } + }, + "config-setup-process": { + "type": "component-resource-resolution", + "interfaces": { + "ResourceResolutionComponent": { + "operations": { + "process": { + "inputs": { + "resolution-key": { + "get_input": "resolution-key" + }, + "store-result": false, + "artifact-prefix-names": [ + "config-deploy" + ] + }, + "outputs": { + "resource-assignment-params": { + "get_attribute": [ + "SELF", + "assignment-params" + ] + }, + "status": "success" + } + } + } + } + }, + "artifacts": { + "config-deploy-template": { + "type": "artifact-template-velocity", + "file": "Templates/config-setup-template.vtl" + }, + "config-deploy-mapping": { + "type": "artifact-mapping-resource", + "file": "Templates/config-setup-mapping.json" + } + } + }, + "config-deploy-process": { + "type": "component-script-executor", + "interfaces": { + "ComponentScriptExecutor": { + "operations": { + "process": { + "inputs": { + "script-type": "kotlin", + "script-class-reference": "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts.ConfigDeploy", + "dynamic-properties": "*config-deploy-properties" + } + } + } + } + } + }, + "collect-results": { + "type": "component-script-executor", + "interfaces": { + "ComponentScriptExecutor": { + "operations": { + "process": { + "implementation": { + "primary": "component-script", + "timeout": 180, + "operation_host": "SELF" + }, + "inputs": { + "script-type": "kotlin", + "script-class-reference": "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts.CollectorScript" + }, + "outputs": {} + } + } + } + } + } + } + } +} diff --git a/tutorials/ApacheCNF/templates/cba/Definitions/artifact_types.json b/tutorials/ApacheCNF/templates/cba/Definitions/artifact_types.json new file mode 100644 index 00000000..4211156e --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Definitions/artifact_types.json @@ -0,0 +1,30 @@ +{ + "artifact_types": { + "artifact-mapping-resource": { + "description": "Resource Mapping File used along with Configuration template", + "version": "1.0.0", + "derived_from": "tosca.artifacts.Implementation", + "file_ext": [ + "json" + ] + }, + "artifact-template-velocity": { + "description": " Velocity Template used for Configuration", + "version": "1.0.0", + "derived_from": "tosca.artifacts.Implementation", + "file_ext": [ + "vtl" + ] + }, + "artifact-k8sprofile-content": { + "description": "K8s Profile Folder Artifact", + "version": "1.0.0", + "derived_from": "tosca.artifacts.Implementation" + }, + "artifact-k8sconfig-content": { + "description": "K8s Config Folder Artifact", + "version": "1.0.0", + "derived_from": "tosca.artifacts.Implementation" + } + } +} diff --git a/tutorials/ApacheCNF/templates/cba/Definitions/data_types.json b/tutorials/ApacheCNF/templates/cba/Definitions/data_types.json new file mode 100644 index 00000000..603b0baa --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Definitions/data_types.json @@ -0,0 +1,363 @@ +{ + "data_types": { + "dt-config-assign-properties": { + "description": "Dynamic DataType definition for workflow(config-assign).", + "version": "1.0.0", + "properties": { + "service-instance-id": { + "description": "", + "required": false, + "type": "string" + }, + "vnf-id": { + "description": "", + "required": false, + "type": "string" + } + }, + "derived_from": "tosca.datatypes.Dynamic" + }, + "dt-config-deploy-properties": { + "description": "Dynamic DataType definition for workflow(config-deploy).", + "version": "1.0.0", + "properties": { + "service-instance-id": { + "description": "", + "required": false, + "type": "string" + }, + "vnf-id": { + "description": "", + "required": false, + "type": "string" + } + }, + "derived_from": "tosca.datatypes.Dynamic" + }, + "dt-health-check-properties": { + "description": "Dynamic DataType definition for workflow(health-check).", + "version": "1.0.0", + "properties": { + "service-instance-id": { + "description": "", + "required": false, + "type": "string" + }, + "vnf-id": { + "description": "", + "required": false, + "type": "string" + }, + "service-instance.service-instance-id": { + "description": "", + "required": false, + "type": "string" + }, + "generic-vnf.vnf-id": { + "description": "", + "required": false, + "type": "string" + } + }, + "derived_from": "tosca.datatypes.Dynamic" + }, + "dt-scale-out-properties": { + "description": "Dynamic DataType definition for workflow(scale-out).", + "version": "1.0.0", + "properties": { + "service-instance-id": { + "description": "", + "required": false, + "type": "string" + }, + "vnf-id": { + "description": "", + "required": false, + "type": "string" + }, + "service-instance.service-instance-id": { + "description": "", + "required": false, + "type": "string" + }, + "generic-vnf.vnf-id": { + "description": "", + "required": false, + "type": "string" + }, + "replica-count": { + "description": "replica count for apache pods", + "type": "integer", + "default": 2 + } + }, + "derived_from": "tosca.datatypes.Dynamic" + }, + "dt-scale-in-properties": { + "description": "Dynamic DataType definition for workflow(scale-in).", + "version": "1.0.0", + "properties": { + "service-instance-id": { + "description": "", + "required": false, + "type": "string" + }, + "vnf-id": { + "description": "", + "required": false, + "type": "string" + }, + "service-instance.service-instance-id": { + "description": "", + "required": false, + "type": "string" + }, + "generic-vnf.vnf-id": { + "description": "", + "required": false, + "type": "string" + }, + "replica-count": { + "description": "replica count for apache pods", + "type": "integer", + "default": 1 + } + }, + "derived_from": "tosca.datatypes.Dynamic" + }, + "dt-scale-properties": { + "description": "Dynamic DataType definition for workflow(scale).", + "version": "1.0.0", + "properties": { + "service-instance-id": { + "description": "", + "required": false, + "type": "string" + }, + "vnf-id": { + "description": "", + "required": false, + "type": "string" + }, + "service-instance.service-instance-id": { + "description": "", + "required": false, + "type": "string" + }, + "generic-vnf.vnf-id": { + "description": "", + "required": false, + "type": "string" + }, + "replica-count": { + "description": "replica count for apache pods", + "type": "integer", + "required": false + }, + "data": { + "description": "the data content of the policy request parameters", + "required": false, + "type": "json" + } + }, + "derived_from": "tosca.datatypes.Dynamic" + }, + "dt-resource-assignment-properties": { + "description": "Dynamic DataType definition for workflow(resource-assignment).", + "version": "1.0.0", + "properties": { + "replica-count": { + "description": "replica count for apache pods", + "type": "integer", + "default": 0 + }, + "k8s-rb-profile-namespace": { + "description": "K8s namespace to create helm chart for specified profile", + "type": "string" + }, + "k8s-rb-profile-name": { + "description": "Profile name used in multicloud/k8s plugin to identify Helm chart(s) where this mapping is providing override values.", + "type": "string" + }, + "k8s-rb-instance-release-name": { + "description": "Name of the release for the helm package instance in k8s", + "type": "string" + }, + "k8s-rb-profile-source": { + "description": "The source folder or file relative to 'Templates/k8s-profiles' folder", + "type": "string" + }, + "k8s-rb-profile-k8s-version": { + "description": "Profile k8s version used in multicloud/k8s plugin", + "type": "string" + }, + "k8s-rb-config-template-name": { + "description": "The name of configuration template for config-assign operation", + "type": "string" + }, + "k8s-rb-config-template-source": { + "description": "The source of configuration template for config-assign operation", + "type": "string" + }, + "k8s-rb-config-name": { + "description": "The source of configuration values for config-deploy operation", + "type": "string" + }, + "k8s-rb-config-value-source": { + "description": "The source of configuration values for config-deploy operation", + "type": "string" + }, + "private1-prefix-id": { + "description": "", + "required": false, + "type": "string" + }, + "private2-prefix-id": { + "description": "", + "required": false, + "type": "string" + }, + "vnf-id": { + "description": "", + "required": false, + "type": "string" + }, + "service-instance-id": { + "description": "", + "required": false, + "type": "string" + }, + "vnf_name": { + "description": "", + "required": false, + "type": "string" + }, + "demo_artifacts_version": { + "description": "", + "required": false, + "type": "string", + "default": "1.5.0" + }, + "aic-cloud-region": { + "description": "", + "required": false, + "type": "string" + }, + "vf-module-model-customization-uuid": { + "description": "", + "required": false, + "type": "string" + }, + "onap_private_net_cidr": { + "description": "", + "required": false, + "type": "string" + }, + "management-prefix-id": { + "description": "", + "required": false, + "type": "string" + }, + "dcae_collector_ip": { + "description": "", + "required": false, + "type": "string", + "default": "10.0.4.1" + }, + "int_private1_net_cidr": { + "description": "", + "required": false, + "type": "string" + }, + "vf-module-id": { + "description": "", + "required": false, + "type": "string" + }, + "dcae_collector_port": { + "description": "", + "required": false, + "type": "string", + "default": "30235" + }, + "vf-module-name": { + "description": "", + "required": false, + "type": "string" + }, + "vf-module-label": { + "description": "", + "required": false, + "type": "string" + }, + "vf-module-model-invariant-uuid": { + "type": "string" + }, + "vf-naming-policy": { + "description": "", + "required": false, + "type": "string" + }, + "int_private2_net_cidr": { + "description": "", + "required": false, + "type": "string" + }, + "vf-module-model-version": { + "type": "string" + }, + "core-instance-name": { + "description": "Name of 5g core instance that requires PNF registration", + "type": "string" + } + }, + "derived_from": "tosca.datatypes.Dynamic" + }, + "dt-ue-subscribe-properties": { + "description": "Dynamic DataType definition for workflow(ue-subscription).", + "version": "1.0.0", + "properties": { + "service-instance-id": { + "description": "", + "required": false, + "type": "string" + }, + "vnf-id": { + "description": "", + "required": false, + "type": "string" + }, + "vf-modules-list": { + "type": "json" + }, + "config-deploy-setup": { + "type": "json" + } + }, + "derived_from": "tosca.datatypes.Dynamic" + }, + "dt-ue-reconfiguration-properties": { + "description": "Dynamic DataType definition for workflow(ue-reconfiguration).", + "version": "1.0.0", + "properties": { + "service-instance-id": { + "description": "", + "required": false, + "type": "string" + }, + "vnf-id": { + "description": "", + "required": false, + "type": "string" + }, + "vf-modules-list": { + "type": "json" + }, + "config-deploy-setup": { + "type": "json" + } + }, + "derived_from": "tosca.datatypes.Dynamic" + } + } +} diff --git a/tutorials/ApacheCNF/templates/cba/Definitions/node_types.json b/tutorials/ApacheCNF/templates/cba/Definitions/node_types.json new file mode 100644 index 00000000..c191f164 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Definitions/node_types.json @@ -0,0 +1,676 @@ +{ + "node_types": { + "component-resource-resolution": { + "description": "This is Resource Assignment Component API", + "version": "1.0.0", + "attributes": { + "assignment-params": { + "description": "Holds resolved template, resolution-summary or key-value", + "required": true, + "type": "string" + }, + "assignment-map": { + "description": "Holds resolved values for each artifact prefix eg. { vdns: { vnf-id: 123 } }", + "required": true, + "type": "map" + } + }, + "capabilities": { + "component-node": { + "type": "tosca.capabilities.Node" + } + }, + "interfaces": { + "ResourceResolutionComponent": { + "operations": { + "process": { + "inputs": { + "resolution-key": { + "description": "Key for service instance related correlation.", + "required": false, + "type": "string" + }, + "occurrence": { + "description": "Number of time to perform the resolution.", + "required": false, + "default": 1, + "type": "integer" + }, + "store-result": { + "description": "Whether or not to store the output.", + "required": false, + "type": "boolean" + }, + "resource-type": { + "description": "Request type.", + "required": false, + "type": "string" + }, + "resolution-summary": { + "description": "Enable resolution-summary output", + "required": false, + "type": "boolean" + }, + "artifact-prefix-names": { + "required": true, + "description": "Template , Resource Assignment Artifact Prefix names", + "type": "list", + "entry_schema": { + "type": "string" + } + }, + "request-id": { + "description": "Request Id, Unique Id for the request.", + "required": true, + "type": "string" + }, + "resource-id": { + "description": "Resource Id.", + "required": false, + "type": "string" + }, + "action-name": { + "description": "Action Name of the process", + "required": false, + "type": "string" + }, + "dynamic-properties": { + "description": "Dynamic Json Content or DSL Json reference.", + "required": false, + "type": "json" + } + }, + "outputs": { + "resource-assignment-params": { + "required": true, + "type": "string" + }, + "resource-assignment-map": { + "required": true, + "type": "string" + }, + "status": { + "required": true, + "type": "string" + } + } + } + } + } + }, + "derived_from": "tosca.nodes.Component" + }, + "component-script-executor": { + "description": "This is CLI Transaction Configuration Component API", + "version": "1.0.0", + "attributes": { + "response-data": { + "required": false, + "type": "json" + } + }, + "capabilities": { + "component-node": { + "type": "tosca.capabilities.Node" + } + }, + "interfaces": { + "ComponentScriptExecutor": { + "operations": { + "process": { + "inputs": { + "script-type": { + "description": "Script type, kotlin type is supported", + "required": true, + "type": "string", + "constraints": [ + { + "valid_values": [ + "kotlin", + "jython", + "internal" + ] + } + ], + "default": "internal" + }, + "script-class-reference": { + "description": "Kotlin Script class name or jython script name.", + "required": true, + "type": "string" + }, + "instance-dependencies": { + "description": "Instance names to inject to Jython or Kotlin Script.", + "required": true, + "type": "list", + "entry_schema": { + "type": "string" + } + }, + "dynamic-properties": { + "description": "Dynamic Json Content or DSL Json reference.", + "required": false, + "type": "json" + } + }, + "outputs": { + "response-data": { + "description": "Execution Response Data.", + "required": false, + "type": "string" + }, + "status": { + "description": "Status of the Component Execution ( success or failure )", + "required": true, + "type": "string" + } + } + } + } + } + }, + "derived_from": "tosca.nodes.Component" + }, + "component-k8s-profile-upload": { + "description": "This component is rendering and sending the k8s profile to the multicloud plugin.", + "version": "1.0.0", + "attributes": { + "statuses": { + "required": true, + "type": "json" + } + }, + "capabilities": { + "component-node": { + "type": "tosca.capabilities.Node" + } + }, + "interfaces": { + "K8sProfileUploadComponent": { + "operations": { + "process": { + "inputs": { + "k8s-rb-profile-name": { + "description": "K8s profile name", + "required": false, + "type": "string" + }, + "k8s-rb-definition-name": { + "description": "K8s definition name", + "required": false, + "type": "string" + }, + "k8s-rb-definition-version": { + "description": "Version of the definition", + "required": false, + "type": "string" + }, + "k8s-rb-profile-namespace": { + "description": "a K8s namespace for the profile", + "required": false, + "type": "string" + }, + "k8s-rb-profile-k8s-version": { + "description": "a K8s cluster version for the profile", + "required": false, + "type": "string" + }, + "k8s-rb-profile-source": { + "description": "Source (tgz/folder) for the template in CBA", + "required": false, + "type": "string" + }, + "artifact-prefix-names": { + "description": "Resource Assignment Artifact Prefix names", + "required": false, + "type": "list", + "entry_schema": { + "type": "string" + } + }, + "resource-assignment-map": { + "description": "Holds resolved values for each artifact prefix eg. { vdns: { vnf-id: 123 } }", + "required": false, + "type": "json" + } + }, + "outputs": { + "statuses": { + "required": true, + "type": "string" + } + } + } + } + } + }, + "derived_from": "tosca.nodes.Component" + }, + "component-k8s-config-template": { + "description": "This component is rendering and sending the k8s template to the multicloud plugin.", + "version": "1.0.0", + "attributes": { + "statuses": { + "required": true, + "type": "json" + } + }, + "capabilities": { + "component-node": { + "type": "tosca.capabilities.Node" + } + }, + "interfaces": { + "K8sConfigTemplateComponent": { + "operations": { + "process": { + "inputs": { + "k8s-rb-config-template-name": { + "description": "K8s template name", + "required": false, + "type": "string" + }, + "k8s-rb-definition-name": { + "description": "K8s definition name", + "required": false, + "type": "string" + }, + "k8s-rb-definition-version": { + "description": "Version of the definition", + "required": false, + "type": "string" + }, + "k8s-rb-config-template-source": { + "description": "Source (tgz/folder) for the template in CBA", + "required": false, + "type": "string" + }, + "artifact-prefix-names": { + "description": "Resource Assignment Artifact Prefix names", + "required": false, + "type": "list", + "entry_schema": { + "type": "string" + } + }, + "resource-assignment-map": { + "description": "Holds resolved values for each artifact prefix eg. { vdns: { vnf-id: 123 } }", + "required": false, + "type": "json" + } + }, + "outputs": { + "statuses": { + "required": true, + "type": "string" + } + } + } + } + } + }, + "derived_from": "tosca.nodes.Component" + }, + "component-k8s-config-value": { + "description": "This component is sending the k8s config value to the multicloud plugin.", + "version": "1.0.0", + "attributes": { + "statuses": { + "required": true, + "type": "json" + } + }, + "capabilities": { + "component-node": { + "type": "tosca.capabilities.Node" + } + }, + "interfaces": { + "K8sConfigValueComponent": { + "operations": { + "process": { + "inputs": { + "k8s-rb-config-template-name": { + "description": "K8s template name", + "required": false, + "type": "string" + }, + "k8s-rb-config-name": { + "description": "K8s config name", + "required": false, + "type": "string" + }, + "k8s-instance-id": { + "description": "K8s instance id", + "required": false, + "type": "string" + }, + "k8s-rb-config-value-source": { + "description": "Location of value source in CBA", + "required": false, + "type": "string" + }, + "k8s-config-operation-type": { + "required": false, + "type": "string", + "constraints": [ + { + "valid_values": [ + "create", + "update", + "delete" + ] + } + ], + "default": "create" + }, + "artifact-prefix-names": { + "description": "Resource Assignment Artifact Prefix names", + "required": false, + "type": "list", + "entry_schema": { + "type": "string" + } + }, + "resource-assignment-map": { + "description": "Holds resolved values for each artifact prefix eg. { vdns: { vnf-id: 123 } }", + "required": false, + "type": "json" + } + }, + "outputs": { + "statuses": { + "required": true, + "type": "string" + } + } + } + } + } + }, + "derived_from": "tosca.nodes.Component" + }, + "source-capability": { + "description": "This is Component Resource Source Node Type", + "version": "1.0.0", + "properties": { + "script-type": { + "required": true, + "type": "string", + "constraints": [ + { + "valid_values": [ + "kotlin", + "internal", + "jython" + ] + } + ], + "default": "kotlin" + }, + "script-class-reference": { + "description": "Capability reference name for internal and kotlin, for jython script file path", + "required": true, + "type": "string" + }, + "instance-dependencies": { + "description": "Instance dependency Names to Inject to Kotlin / Jython Script.", + "required": false, + "type": "list", + "entry_schema": { + "type": "string" + } + }, + "key-dependencies": { + "description": "Resource Resolution dependency dictionary names.", + "required": true, + "type": "list", + "entry_schema": { + "type": "string" + } + } + }, + "derived_from": "tosca.nodes.ResourceSource" + }, + "source-db": { + "description": "This is Database Resource Source Node Type", + "version": "1.0.0", + "properties": { + "type": { + "required": true, + "type": "string", + "constraints": [ + { + "valid_values": [ + "SQL", + "PLSQL" + ] + } + ], + "default": "SQL" + }, + "endpoint-selector": { + "required": false, + "type": "string" + }, + "query": { + "required": true, + "type": "string" + }, + "input-key-mapping": { + "required": false, + "type": "map", + "entry_schema": { + "type": "string" + } + }, + "output-key-mapping": { + "required": false, + "type": "map", + "entry_schema": { + "type": "string" + } + }, + "key-dependencies": { + "required": true, + "type": "list", + "entry_schema": { + "type": "string" + } + } + }, + "derived_from": "tosca.nodes.ResourceSource" + }, + "source-default": { + "description": "This is Default Resource Source Node Type", + "version": "1.0.0", + "properties": {}, + "derived_from": "tosca.nodes.ResourceSource" + }, + "source-input": { + "description": "This is Input Resource Source Node Type", + "version": "1.0.0", + "properties": {}, + "derived_from": "tosca.nodes.ResourceSource" + }, + "source-rest": { + "description": "This is Rest Resource Source Node Type", + "version": "1.0.0", + "properties": { + "type": { + "required": true, + "type": "string", + "constraints": [ + { + "valid_values": [ + "JSON" + ] + } + ], + "default": "JSON" + }, + "headers": { + "required": false, + "type": "map", + "entry_schema": { + "type": "string" + } + }, + "verb": { + "required": true, + "type": "string", + "constraints": [ + { + "valid_values": [ + "GET", + "POST", + "DELETE", + "PUT" + ] + } + ], + "default": "GET" + }, + "payload": { + "required": false, + "type": "string", + "default": "" + }, + "endpoint-selector": { + "required": false, + "type": "string" + }, + "url-path": { + "required": true, + "type": "string" + }, + "path": { + "required": true, + "type": "string" + }, + "expression-type": { + "required": false, + "type": "string", + "constraints": [ + { + "valid_values": [ + "JSON_PATH", + "JSON_POINTER" + ] + } + ], + "default": "JSON_PATH" + }, + "input-key-mapping": { + "required": false, + "type": "map", + "entry_schema": { + "type": "string" + } + }, + "output-key-mapping": { + "required": false, + "type": "map", + "entry_schema": { + "type": "string" + } + }, + "key-dependencies": { + "required": true, + "type": "list", + "entry_schema": { + "type": "string" + } + } + }, + "derived_from": "tosca.nodes.ResourceSource" + }, + "tosca.nodes.Component": { + "description": "This is default Component Node", + "version": "1.0.0", + "derived_from": "tosca.nodes.Root" + }, + "tosca.nodes.ResourceSource": { + "description": "TOSCA base type for Resource Sources", + "version": "1.0.0", + "derived_from": "tosca.nodes.Root" + }, + "tosca.nodes.Vnf": { + "description": "This is VNF Node Type", + "version": "1.0.0", + "derived_from": "tosca.nodes.Root" + }, + "tosca.nodes.Workflow": { + "description": "This is Directed Graph Node Type", + "version": "1.0.0", + "derived_from": "tosca.nodes.Root" + }, + "vnf-netconf-device": { + "description": "This is VNF Device with Netconf Capability", + "version": "1.0.0", + "capabilities": { + "netconf": { + "type": "tosca.capabilities.Netconf", + "properties": { + "login-key": { + "required": true, + "type": "string", + "default": "sdnc" + }, + "login-account": { + "required": true, + "type": "string", + "default": "sdnc-tacacs" + }, + "source": { + "required": false, + "type": "string", + "default": "npm" + }, + "target-ip-address": { + "required": true, + "type": "string" + }, + "port-number": { + "required": true, + "type": "integer", + "default": 830 + }, + "connection-time-out": { + "required": false, + "type": "integer", + "default": 30 + } + } + }, + "restconf": { + "type": "tosca.capabilities.Restconf", + "properties": { + "login-key": { + "required": true, + "type": "string" + }, + "login-account": { + "required": true, + "type": "string" + }, + "target-ip-address": { + "required": true, + "type": "string" + }, + "port-number": { + "required": true, + "type": "integer" + }, + "connection-time-out": { + "required": false, + "type": "integer", + "default": 30 + } + } + } + }, + "derived_from": "tosca.nodes.Vnf" + } + } +} diff --git a/tutorials/ApacheCNF/templates/cba/Definitions/policy_types.json b/tutorials/ApacheCNF/templates/cba/Definitions/policy_types.json new file mode 100644 index 00000000..335746c4 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Definitions/policy_types.json @@ -0,0 +1,3 @@ +{ + "policy_types": {} +} diff --git a/tutorials/ApacheCNF/templates/cba/Definitions/relationship_types.json b/tutorials/ApacheCNF/templates/cba/Definitions/relationship_types.json new file mode 100644 index 00000000..8a388510 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Definitions/relationship_types.json @@ -0,0 +1,3 @@ +{ + "relationship_types": {} +} diff --git a/tutorials/ApacheCNF/templates/cba/Definitions/resources_definition_types.json b/tutorials/ApacheCNF/templates/cba/Definitions/resources_definition_types.json new file mode 100644 index 00000000..38b5fee4 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Definitions/resources_definition_types.json @@ -0,0 +1,1516 @@ +{ + "active-streams": { + "tags": "active-streams", + "name": "active-streams", + "property": { + "description": "active-streams", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + } + } + }, + "aic-cloud-region": { + "tags": "aic-cloud-region", + "name": "aic-cloud-region", + "property": { + "description": "aic-cloud-region", + "type": "string" + }, + "group": "default", + "updated-by": "Singal, Kapil ", + "sources": { + "input": { + "type": "source-input", + "properties": {} + } + } + }, + "dcae_collector_ip": { + "tags": "dcae_collector_ip", + "name": "dcae_collector_ip", + "property": { + "description": "dcae_collector_ip", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vnf-topology/vnf-parameters-data/param/dcae_collector_ip", + "path": "/param/0/value", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "dcae_collector_ip": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + } + } + }, + "dcae_collector_port": { + "tags": "dcae_collector_port", + "name": "dcae_collector_port", + "property": { + "description": "dcae_collector_port", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vnf-topology/vnf-parameters-data/param/dcae_collector_port", + "path": "/param/0/value", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "dcae_collector_port": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + } + } + }, + "demo_artifacts_version": { + "tags": "demo_artifacts_version", + "name": "demo_artifacts_version", + "property": { + "description": "demo_artifacts_version", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vnf-topology/vnf-parameters-data/param/demo_artifacts_version", + "path": "/param/0/value", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "demo_artifacts_version": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + } + } + }, + "int_private1_net_cidr": { + "tags": "int_private1_net_cidr", + "name": "int_private1_net_cidr", + "property": { + "description": "int_private1_net_cidr", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vnf-topology/vnf-parameters-data/param/int_private1_net_cidr", + "path": "/param/0/value", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "int_private1_net_cidr": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + }, + "processor-db": { + "type": "source-db", + "properties": { + "type": "SQL", + "query": "select sdnctl.IPAM_IP_POOL.prefix as prefix from sdnctl.IPAM_IP_POOL where description = \"private1\"", + "input-key-mapping": {}, + "output-key-mapping": { + "int_private1_net_cidr": "prefix" + } + } + } + } + }, + "int_private2_net_cidr": { + "tags": "int_private2_net_cidr", + "name": "int_private2_net_cidr", + "property": { + "description": "int_private2_net_cidr", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "processor-db": { + "type": "source-db", + "properties": { + "type": "SQL", + "query": "select sdnctl.IPAM_IP_POOL.prefix as prefix from sdnctl.IPAM_IP_POOL where description = \"private2\"", + "output-key-mapping": { + "int_private2_net_cidr": "prefix" + }, + "input-key-mapping": {} + } + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vnf-topology/vnf-parameters-data/param/int_private2_net_cidr", + "path": "/param/0/value", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "int_private2_net_cidr": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + } + } + }, + "k8s-rb-profile-name": { + "tags": "k8s, cnf, profile, k8s-rb-profile-name", + "name": "k8s-rb-profile-name", + "property": { + "description": "Profile name used in multicloud/k8s plugin to identify Helm chart(s) where this mapping is providing override values.", + "type": "string" + }, + "group": "default", + "updated-by": "Samuli, Silvius ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + } + } + }, + "k8s-rb-instance-release-name": { + "tags": "k8s, cnf, profile, k8s-rb-instance-release-name", + "name": "k8s-rb-instance-release-name", + "property": { + "description": "Name of the release for the helm package instance in k8s", + "type": "string" + }, + "group": "default", + "updated-by": "Rajewski, Lukasz ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + } + } + }, + "k8s-rb-profile-namespace": { + "tags": "k8s, cnf, profile, namespace, k8s-rb-profile-namespace", + "name": "k8s-rb-profile-namespace", + "property": { + "description": "Profile name used in multicloud/k8s plugin", + "type": "string" + }, + "group": "default", + "updated-by": "Samuli, Silvius ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vnf-topology/vnf-parameters-data/param/k8s-rb-profile-namespace", + "path": "/param/0/value", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "k8s-rb-profile-namespace": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + } + } + }, + "k8s-rb-profile-k8s-version": { + "tags": "k8s, cnf, profile, k8s version, k8s-rb-profile-k8s-version", + "name": "k8s-rb-profile-k8s-version", + "property": { + "description": "Profile k8s version used in multicloud/k8s plugin", + "type": "string" + }, + "group": "default", + "updated-by": "Rajewski, Lukasz ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vnf-topology/vnf-parameters-data/param/k8s-rb-profile-k8s-version", + "path": "/param/0/value", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "k8s-rb-profile-k8s-version": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + } + } + }, + "k8s-rb-profile-source": { + "tags": "k8s, cnf, profile, k8s-rb-profile-source", + "name": "k8s-rb-profile-source", + "property": { + "description": "The source folder or file relative to 'Templates/k8s-profiles' folder", + "type": "string" + }, + "group": "default", + "updated-by": "Rajewski, Lukasz ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + } + } + }, + "k8s-rb-config-template-name": { + "tags": "k8s, cnf, config, k8s-rb-config-template-name", + "name": "k8s-rb-config-template-name", + "property": { + "description": "The name of configuration template for config-assign operation", + "type": "string" + }, + "group": "default", + "updated-by": "Rajewski, Lukasz ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + } + } + }, + "k8s-rb-config-template-source": { + "tags": "k8s, cnf, config, k8s-rb-config-template-source", + "name": "k8s-rb-config-template-source", + "property": { + "description": "The source of configuration template for config-assign operation", + "type": "string" + }, + "group": "default", + "updated-by": "Rajewski, Lukasz ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + } + } + }, + "k8s-rb-config-value-source": { + "tags": "k8s, cnf, config, k8s-rb-config-value-source", + "name": "k8s-rb-config-value-source", + "property": { + "description": "The source of configuration values for config-deploy operation", + "type": "string" + }, + "group": "default", + "updated-by": "Rajewski, Lukasz ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + } + } + }, + "k8s-rb-config-name": { + "tags": "k8s, cnf, config, k8s-rb-config-name", + "name": "k8s-rb-config-name", + "property": { + "description": "The source of configuration values for config-deploy operation", + "type": "string" + }, + "group": "default", + "updated-by": "Rajewski, Lukasz ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + } + } + }, + "management-prefix-id": { + "tags": "management-prefix-id", + "name": "management-prefix-id", + "property": { + "description": "management-prefix-id", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vnf-topology/vnf-parameters-data/param/management-prefix-id", + "path": "/param/0/value", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "management-prefix-id": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + }, + "processor-db": { + "type": "source-db", + "properties": { + "type": "SQL", + "query": "select sdnctl.IPAM_IP_POOL.prefix_id as prefix_id from sdnctl.IPAM_IP_POOL where description = \"management\"", + "input-key-mapping": {}, + "output-key-mapping": { + "management-prefix-id": "prefix_id" + } + } + } + } + }, + "onap_private_net_cidr": { + "tags": "onap_private_net_cidr", + "name": "onap_private_net_cidr", + "property": { + "description": "onap_private_net_cidr", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "processor-db": { + "type": "source-db", + "properties": { + "type": "SQL", + "query": "select sdnctl.IPAM_IP_POOL.prefix as prefix from sdnctl.IPAM_IP_POOL where description = \"management\"", + "input-key-mapping": {}, + "output-key-mapping": { + "onap_private_net_cidr": "prefix" + } + } + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vnf-topology/vnf-parameters-data/param/onap_private_net_cidr", + "path": "/param/0/value", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "onap_private_net_cidr": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + } + } + }, + "private1-prefix-id": { + "tags": "private1-prefix-id", + "name": "private1-prefix-id", + "property": { + "description": "private1-prefix-id", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vnf-topology/vnf-parameters-data/param/private1-prefix-id", + "path": "/param/0/value", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "private1-prefix-id": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + }, + "processor-db": { + "type": "source-db", + "properties": { + "type": "SQL", + "query": "select sdnctl.IPAM_IP_POOL.prefix_id as prefix_id from sdnctl.IPAM_IP_POOL where description = \"private1\"", + "input-key-mapping": {}, + "output-key-mapping": { + "private1-prefix-id": "prefix_id" + } + } + } + } + }, + "private2-prefix-id": { + "tags": "private2-prefix-id", + "name": "private2-prefix-id", + "property": { + "description": "private2-prefix-id", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vnf-topology/vnf-parameters-data/param/private2-prefix-id", + "path": "/param/0/value", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "private2-prefix-id": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + }, + "processor-db": { + "type": "source-db", + "properties": { + "type": "SQL", + "query": "select sdnctl.IPAM_IP_POOL.prefix_id as prefix_id from sdnctl.IPAM_IP_POOL where description = \"private2\"", + "input-key-mapping": {}, + "output-key-mapping": { + "private2-prefix-id": "prefix_id" + } + } + } + } + }, + "put-active-streams": { + "tags": "put-active-streams", + "name": "put-active-streams", + "property": { + "description": "put-active-streams", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "PUT", + "type": "JSON", + "url-path": "$vpg_onap_private_ip_0:8183/restconf/config/stream-count:stream-count/streams", + "path": "/param/0/value", + "input-key-mapping": { + "vpg_onap_private_ip_0": "vpg_onap_private_ip_0", + "active-streams": "active-streams" + }, + "output-key-mapping": {}, + "key-dependencies": [ + "vpg_onap_private_ip_0", + "active-streams" + ], + "endpoint-selector": "vpkg-rest-api", + "payload": "{\"streams\": {\"active-streams\": $active-streams}}" + } + } + } + }, + "service-instance-id": { + "tags": "service-instance-id, tosca.datatypes.Root, data_type", + "name": "service-instance-id", + "property": { + "description": "To be provided", + "type": "string" + }, + "group": "default", + "updated-by": "Singal, Kapil ", + "sources": { + "input": { + "type": "source-input", + "properties": {} + }, + "any-db": { + "type": "source-db", + "properties": { + "query": "SELECT artifact_name FROM BLUEPRINT_RUNTIME where artifact_version=\"1.0.0\"", + "input-key-mapping": {}, + "output-key-mapping": { + "service-instance-id": "artifact_name" + } + } + }, + "processor-db": { + "type": "source-db", + "properties": { + "query": "SELECT artifact_name FROM BLUEPRINT_RUNTIME where artifact_version=\"1.0.0\"", + "input-key-mapping": {}, + "output-key-mapping": { + "service-instance-id": "artifact_name" + } + } + }, + "capability": { + "type": "source-capability", + "properties": { + "script-type": "kotlin", + "script-class-reference": "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts.ConfigDeploySetup", + "instance-dependencies": [] + } + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id", + "path": "/service/0/service-instance-id", + "input-key-mapping": { + "service-instance-id": "service-instance.service-instance-id" + }, + "output-key-mapping": { + "service-instance-id": "service-instance-id" + }, + "key-dependencies": [ + "service-instance.service-instance-id" + ] + } + } + } + }, + "vf-module-id": { + "tags": "vf-module-id", + "name": "vf-module-id", + "property": { + "description": "vf-module-id", + "type": "string" + }, + "group": "default", + "updated-by": "Singal, Kapil ", + "sources": { + "input": { + "type": "source-input", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vf-modules/vf-module/$vf-module-id", + "path": "/vf-module/0/vf-module-id", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id", + "vf-module-id": "vf-module.vf-module-id" + }, + "output-key-mapping": { + "vf-module-id": "vf-module-id" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id", + "vf-module.vf-module-id" + ] + } + } + } + }, + "vf-module-name": { + "tags": "vf-module-name", + "name": "vf-module-name", + "property": { + "description": "vf-module-name", + "type": "string" + }, + "group": "default", + "updated-by": "Singal, Kapil ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vf-modules/vf-module/$vf_module_id/vf-module-data/vf-module-topology/vf-module-parameters/param/vf-module-name", + "path": "/param/0/value", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "vf-module-name": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id", + "vf_module_id" + ] + } + }, + "rest": { + "type": "source-rest", + "properties": { + "endpoint-selector": "naming-resolution", + "verb": "POST", + "type": "JSON", + "headers": { + "Accept": "application/json", + "Content-Type": "application/json" + }, + "url-path": "/v1/genNetworkElementName", + "payload": "{\r\n \"elements\": [\r\n {\r\n \"resource-name\": \"vf-module-name\",\r\n \"resource-value\": \"${vf-module-name}\",\r\n \"external-key\": \"${vf-module-id}\",\r\n \"policy-instance-name\": \"${vf-naming-policy}\",\r\n \"naming-type\": \"VF-MODULE\",\r\n \"VNF_NAME\": \"${vnf_name}\",\r\n \"VF_MODULE_LABEL\":\"${vf-module-label}\",\r\n \"VF_MODULE_TYPE\":\"vfmt\"\r\n }\r\n ]\r\n}", + "path": "/elements/0/resource-value", + "input-key-mapping": { + "vf-naming-policy": "vf-naming-policy", + "vnf_name": "vnf_name", + "vf-module-label": "vf-module-label", + "vf-module-id": "vf-module-id" + }, + "output-key-mapping": { + "vf-module-name": "resource-value" + }, + "key-dependencies": [ + "vf-naming-policy", + "vnf_name", + "vf-module-label", + "vf-module-id" + ] + } + } + } + }, + "vf-module-type": { + "tags": "vf-module-type", + "name": "vf-module-type", + "property": { + "description": "vf-module-type", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "processor-db": { + "type": "source-db", + "properties": { + "type": "SQL", + "query": "select vf_module_type as vf_module_type from sdnctl.VF_MODULE_MODEL where customization_uuid=:customizationid", + "output-key-mapping": { + "vf-module-type": "vf_module_type" + }, + "input-key-mapping": { + "customizationid": "vf-module-model-customization-uuid" + }, + "key-dependencies": [ + "vf-module-model-customization-uuid" + ] + } + } + } + }, + "vf-module-label": { + "tags": "vf-module-label", + "name": "vf-module-label", + "property": { + "description": "vf-module-label", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "processor-db": { + "type": "source-db", + "properties": { + "type": "SQL", + "query": "select sdnctl.VF_MODULE_MODEL.vf_module_label as vf_module_label from sdnctl.VF_MODULE_MODEL where sdnctl.VF_MODULE_MODEL.customization_uuid=:customizationid", + "input-key-mapping": { + "customizationid": "vf-module-model-customization-uuid" + }, + "output-key-mapping": { + "vf-module-label": "vf_module_label" + }, + "key-dependencies": [ + "vf-module-model-customization-uuid" + ] + } + } + } + }, + "vf-module-model-customization-uuid": { + "tags": "vf-module-model-customization-uuid", + "name": "vf-module-model-customization-uuid", + "property": { + "description": "vf-module-model-customization-uuid", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + } + } + }, + "vf-module-model-invariant-uuid": { + "tags": "vnf, vf-module", + "name": "vf-module-model-invariant-uuid", + "property": { + "description": "vf module model invariant uuid", + "type": "string" + }, + "group": "default", + "updated-by": "Samuli, Silvius ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "processor-db": { + "type": "source-db", + "properties": { + "type": "SQL", + "query": "select sdnctl.VF_MODULE_MODEL.invariant_uuid as vf_module_model_invariant_uuid from sdnctl.VF_MODULE_MODEL where sdnctl.VF_MODULE_MODEL.customization_uuid=:customizationid", + "input-key-mapping": { + "customizationid": "vf-module-model-customization-uuid" + }, + "output-key-mapping": { + "vf-module-model-invariant-uuid": "vf_module_model_invariant_uuid" + }, + "key-dependencies": [ + "vf-module-model-customization-uuid" + ] + } + } + } + }, + "vf-module-model-version": { + "tags": "vnf, vf-module", + "name": "vf-module-model-version", + "property": { + "description": "vf module model model version", + "type": "string" + }, + "group": "default", + "updated-by": "Samuli, Silvius ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "processor-db": { + "type": "source-db", + "properties": { + "type": "SQL", + "query": "select sdnctl.VF_MODULE_MODEL.uuid as vf_module_model_version from sdnctl.VF_MODULE_MODEL where sdnctl.VF_MODULE_MODEL.customization_uuid=:customizationid", + "input-key-mapping": { + "customizationid": "vf-module-model-customization-uuid" + }, + "output-key-mapping": { + "vf-module-model-version": "vf_module_model_version" + }, + "key-dependencies": [ + "vf-module-model-customization-uuid" + ] + } + } + } + }, + "vf-naming-policy": { + "tags": "vf-naming-policy", + "name": "vf-naming-policy", + "property": { + "description": "vf-naming-policy", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vnf-topology/vnf-parameters-data/param/vf-naming-policy", + "path": "/param/0/value", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "vf-naming-policy": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + }, + "processor-db": { + "type": "source-db", + "properties": { + "type": "SQL", + "query": "select sdnctl.VF_MODEL.naming_policy as vf_naming_policy from sdnctl.VF_MODEL where sdnctl.VF_MODEL.customization_uuid=:vnf_model_customization_uuid", + "input-key-mapping": { + "vnf_model_customization_uuid": "vnf-model-customization-uuid" + }, + "output-key-mapping": { + "vf-naming-policy": "vf_naming_policy" + }, + "key-dependencies": [ + "vnf-model-customization-uuid" + ] + } + } + } + }, + "vnf-id": { + "tags": "vnf-id", + "name": "vnf-id", + "property": { + "description": "vnf-id", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "capability": { + "type": "source-capability", + "properties": { + "script-type": "kotlin", + "script-class-reference": "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts.ConfigDeploySetup", + "instance-dependencies": [] + } + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/", + "path": "/vnf/0/vnf-id", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "generic-vnf.vnf-id" + }, + "output-key-mapping": { + "vnf-id": "vnf-id" + }, + "key-dependencies": [ + "service-instance-id", + "generic-vnf.vnf-id" + ] + } + } + } + }, + "vnf_name": { + "tags": "vnf_name", + "name": "vnf_name", + "property": { + "description": "vnf_name", + "type": "string" + }, + "group": "default", + "updated-by": "MALAKOV, YURIY ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vnf-topology/vnf-parameters-data/param/vnf_name", + "path": "/param/0/value", + "headers": { + "Accept": "application/json", + "Content-Type": "application/json" + }, + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "vnf_name": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + }, + "rest": { + "type": "source-rest", + "properties": { + "endpoint-selector": "naming-resolution", + "verb": "POST", + "type": "JSON", + "headers": { + "Accept": "application/json", + "Content-Type": "application/json" + }, + "url-path": "/v1/genNetworkElementName", + "payload": "{\r\n \"elements\": [\r\n {\r\n \"resource-name\": \"vnf_name\",\r\n \"resource-value\": \"${vnf_name}\",\r\n \"external-key\": \"${vnf-id}\",\r\n \"policy-instance-name\": \"${vf-naming-policy}\",\r\n \"naming-type\": \"VNF\",\r\n \"AIC_CLOUD_REGION\": \"${aic-cloud-region}\"\r\n }\r\n ]\r\n}", + "path": "/elements/0/resource-value", + "input-key-mapping": { + "vnf-id": "vnf-id", + "aic-cloud-region": "aic-cloud-region", + "vf-naming-policy": "vf-naming-policy" + }, + "output-key-mapping": { + "vnf_name": "resource-value" + }, + "key-dependencies": [ + "vnf-id", + "aic-cloud-region", + "vf-naming-policy" + ] + } + } + } + }, + "replica-count": { + "tags": "replica-count", + "name": "replica-count", + "property": { + "description": "replica-count", + "type": "integer" + }, + "group": "default", + "updated-by": "Rajewski, Lukasz ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "capability": { + "type": "source-capability", + "properties": { + "script-type": "kotlin", + "script-class-reference": "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts.ConfigDeploySetup", + "instance-dependencies": [] + } + } + } + }, + "vpg_onap_private_ip_0": { + "tags": "vpg_onap_private_ip_0", + "name": "vpg_onap_private_ip_0", + "property": { + "description": "vpg_onap_private_ip_0", + "type": "string" + }, + "group": "default", + "updated-by": "Singal, Kapil ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vnf-topology/vnf-parameters-data/param/vpg_onap_private_ip_0", + "path": "/param/0/value", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "vpg_onap_private_ip_0": "value" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + } + } + }, + "vnf-relationship-list": { + "tags": "vnf-relationship-list", + "name": "vnf-relationship-list", + "property": { + "description": "Details about VNF relationships from AAI", + "type": "json" + }, + "group": "default", + "updated-by": "Lukasz Rajewski ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "aai-data": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/aai/v19/network/generic-vnfs/generic-vnf/${vnf-id}?depth=1", + "path": "/relationship-list", + "input-key-mapping": { + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "relationship-list": "relationship" + }, + "key-dependencies": [ + "vnf-id" + ] + } + } + } + }, + "vf-modules-list": { + "tags": "vf-modules-list", + "name": "vf-modules-list", + "property": { + "description": "List of vf-modules associated with vnf", + "type": "json" + }, + "group": "default", + "updated-by": "Lukasz Rajewski ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "aai-data": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/aai/v19/network/generic-vnfs/generic-vnf/${vnf-id}?depth=1", + "path": "/vf-modules", + "input-key-mapping": { + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "vf-modules": "vf-module" + }, + "key-dependencies": [ + "vnf-id" + ] + } + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id/service-data/vnfs/vnf/$vnf-id/vnf-data/vf-modules", + "path": "/vf-modules", + "input-key-mapping": { + "service-instance-id": "service-instance-id", + "vnf-id": "vnf-id" + }, + "output-key-mapping": { + "vf-modules": "vf-module" + }, + "key-dependencies": [ + "service-instance-id", + "vnf-id" + ] + } + } + } + }, + "config-deploy-setup": { + "tags": "config-deploy-setup", + "name": "config-deploy-setup", + "property": { + "description": "Configuration Input setup for config-deploy operation", + "type": "json" + }, + "group": "default", + "updated-by": "Lukasz Rajewski ", + "sources": { + "capability": { + "type": "source-capability", + "properties": { + "script-type": "kotlin", + "script-class-reference": "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts.ConfigDeploySetup", + "instance-dependencies": [] + } + } + } + }, + "registration-reconfiguration-parameters": { + "tags": "registration-reconfiguration-parameters", + "name": "registration-reconfiguration-parameters", + "property": { + "description": "Configuration Input setup for config-deploy operation", + "type": "json" + }, + "group": "default", + "updated-by": "Chabiera, Michal ", + "sources": { + "capability": { + "type": "source-capability", + "properties": { + "script-type": "kotlin", + "script-class-reference": "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts.ConfigDeploySetup", + "instance-dependencies": [] + } + } + } + }, + "pnf-instance-name": { + "tags": "pnf-instance-name", + "name": "pnf-instance-name", + "property": { + "description": "Configuration Input setup for config-deploy operation", + "type": "string" + }, + "group": "default", + "updated-by": "Chabiera, Michal ", + "sources": { + "capability": { + "type": "source-capability", + "properties": { + "script-type": "kotlin", + "script-class-reference": "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts.ConfigDeploySetup", + "instance-dependencies": [] + } + } + } + }, + "core-instance-name": { + "tags": "PNF, ueransim, core, core-instance-namee", + "name": "core-instance-name", + "property": { + "description": "Name of 5g core instance that requires PNF registration", + "type": "string" + }, + "group": "default", + "updated-by": "Chabiera, Michal ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + } + } + }, + "service-instance-name": { + "tags": "service-instance-name", + "name": "service-instance-name", + "property": { + "description": "service-instance-name", + "type": "string" + }, + "group": "default", + "updated-by": "Chabiera, Michal ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "sdnc": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/restconf/config/GENERIC-RESOURCE-API:services/service/$service-instance-id", + "path": "/service/0/service-data/service-topology/service-topology-identifier/service-instance-name", + "input-key-mapping": { + "service-instance-id": "service-instance-id" + }, + "output-key-mapping": { + "service-instance-name": "value" + }, + "key-dependencies": [ + "service-instance-id" + ] + } + } + } + }, + "pnf-details-aai": { + "tags": "pnf-details-aai", + "name": "pnf-details-aai", + "property": { + "description": "PNF details stored in AAI", + "type": "json" + }, + "group": "default", + "updated-by": "Chabiera, Michal ", + "sources": { + "input": { + "type": "source-input" + }, + "default": { + "type": "source-default", + "properties": {} + }, + "aai-data": { + "type": "source-rest", + "properties": { + "verb": "GET", + "type": "JSON", + "url-path": "/aai/v19/network/pnfs?pnf-name=$pnf-instance-name", + "path": "", + "input-key-mapping": { + "pnf-instance-name": "pnf-instance-name" + }, + "output-key-mapping": { + "pnf": "pnf" + }, + "key-dependencies": [ + "pnf-instance-name" + ] + } + } + } + } +} diff --git a/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/CollectorScript.kt b/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/CollectorScript.kt new file mode 100644 index 00000000..589b9342 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/CollectorScript.kt @@ -0,0 +1,53 @@ +/* + * Copyright © 2021 Bell Canada. + * + * 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. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts + +import com.fasterxml.jackson.databind.JsonNode +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentScriptExecutor +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode +import org.onap.ccsdk.cds.controllerblueprints.core.logger + +open class CollectorScript : AbstractScriptComponentFunction() { + + private val log = logger(CollectorScript::class) + + override suspend fun processNB(executionRequest: ExecutionServiceInput) { + bluePrintRuntimeService.bluePrintContext() + .serviceTemplate.topologyTemplate!!.nodeTemplates!! + .keys.filter { it.startsWith("execute-script") } + .associateWith { responseData(it) } + .let { it.asJsonNode() } + .also { log.info("Collected results: $it") } + .let { setAttribute(ComponentScriptExecutor.ATTRIBUTE_RESPONSE_DATA, it) } + } + + private fun responseData(nodeTemplateName: String): JsonNode? { + return try { + bluePrintRuntimeService.getNodeTemplateAttributeValue( + nodeTemplateName, + ComponentScriptExecutor.ATTRIBUTE_RESPONSE_DATA + ) + } catch (exception: BluePrintProcessorException) { null } + } + + override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { + addError(runtimeException.message ?: "Failed without error message") + } +} diff --git a/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/ConfigDeploy.kt b/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/ConfigDeploy.kt new file mode 100644 index 00000000..96b3c515 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/ConfigDeploy.kt @@ -0,0 +1,48 @@ +/* + * Copyright © 2021 Orange + * + * 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. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts + +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.storedContentFromResolvedArtifactNB +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction +import org.slf4j.LoggerFactory + +open class ConfigDeploy : AbstractScriptComponentFunction() { + + private val log = LoggerFactory.getLogger(ConfigDeploy::class.java)!! + + override fun getName(): String { + return "ConfigDeploy" + } + + override suspend fun processNB(executionRequest: ExecutionServiceInput) { + val resolutionKey = getDynamicProperties("resolution-key").asText() + log.info("Got the resolution_key: $resolutionKey from config-deploy going to retrieve the data from DB") + val prefix = "config-deploy" // used in the config-assign resolution + + val payload = storedContentFromResolvedArtifactNB(resolutionKey, prefix) + log.info("cnf configuration data from DB : \n$payload\n") + + println("Run config-deploy") + println("$payload") + } + + override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { + log.info("Executing Recovery") + this.addError("${runtimeException.message}") + } +} diff --git a/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/ConfigDeploySetup.kt b/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/ConfigDeploySetup.kt new file mode 100644 index 00000000..77d86d04 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/ConfigDeploySetup.kt @@ -0,0 +1,145 @@ +/* + * Copyright © 2021 Orange + * + * 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. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts + +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.node.ObjectNode +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.definition.template.K8sConfigTemplateComponent +import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.definition.template.K8sConfigValueComponent +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor.ResourceAssignmentProcessor +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.isNullOrMissing +import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment +import org.slf4j.LoggerFactory + +open class ConfigDeploySetup() : ResourceAssignmentProcessor() { + + private val log = LoggerFactory.getLogger(ConfigDeploySetup::class.java)!! + + override fun getName(): String { + return "ConfigDeploySetup" + } + + override suspend fun processNB(executionRequest: ResourceAssignment) { + + var retValue: Any? = null + + try { + if (executionRequest.name == "service-instance-id") { + var value = raRuntimeService.getInputValue(executionRequest.name) + if (!value.isNullOrMissing()) { + retValue = value.asText() + } else { + val vnfRelationshipList = raRuntimeService.getResolutionStore("vnf-relationship-list") + if (!vnfRelationshipList.isNullOrMissing()) { + vnfRelationshipList["relationship-list"].forEach { relation -> + if (relation["related-to"].asText() == "service-instance") { + relation["relationship-data"].forEach { data -> + if (data["relationship-key"].asText() == "service-instance.service-instance-id") { + retValue = data["relationship-value"].asText() + } + } + } + } + } + } + } else if (executionRequest.name == "vnf-id") { + var value = raRuntimeService.getInputValue(executionRequest.name) + if (!value.isNullOrMissing()) { + retValue = value.asText() + } else { + value = raRuntimeService.getInputValue("generic-vnf.vnf-id") + if (!value.isNullOrMissing()) { + retValue = value.asText() + } + } + } else if (executionRequest.name == "replica-count") { + var value = raRuntimeService.getInputValue(executionRequest.name) + retValue = "1" + if (!value.isNullOrMissing()) { + retValue = value.asText() + } else { + value = raRuntimeService.getInputValue("data") + if (!value.isNullOrMissing()) { + if (value["replicaCount"] != null) { + retValue = value["replicaCount"].asText() + } + } + } + } else if (executionRequest.name == "config-deploy-setup") { + val modulesSdnc = raRuntimeService.getResolutionStore("vf-modules-list-sdnc")["vf-modules"] + val modulesAai = raRuntimeService.getResolutionStore("vf-modules-list-aai")["vf-modules"] + val objectMapper = jacksonObjectMapper() + val result: ObjectNode = objectMapper.createObjectNode() + for (module in modulesSdnc) { + val modelTopology = module.at("/vf-module-data/vf-module-topology") + val moduleParameters = modelTopology.at("/vf-module-parameters/param") + val label: String? = getParamValueByName(moduleParameters, "vf_module_label") + if (label != null) { + val modelInfo = modelTopology["onap-model-information"] + val moduleData: ObjectNode = objectMapper.createObjectNode() + result.put(label, moduleData) + moduleData.put(K8sConfigTemplateComponent.INPUT_K8S_DEFINITION_NAME, modelInfo["model-invariant-uuid"].asText()) + moduleData.put(K8sConfigTemplateComponent.INPUT_K8S_DEFINITION_VERSION, modelInfo["model-customization-uuid"].asText()) + val templateName: String? = getParamValueByName(moduleParameters, K8sConfigTemplateComponent.INPUT_K8S_TEMPLATE_NAME) + val templateSource: String? = getParamValueByName(moduleParameters, K8sConfigTemplateComponent.INPUT_K8S_TEMPLATE_SOURCE) + val configValueSource: String? = getParamValueByName(moduleParameters, K8sConfigValueComponent.INPUT_K8S_CONFIG_VALUE_SOURCE) + val configName: String? = getParamValueByName(moduleParameters, K8sConfigValueComponent.INPUT_K8S_RB_CONFIG_NAME) + + if (templateName != null) + moduleData.put(K8sConfigTemplateComponent.INPUT_K8S_TEMPLATE_NAME, templateName) + if (templateSource != null) + moduleData.put(K8sConfigTemplateComponent.INPUT_K8S_TEMPLATE_SOURCE, templateSource) + if (configValueSource != null) + moduleData.put(K8sConfigValueComponent.INPUT_K8S_CONFIG_VALUE_SOURCE, configValueSource) + if (configName != null) + moduleData.put(K8sConfigValueComponent.INPUT_K8S_RB_CONFIG_NAME, configName) + + for (aaiModule in modulesAai) { + if (aaiModule["vf-module-id"].asText() == module["vf-module-id"].asText() && aaiModule["heat-stack-id"] != null) { + moduleData.put(K8sConfigValueComponent.INPUT_K8S_INSTANCE_ID, aaiModule["heat-stack-id"].asText()) + break + } + } + } + } + retValue = result + } + ResourceAssignmentUtils.setResourceDataValue(executionRequest, raRuntimeService, retValue) + } catch (e: Exception) { + log.error(e.message, e) + ResourceAssignmentUtils.setResourceDataValue(executionRequest, raRuntimeService, "ERROR") + + throw BluePrintProcessorException("Failed in template key ($executionRequest) assignments, cause: ${e.message}", e) + } + } + + private fun getParamValueByName(params: JsonNode, paramName: String): String? { + for (param in params) { + if (param["name"].asText() == paramName && param["value"].asText() != "null") { + return param["value"].asText() + } + } + return null + } + + override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ResourceAssignment) { + this.addError("${runtimeException.message}") + } +} diff --git a/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/K8sHealthCheck.kt b/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/K8sHealthCheck.kt new file mode 100644 index 00000000..dd87c6f5 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/K8sHealthCheck.kt @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ +package org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts + +import com.fasterxml.jackson.databind.node.ObjectNode +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel +import kotlinx.coroutines.delay +import kotlinx.coroutines.joinAll +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertiesService +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.K8sConnectionPluginConfiguration +import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.K8sPluginInstanceApi +import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.healthcheck.K8sRbInstanceHealthCheck +import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.healthcheck.K8sRbInstanceHealthCheckSimple +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction +import org.slf4j.LoggerFactory + +open class K8sHealthCheck : AbstractScriptComponentFunction() { + + private val log = LoggerFactory.getLogger(K8sHealthCheck::class.java)!! + + override fun getName(): String { + return "K8sHealthCheck" + } + + private fun initPluginApi(): K8sPluginInstanceApi { + val bluePrintPropertiesService: BluePrintPropertiesService = this.functionDependencyInstanceAsType("bluePrintPropertiesService")!! + val k8sConfiguration = K8sConnectionPluginConfiguration(bluePrintPropertiesService) + + return K8sPluginInstanceApi(k8sConfiguration) + } + + override suspend fun processNB(executionRequest: ExecutionServiceInput) { + val instanceApi = initPluginApi() + + log.info("Health check script execution - START") + val configValueSetup: ObjectNode = getDynamicProperties("config-deploy-setup") as ObjectNode + log.info("Config Value Setup: $configValueSetup") + + val instanceHealthCheckList = startInstanceHealthCheck(configValueSetup, instanceApi) + val statuses = getStatuses(instanceHealthCheckList, instanceApi) + log.info("Health check script execution - END") + } + + private fun startInstanceHealthCheck(configValueSetup: ObjectNode, instanceApi: K8sPluginInstanceApi): List { + val healthCheckInstanceList = arrayListOf() + + configValueSetup.fields().forEach { + val instanceName = it.value.get("k8s-instance-id").asText() + val response: K8sRbInstanceHealthCheckSimple? = instanceApi.startInstanceHealthCheck(instanceName) + log.debug("K8sRbInstanceHealthCheckSimple response: $$response") + healthCheckInstanceList.add(HealthCheckInstance(instanceName, response?.id)) + } + log.info("healthCheckInstanceList: $healthCheckInstanceList") + + return healthCheckInstanceList + } + + private fun getStatuses(instanceHealthCheckList: List, instanceApi: K8sPluginInstanceApi): Map { + val statuses = hashMapOf() + runBlocking { + val jobs: List = instanceHealthCheckList.map { + launch { + log.info("Thread started: ${Thread.currentThread().name} for $it") + // WAIT APPROX 5 MINUTES + repeat(30) { _ -> + val response: K8sRbInstanceHealthCheck = instanceApi.getInstanceHealthCheck(it.heatStackId, it.healthCheckInstance!!)!! + log.debug("Response for $it: $response") + val status = response.status!! + if (!"RUNNING".equals(status, true)) { + statuses[it.heatStackId] = status + log.info("Poll status: $status for $it") + instanceApi.deleteInstanceHealthCheck(it.heatStackId, it.healthCheckInstance) + cancel() + } + delay(10_000L) + } + statuses[it.heatStackId] = "Timeout" + log.warn("Send delete hc request") + instanceApi.deleteInstanceHealthCheck(it.heatStackId, it.healthCheckInstance!!) + } + } + jobs.joinAll() + } + var success = true + statuses?.forEach { it -> + if (it.value != "Succeeded") { + success = false + } + } + log.info("---") + if (success) { + log.info("Healthcheck finished successfully") + } else { + log.info("Healthcheck finished with failure") + } + log.info("Detailed results: $statuses") + log.info("---") + return statuses + } + + data class HealthCheckInstance(val heatStackId: String, val healthCheckInstance: String?) { + override fun toString(): String { + return "HealthCheckInstance(heatStackId='$heatStackId', healthCheckInstance='$healthCheckInstance')" + } + } + + override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { + log.info("Executing Recovery") + bluePrintRuntimeService.getBluePrintError().addError("${runtimeException.message}", getName()) + } +} diff --git a/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/README.md b/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/README.md new file mode 100644 index 00000000..29b7978e --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/README.md @@ -0,0 +1 @@ +kotlin Folder \ No newline at end of file diff --git a/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/SimpleErrorCheck.kt b/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/SimpleErrorCheck.kt new file mode 100644 index 00000000..8e4a58ab --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/SimpleErrorCheck.kt @@ -0,0 +1,41 @@ +/* + * Copyright © 2021 Orange + * + * 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. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts + +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction +import org.slf4j.LoggerFactory + +open class SimpleErrorCheck : AbstractScriptComponentFunction() { + + private val log = LoggerFactory.getLogger(SimpleErrorCheck::class.java)!! + + override fun getName(): String { + return "SimpleErrorCheck" + } + + override suspend fun processNB(executionRequest: ExecutionServiceInput) { + log.info("SIMPLE ERROR CHECK - START") + + log.info("SIMPLE ERROR CHECK - END") + } + + override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { + log.info("Executing Recovery") + this.addError("${runtimeException.message}") + } +} diff --git a/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/SimpleStatusCheck.kt b/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/SimpleStatusCheck.kt new file mode 100644 index 00000000..c99dcd4f --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Scripts/kotlin/SimpleStatusCheck.kt @@ -0,0 +1,81 @@ +/* + * Copyright © 2021 Orange + * + * 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. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts + +import com.fasterxml.jackson.databind.node.ObjectNode +import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertiesService +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.K8sConnectionPluginConfiguration +import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.K8sPluginInstanceApi +import org.onap.ccsdk.cds.blueprintsprocessor.functions.k8s.instance.K8sRbInstanceStatus +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException +import org.slf4j.LoggerFactory + +open class SimpleStatusCheck : AbstractScriptComponentFunction() { + + private val log = LoggerFactory.getLogger(SimpleStatusCheck::class.java)!! + + override fun getName(): String { + return "SimpleStatusCheck" + } + + override suspend fun processNB(executionRequest: ExecutionServiceInput) { + log.info("SIMPLE STATUS CHECK - START") + + val configValueSetup: ObjectNode = getDynamicProperties("config-deploy-setup") as ObjectNode + + val bluePrintPropertiesService: BluePrintPropertiesService = + this.functionDependencyInstanceAsType("bluePrintPropertiesService") + + val k8sConfiguration = K8sConnectionPluginConfiguration(bluePrintPropertiesService) + + val instanceApi = K8sPluginInstanceApi(k8sConfiguration) + + var checkCount: Int = 30 // in the future to be read in from the input + while (checkCount > 0) { + var continueCheck = false + configValueSetup.fields().forEach { it -> + val vfModuleName = it.key + val instanceName = it.value.get("k8s-instance-id").asText() + + val instanceStatus: K8sRbInstanceStatus? = instanceApi.getInstanceStatus(instanceName) + log.debug("Get status for $vfModuleName ($instanceName)") + if (!instanceStatus?.ready!!) { + continueCheck = true + log.info("VfModule $vfModuleName ($instanceName) is not ready. Please wait...") + } else { + log.info("VfModule $vfModuleName ($instanceName) is ready.") + } + } + if (continueCheck) { + checkCount-- + if (checkCount == 0) + throw BluePrintException("Instance State verification failed") + Thread.sleep(10000L) + } else + checkCount = 0 + } + + log.info("SIMPLE STATUS CHECK - END") + } + + override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { + log.info("Executing Recovery") + this.addError("${runtimeException.message}") + } +} diff --git a/tutorials/ApacheCNF/templates/cba/TOSCA-Metadata/TOSCA.meta b/tutorials/ApacheCNF/templates/cba/TOSCA-Metadata/TOSCA.meta new file mode 100644 index 00000000..a8282073 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/TOSCA-Metadata/TOSCA.meta @@ -0,0 +1,8 @@ +TOSCA-Meta-File-Version: 1.0.0 +CSAR-Version: 1.0 +Created-By: Lukasz Rajewski +Entry-Definitions: Definitions/CNF.json +Template-Name: APACHE +Template-Version: 1.0.0 +Template-Type: DEFAULT +Template-Tags: Lukasz Rajewski, CNF diff --git a/tutorials/ApacheCNF/templates/cba/Templates/cnf-mapping.json b/tutorials/ApacheCNF/templates/cba/Templates/cnf-mapping.json new file mode 100644 index 00000000..63f5431b --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/cnf-mapping.json @@ -0,0 +1,314 @@ +[ + { + "name": "vf-module-model-invariant-uuid", + "property": { + "type": "string" + }, + "input-param": false, + "dictionary-name": "vf-module-model-invariant-uuid", + "dictionary-source": "processor-db", + "dependencies": [ + "vf-module-model-customization-uuid" + ] + }, + { + "name": "vf-module-model-version", + "property": { + "type": "string" + }, + "input-param": false, + "dictionary-name": "vf-module-model-version", + "dictionary-source": "processor-db", + "dependencies": [ + "vf-module-model-customization-uuid" + ] + }, + { + "name": "vf-module-name", + "property": { + "description": "", + "required": false, + "type": "string", + "status": "", + "constraints": [ + {} + ], + "entry_schema": { + "type": "" + } + }, + "input-param": false, + "dictionary-name": "vf-module-name", + "dictionary-source": "rest", + "dependencies": [ + "vnf_name", + "vf-module-label", + "vf-naming-policy", + "vf-module-id" + ], + "version": 0 + }, + { + "name": "vnf_name", + "property": { + "description": "", + "required": false, + "type": "string" + }, + "input-param": false, + "dictionary-name": "vnf_name", + "dictionary-source": "sdnc", + "dependencies": [ + "service-instance-id", + "vnf-id" + ], + "version": 0 + }, + { + "name": "service-instance-id", + "property": { + "description": "", + "required": false, + "type": "string" + }, + "input-param": false, + "dictionary-name": "service-instance-id", + "dictionary-source": "input", + "dependencies": [], + "version": 0 + }, + { + "name": "vf-module-label", + "property": { + "description": "", + "required": false, + "type": "string" + }, + "input-param": false, + "dictionary-name": "vf-module-label", + "dictionary-source": "processor-db", + "dependencies": [ + "vf-module-model-customization-uuid" + ], + "version": 0 + }, + { + "name": "vf-naming-policy", + "property": { + "description": "", + "required": false, + "type": "string" + }, + "input-param": false, + "dictionary-name": "vf-naming-policy", + "dictionary-source": "sdnc", + "dependencies": [ + "service-instance-id", + "vnf-id" + ], + "version": 0 + }, + { + "name": "vf-module-model-customization-uuid", + "property": { + "description": "", + "required": false, + "type": "string" + }, + "input-param": false, + "dictionary-name": "vf-module-model-customization-uuid", + "dictionary-source": "input", + "dependencies": [], + "version": 0 + }, + { + "name": "vnf-id", + "property": { + "description": "", + "required": false, + "type": "string" + }, + "input-param": false, + "dictionary-name": "vnf-id", + "dictionary-source": "input", + "dependencies": [], + "version": 0 + }, + { + "name": "vf-module-id", + "property": { + "description": "", + "required": false, + "type": "string" + }, + "input-param": false, + "dictionary-name": "vf-module-id", + "dictionary-source": "input", + "dependencies": [], + "version": 0 + }, + { + "name": "k8s-rb-profile-namespace", + "property": { + "description": "K8s namespace to create helm chart for specified RB profile", + "type": "string", + "required": false, + "default": "default" + }, + "input-param": false, + "dictionary-name": "k8s-rb-profile-namespace", + "dictionary-source": "sdnc", + "dependencies": [ + "service-instance-id", + "vnf-id" + ] + }, + { + "name": "k8s-rb-profile-k8s-version", + "property": { + "description": "K8s cluster version to create helm chart for specified RB profile", + "type": "string", + "required": false, + "default": "1.18.9" + }, + "input-param": false, + "dictionary-name": "k8s-rb-profile-k8s-version", + "dictionary-source": "sdnc", + "dependencies": [ + "service-instance-id", + "vnf-id" + ] + }, + { + "name": "k8s-rb-profile-name", + "property": { + "description": "RB Profile name used in k8s plugin to identify Helm chart(s) where this mapping is providing override values.", + "type": "string", + "required": false, + "default": "default" + }, + "input-param": false, + "dictionary-name": "k8s-rb-profile-name", + "dictionary-source": "default", + "dependencies": [] + }, + { + "name": "k8s-rb-instance-release-name", + "property": { + "description": "Name of the release for the helm package instance in k8s", + "type": "string", + "required": false, + "default": "base" + }, + "input-param": false, + "dictionary-name": "k8s-rb-instance-release-name", + "dictionary-source": "default", + "dependencies": [] + }, + { + "name": "k8s-rb-definition-name", + "property": { + "description": "RB Name identifier of Helm chart(s) in k8s plugin", + "type": "string", + "required": false, + "metadata": { + "transform-template": "${vf-module-model-invariant-uuid}" + } + }, + "input-param": false, + "dictionary-name": "k8s-rb-definition-name", + "dictionary-source": "default", + "dependencies": [ + "vf-module-model-invariant-uuid" + ] + }, + { + "name": "k8s-rb-definition-version", + "property": { + "description": "RB Version identifier of Helm chart(s) in k8s plugin", + "type": "string", + "required": false, + "metadata": { + "transform-template": "${vf-module-model-customization-uuid}" + } + }, + "input-param": false, + "dictionary-name": "k8s-rb-definition-version", + "dictionary-source": "default", + "dependencies": [ + "vf-module-model-customization-uuid" + ] + }, + { + "name": "k8s-rb-profile-source", + "property": { + "description": "The source folder or file relative to 'Templates/k8s-profiles' folder", + "type": "string", + "required": false + }, + "input-param": false, + "dictionary-name": "k8s-rb-profile-source", + "dictionary-source": "default", + "dependencies": [] + }, + { + "name": "k8s-rb-config-template-name", + "property": { + "description": "The source of configuration template for ue-reconfiuration operation", + "type": "string", + "required": false + }, + "input-param": false, + "dictionary-name": "k8s-rb-config-template-name", + "dictionary-source": "default", + "dependencies": [] + }, + { + "name": "k8s-rb-config-template-source", + "property": { + "description": "The source of configuration template for ue-reconfiuration operation", + "type": "string", + "required": false + }, + "input-param": false, + "dictionary-name": "k8s-rb-config-template-source", + "dictionary-source": "default", + "dependencies": [] + }, + { + "name": "k8s-rb-config-name", + "property": { + "description": "The source of configuration values for ue-reconfiguration operation", + "type": "string", + "required": false + }, + "input-param": false, + "dictionary-name": "k8s-rb-config-name", + "dictionary-source": "default", + "dependencies": [] + }, + { + "name": "k8s-rb-config-value-source", + "property": { + "description": "The source of configuration values for ue-reconfiguration operation", + "type": "string", + "required": false + }, + "input-param": false, + "dictionary-name": "k8s-rb-config-value-source", + "dictionary-source": "default", + "dependencies": [] + }, + { + "name": "core-instance-name", + "property": { + "description": "Name of 5g core instance that requires PNF registration", + "type": "string", + "required": false + }, + "input-param": false, + "dictionary-name": "core-instance-name", + "dictionary-source": "default", + "dependencies": [] + } +] diff --git a/tutorials/ApacheCNF/templates/cba/Templates/cnf-template.vtl b/tutorials/ApacheCNF/templates/cba/Templates/cnf-template.vtl new file mode 100644 index 00000000..1bebcaa0 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/cnf-template.vtl @@ -0,0 +1,67 @@ +{ + "capability-data": [ + { + "capability-name": "aai-vf-module-put", + "key-mapping": [ + { + "output-key-mapping": [ + { + "resource-name": "aai-vf-module-put", + "resource-value": "" + } + ] + } + ] + } + ], + "resource-accumulator-resolved-data": [ + { + "param-name": "vnf_name", + "param-value": "${vnf_name}" + }, + { + "param-name": "vf-module-name", + "param-value": "${vf-module-name}" + }, +##RB name + { + "param-name": "vf-module-model-invariant-uuid", + "param-value": "${vf-module-model-invariant-uuid}" + }, +##RB version + { + "param-name": "vf-module-model-version", + "param-value": "${vf-module-model-version}" + }, +##Release name + { + "param-name": "k8s-rb-instance-release-name", + "param-value": "${k8s-rb-instance-release-name}" + }, +##Profile name + { + "param-name": "k8s-rb-profile-name", + "param-value": "${k8s-rb-profile-name}" + }, + { + "param-name": "k8s-rb-config-template-name", + "param-value": "${k8s-rb-config-template-name}" + }, + { + "param-name": "k8s-rb-config-template-source", + "param-value": "${k8s-rb-config-template-source}" + }, + { + "param-name": "k8s-rb-config-name", + "param-value": "${k8s-rb-config-name}" + }, + { + "param-name": "k8s-rb-config-value-source", + "param-value": "${k8s-rb-config-value-source}" + }, + { + "param-name": "core-instance-name", + "param-value": "${core-instance-name}" + } + ] +} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/config-setup-mapping.json b/tutorials/ApacheCNF/templates/cba/Templates/config-setup-mapping.json new file mode 100644 index 00000000..95d2681f --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/config-setup-mapping.json @@ -0,0 +1,105 @@ +[ + { + "name": "vnf-id", + "property": { + "description": "", + "required": false, + "type": "string" + }, + "input-param": false, + "dictionary-name": "vnf-id", + "dictionary-source": "capability", + "dependencies": [], + "version": 0 + }, + { + "name": "vnf-relationship-list", + "property": { + "description": "Details about VNF relationships from AAI", + "type": "json" + }, + "input-param": false, + "dictionary-name": "vnf-relationship-list", + "dictionary-source": "aai-data", + "dependencies": [ + "vnf-id" + ] + }, + { + "name": "service-instance-id", + "property": { + "description": "", + "required": false, + "type": "string", + "status": "", + "constraints": [ + {} + ], + "entry_schema": { + "type": "" + } + }, + "input-param": false, + "dictionary-name": "service-instance-id", + "dictionary-source": "capability", + "dependencies": [ + "vnf-relationship-list" + ], + "version": 0 + }, + { + "name": "vf-modules-list-sdnc", + "property": { + "description": "list of modules associated with vnf from MDSAL", + "type": "json" + }, + "input-param": false, + "dictionary-name": "vf-modules-list", + "dictionary-source": "sdnc", + "dependencies": [ + "service-instance-id", + "vnf-id" + ] + }, + { + "name": "vf-modules-list-aai", + "property": { + "description": "list of modules associated with vnf from AAI", + "type": "json" + }, + "input-param": false, + "dictionary-name": "vf-modules-list", + "dictionary-source": "aai-data", + "dependencies": [ + "service-instance-id", + "vnf-id" + ] + }, + { + "name": "config-deploy-setup", + "property": { + "description": "configuration for config value setup", + "type": "json" + }, + "input-param": false, + "dictionary-name": "config-deploy-setup", + "dictionary-source": "capability", + "dependencies": [ + "vf-modules-list-aai", + "vf-modules-list-sdnc" + ] + }, + { + "name": "service-instance-name", + "property": { + "description": "Service instance name retrieved based on service instance id", + "type": "string" + }, + "input-param": false, + "dictionary-name": "service-instance-name", + "dictionary-source": "sdnc", + "dependencies": [ + "service-instance-id" + ] + } +] diff --git a/tutorials/ApacheCNF/templates/cba/Templates/config-setup-template.vtl b/tutorials/ApacheCNF/templates/cba/Templates/config-setup-template.vtl new file mode 100644 index 00000000..88771d61 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/config-setup-template.vtl @@ -0,0 +1 @@ +${config-deploy-setup} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config.tar.gz b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..44fc1ddf43a4e21133c4a9366d8909758b3fc53e GIT binary patch literal 13406 zcmV-kG@;8MiwFQ5{*z$@0PG!UcjGj0Kj&A7>;f%p+$6ntfqjqC<>&);OUv=N9(5BX zG3(gDc6z|VZ)aw7`bcc2X($l!=sLDE8qJJGGdf1@)a{S?&ZGNG?e<>#@bD1+rIh+t zJ$LpxdwY8a-S&PL-XC^%4 z-O>C%*xiNvoz6k`5nBsS{`dU%zU5Kug+Y&9bsFw;s(*H!J!kKrG2n4O@}>#BJ7S-4 zf5Q4GE-VSzBpi6dTXsZJ#0Grohqn_RBn=*nyny%EC`_h)BXB41EM%>5r7Add4xIlh z-5*Ml{ht^b-_tNqS^pm%?svLf)EE1^?T!9lM@sX*A5JD=uxc@=&;M?_yW#&@QX&7H zF(`R&6oe6fw1QMN{_l4W1pm7S2c5(HM{W3V(B6#y>qw8;shcD`3Su121<%>_mXni6bl8u6ib!w2lzgM4pnJM3lP-?A`(k^&_*DIBGxCxh`YX_HIG4XiJM>q*7>{=FkNO#31v>`NCA4ogWkb*BapN5) zzMjJ0OZOH0O(yXC7i9g`jl6IcvyZ#Rl~W8`{97^G#>qH zQc?e3wKuT1|HIe4PNx6w9`5aJ`u{qT8w6oOJu>b!80)(UABE9vkDUa=$c>X|)=y^8 zXBPMgZRb6wn{^Yu@Gc`ax)tsM$rBrf5gSF}Y>G;yFZ!Mzj=Vm*@GXjk=yL6zA9SKqicoK2G zGl6#TNPiNjG`xNoXb|cn!5DCOg?e_qRdikM+2@phhQXk2}^h;G4 zhqI{95lT5BWFE+JeSPiNjcr_|`1&tWWt+4_D%AgHA0Ivc@?&Q*c(jtVSpS2rZ|`RH z|8A$V(f{j6kCiTw){s)%LT5J`N9;#b;px{uZz%` z3b{S4!2kGzc|qTw4LEBGg?k|-R^#MsiX22C(auRIu5#ZFU!viN`ee0Isfj))DkSMm+9Lx_x-QbY$r zf~TM1&@wJ!ASVNQ;=mp|WH#6{m18%C$~m?kats*KA)F$J9~GL2O%!m*z)m$S+1V^e zya`XEIEC+y7XpS`AANp$2A<1v!jj=Hq~3@FwzDLhxLDcOU!1c(j}mX_p?MWQMY$gV zF-42Q07VmiQhRS<5NALGAMzpwq8|WCJmSC2JP>1WQW`BA-Hy}gz6-CYy|(LxfTkZ`CFWa%2KPROA0y%;E&jE!)(S746NH!q+MvU5wRalu&x zmuJcc_#LK#hde^w#JsPOhkB2OLl0W%A?mLYGj!}c=uSuzc+98Q?76Wg*)r)h`}k%G zXaH&_!E~0e`ssD!b*oCMmg{~Yv;bLlAytX1>FosIk2-NUOfEEC&Nx`~0cZq#%`k)H z&n@&ed?=wg)HCq<32TDc+hom8UcQ9Cq@Lm?+X5MaPahqfHSzBc&FzZ<5Q~t74m&77 z7GFOoWT)Xk5_S${A%nto2cJRO7vpY_h1#ZJ0R2Owj1B?6f!|Lo6zd^t2%D$uKZPu* zhhs28FFn7Of>@ufsHz24+MQol?dpAtc8(b=9b=JPSnL)$+?~P*HjO;A0!+TlaO>nd zl5-(FdC6b%aV|!20+oPG6Y~^GH88RvtO6q#?IIq>8Eop%NI`%i^=L%G{&5tAQ9Uug zyMV7LtzgW(!!TUlaUN2-A4F}j=Ok&)Y&wcu7+0rm9Mde710Fzfdx7jaNx&9|DSRHp zGce`I#EgJ@IxksxBbdz(#G=48r#Av7nXtmbcG$^~UBI~N4ajU2QhuQ(?WjiP$=Z@} z6kap%2M9y7g2nq7Y;yRhz(ZAJMLK4v$yA_+@F$rM?RNfEXPc!)Ce0Bhp%m+PZMJq5pqvmZ}Xv7fgdQ=SN($(tpd^qjgFKnj{P1ys*@KjKMz zF|SF_!~QGyhw6gQBj^R-m5Ea91x_W*Z<6XZ^IO$$Awrj8QFj1zI3Jc5+R)7L6&JvqeC}?v~FoJ=l{t<<{gk@iv zp)^&O3z`6=zZbbSfEW-{@GDGP;j^6D3L~6TV;9sFW%-v^FtP$wFRC#Gz8B6xTF&Be z#K{syU(lWT38~Xt_S?+$k#PgGmkBxNuA(VWptfDuSwvw$fGJG$(L`?@xp-YgG=*IM z6T*4l*1!_!0rZatkZj?MNj!8XHJtpE!&)u$kX$DfC7e=Hs{xwdfPw|Xngnr<;gQM% zWn`a3wR%2-Nt+v(f|=aP$CS-043v-U@@SELMn(H3^J6qd}UO? z2|oIZbZFk8spS(^xDyG6!~d|B_z!peN)zQPoF&I~6p%SsJLJWJY%&yi6Q|}Yh_98m zNOqNgem(WEqJPB7T9=4cO8;Rwu9R$Hhl3bbLi!?H%Z@Iz-$6fdjhMcJOu32LffVZn z;|ijV#fybpyh@ElPi1W$tvJdb@i?6M111nev(nW6R9kJsi1%k8%>Jz^+)r6`7f&wG zEWU8`9M3n2_aHpc8tLC9xwf3mkk}3o*B^WxejHrE-dQo>{}JvehPlQoFA4)%!@q)U zwXnKOCX?nw?oaA3*Z0}Qzz;uFP%-zYGU}#(tm5@2 zyT@Odj^xPU8#iM4TrT4nZmK@VwH}zjekfdj!Hrj#yPh{zHKm9D&r|wCSOhs8=tv!y zSL9jcC-Tz_K4qrmr;xOQ>pRdzVPjcLZuhNOt9okfVG>JABk7sqc8Bm*~lE0}P+pL5!6Y#>lsb)7BvAgU1=HZQNkEgqs5!rj5!rh&cFKNj=ae; z#vu3~+8vQYq=?Vl z%W#&+4c3@P?8qIJ@)WAji_I6yEIvyyVCTRU4+PXBuEcO61kOka0nq@>Zudy80^-K> zhY0PHVs~JvV4|+O6ndx6!~w`_mA%ZI|Lo z#2x~o0{p2i2>ZyzOg?#2W*U^>?gw)VR8x@ z0($S;0w1}WWe{?s$i0PM9!#px>&2M96p9O1`eKE2Ab`O7hD2Z0Lq|4%C^L(ymtp90 zH^@Y-&g7(Gf6I`SP6l{zUQlsJa`>>7jOPEQDda&aUK&OYQjpXEq=n)v zMMpCIaf%&8S9qrhnH;i<4*7M6Uk4u}bu%7B1!V%D%=YXp7tftV12>WjiAwf0~GR(i4#dR_<(#M4MI0=RYq z?3Cp2!oLVT5|iPe*<$a~hm|T(D`1Q7J@}jO}<#qX$#pwAgV# zP%zg#cSf}_qH#x zO;olM3h=@j;d|{0#T>Dozrk9GevQY{u`*gH<(-M8CLUz}dhzn>kI$XtMyM%h zdkiCKy!tv->g&{~uOsVg*et9% z9|eqE<#Z78S?~rdglig@`#5lhv2v*8Xh)Sp4!OyjbD_yxpToILn{D#2tx?tT4;r2SoN&ge43#qyds%@JCpV8{8Zah2DHK1Lw7J>Zx>haM0NFF00cCMG%Qja zh8;L(O7n=~-7KP`kK&weL-jixutGpzgF%>Ec#5>2_*9r!j_o5&2j^(H-ehN_fwe;R zYa9lM-m~T(4(dF|lEXinsNkS22YUc%z%dNXcB6<8ouvrTu?f*x4Iw)BK!{EuA@n)v z7oj-l3L+KIrvDc^NB{2#7lrX3)S$ScfPnSmzwNa<2b=hB>qsU1|HaxNl}wim2UQaP zY5!n18~^FB-96mI|5!)*7jMvuL-gZ2hyYgF43m$gmu z`|RK^LICrl&e3dP`Mk3u%q>x4X$@Ee1I=+5lLpUc5t^;gtijBOrxOSVr(b`31DlGl z0V1x5D1=ij%4(;>5-@*_XFo-_tgKOu*0XJLKK4Dvz>;D zvQZDJC}E%)dgp1sOyq_Ven3I3=gI>mRHnTFYdlX482n9bGdH2_`okR*p`itKE71Yu z)Q#$IrdL=e%6dfdElr`hN6!FHNr!E)-2<3hLWDc*eAn@YyJ zL0iwz1U0Q@WCB2|AD94W)p6<3dQzGHCu67F$pb8l|9jBc&-#D6yZameZyl+c|3@mJ zT67#Mf>6G{Rt{QZMh*{`pC@qG_ZXBU?(S-S0BiGmtu}O_V;c@0o0p}XPrXDwDmbK# zX;A|fbjc6cx$0nOypE_!_3dnaXes2BnJU?kHR2gnBakVv7779G{}gRxWTlF9k-67F zle$s^BP`5Ezrt+~uinF-|GyqX z_}|N<$A1Dgp)O%KCk<&g6(Oj_F zs<68A0@}q47neS8jEy>`pHB#6_ZN@LKIUrK_8+I^TfTusPE6ABNwvN!7-G+~d2v z=T~j~-`!8g|0j=d6aRlLsmA!9j}2zF*{6q}e1JX}Q`k~L^|o1V-e*n?W}H@AzH!V% z4e01P9rej%Ry)B9vzw2m0BjG> zOD~OSss!dYn{dtYs;N1J#>TQJPi5mjt&-gD_z$-|cXQ+a?!jjKUq`Aj{?Cs~npdjD zp-zQH&98@*oExw<{>%GjguE^&Lf>VXe0}n;hp02Pa#oyQ+&VL8UEZckob%|)>+|C6 z9AZsT9?gKWYjS4X!IN}OESD?o%Tpf>3WqlcM;==v75CIJ0%IOOM_} z1U1ETj&qz83REnS(&qzptY9}57m!`v8q~!Ywy*(aK*_sRE%2%AhNx$?lJpwS8vD2( zqxmjO-2T#BzEKsTFE_s90y^bSpblyz-hS41XR$nbV@7f+MUg7xT@SuD@e*+dT!Jw; zwj`;Zzc|Od=-=Y-wC%vDA2l0DKuo|uLwj}OgTDC9g-Qr{`dmhHbLh{w)Iv`5Mpt`&oJT*B4l+@6v^QGP{fnZt+)6k&a$}oe$LtB>Iq&20o@n5Vy z-OU0h8UJ?=58B!Be|LX#{$nkv#`vF(?kzODS;M{SG3J#7I2Q|$r`B>~22?8(++atq zJ-*a2*uBDLT!Aq8S(?TG(b__mUAlel_3d?A;+6WWB7>NK z#T1c_79g{h#vB>VkNjJu;Rs~yVi8^&DLDdVKtIcj-STz5T&)2de~8O(L)T@8W$Q zFN%Y>h@$1a7>Zb(7=B?N#<%I-neQBc)q?JkEwQcFKZ+qbCa^_zaRt6W$HAioH;YO= z!5<~7ET!EIK$P0@rS_kQFLa;wU#D}hm$U!&Hum3IQVsi0uK!vK!0Aw7MQU1!PaiVS zGVh)4#F)E)o3F}ri6?f5EYb&d95wr6(aL?RaOpl@jLDR*@mXP^(#3m)$dg)(H8yZ9g@CYBsY+TPl`)GtN|7e#&w)pYRYyq+0sF$~7_0T%$dI0}T!c^>2<@Gz#Ra$ZGJMX(t+!QQ-hae$gJD%3@Sy zzQ~p+L%YGg2fKbdQ~KfUO)2aDaL)Fw+dsX?#Pl6bL%scG{5H+siCH@tpFqsc6dq?$ zzf8km4p~n37-Z5CVt;rhi!I*EeFgk8F*IZmg2?Jx6=mbUImENP6|i{x@9yt+vg?0` z-R|c6$68X2@n41CmEEA~fzF!ocWWGdTtW2R8nwxTmK8(q-dn`o3>#8sD@7}d=hpM< z60$nTCJGj;OTZNq&ZviDyM04XlPVMBDqi?|k-Gs~T>deq-dNwyHQ1rR=z~Cr2dTfF(q2ifrdm#=E}uukY#W##ar>v> zCw)8DoAFNpkguW_?rdjQB?_%(0*|I~#Yp0B#?PKW=4{OHH)D&L=1CJR*ZO*TOJ3HO zzcDUWcf>8D#tN@h@6@7 zZqy&c25GuOtpX4`dlu3x8J|W#oSO=8a61eZ$iPsY29F`DD>D$9*#_W5)~BXjYZ07p zVorT817jv%mzJM{!?bGsXB=GlK1s*C=Hzqap{62f(D~D>7;WR?sg?$LkK=ZF3{aXw z)f1;Cl=AtqOvqR|#oU@}!I?Wjk%MLcF2T`EQ{}%EqiR}XSRv(L*)cjNPxHp=!jPI7 z91K@-t*%7v8kE*VF0Zm8q1CIxft6mEwfu~7XiF1!3Dk5G}AQoW^S$IsIQv44WrDS!n6TWZ)l@7 z%`++fp#gp|%IP^;M^%#Ic4oR)LCkHF?$Y!Z9uhp zlvVB?`jOfOjP_j(#wu(1U&>U4ekns`Im%qbFnnLi5bZIWThv$XG@HxIACBK_aJpC5 z*;KO%NvTZRS`M@UaaSMOKw9WV8{=H(mqu7csL)09+gKGXLNjGsR)a0e*{)_O_Esey z*P#xyqu8Z&{y|69G^>(BVX{~7CkzQz?9%42nB!yRr6NbP1q7+d5p%f}Z<&sqhFjr9o zR^Wt}50CYHwQ_jYSR?2}M5{KW%$3hfC3AaPi3_369&Tk>YH*q3Xm8ui$+{WU>Zl8N zMZzLAwrOEqfmzP0H-J{{*c-?X+_zUQV9wgB$$>(P@m?Lo)mr|QTXZkF!(>&{@>TQ) zw6CaR&J$ZowmXwE>Cy)k7Iv%^- z{exapge?E==3aoh$xKiRp<@!)TZ+&F2-RPh{JezuFC@uB5V@HZP8&{24O#TBo!!li=+*l z=7l>zuUkpDGsDBO6sNf*YiVIEEi0$icboJ4|D9B*|IHTXrFDJ{{on57&j0Rp+Z+AA zmh|{BONVP}z#EF&CKmxkwA|y9o#W@AjzSTp9Q95gyiS}v7e`E1IT780G-o^djB+>u(4!V0_3xY-1#rq%jAFUz%&-;Il|0ek2n)E+J|2jC# z>i^yDCjQr2lDRy$$K-v!jaOj%_SkbR2#pC`U5jUea4sN!nS>A_6BAS2%Hx~c_j8%W zH_U1-+TX)s7+f5yiS>Q{<~IKY@MMNO&;tajy?H9lGBY~I;Y{7UueyP()ifJY{RX`! zfLartVWcakyY#^c5G$r^3r1D_4JwYjzM34%zR#B3Hr2T1tw7q;J+ET3kX+O*bo;4X z`s7}74z$!9QV}K6A#k!NE>DBIHbX#NO>;6YghUr0mAw(HP;x1aVfyOG_rPtm*b4Bb zungSk9y)FKuhXP2rU3LsmE9C+;$`Bq*zv=@>tik|l@}6s2p%^?0W~9H#RvB3@mqU^OR8~f1IQD&r7yMa*(?NJ{2kyI9>eUoM#vQ9kA6wnXksm?;w+K$l z%yC&t26bA-K7bOW>a=B`lU9JIAq>Q~slgdbP4y?W(4Q)=j*@1T90VW^b|46 z`@N&CpBW`sF?sG9p9AErO&A z*j=idrp;C8&nEm!v~468vz#0g%nSu4Sl|?9WP3K2{StvddbHwO2&fwUXJp}e?D=$= z4u78wLi5qoI3NM_f{;LG*@Ai&% zw{aWxKTjd_HniR9r0u@*XXtj_7HroQcij!cFbs~ZwB9*(VA<_5?BPdJpSB#wPJ7#7 zNO0&SHbqhrMUj+5d6T^_YQ9#pl%y8z7C8yCgVfQxt#Ze+`}S7&YIbvV@nZJ-^UJS( z`nJ&+q~(cNiMuI^wONCu714tR4>6xtw?6q+9S;*k5z2%D&P4PW+t|hEPeQ(swDg*_ zoQlmtQ(B$a5QS?fHf5imetx>KsMu2WJJ&^5}__`r-H973Ace-+JeluFn!L`aQ%uy-D1&!x&^vPX~l~qkGG>zaP3ISWXbcY z+>S*9wxbbMgt6qCJJ3FNc^Y>hYJxUUQ9`z=;C)b8P>X7d^fsiX;9;C>5gUSeq}&jW zw$4HfS)mfjHo&|v zfb6j|eFt-Hc#{$h_!dWu|b=afJLM9{%)zADWfD=L1EB@}hPFmAw-MJ>dDy4LJ~*Nz~y z!0(>&yNUgAriNm@J($>PN-B^xTT+LG&EU}Zb}%Ys$-c&=c52wKhvdje^1sWp!@M{= zp&Uz55w7^}RgvIt>|)sR(Twv=(R!K)@Edp$$d{8Z!>Y^=f9q$TNyfLBSznx;ef9)K z)1*nva%ULXKFytd(mCaP@)Xnb({S3&=o!52l@*|!v(Y0eWM~bqlRq~|34iJd zr%!CP#^?WMXN$M~|N9+J!E}GrhTlQ!|L3Q$wX(7P57)o$?|=VSJ_Gju4!r+eO4h%A z^ZUDXN&1FX*fN~7T!{`%9cq8a#y*p;C2o+V@f#x`<0PMKod29XF`!zPV{s>U z+qMGJ8-#A9kz}|-J0d#uCTWKU-vPXgIGC^NC0>CWkVKrdHiq0qgR+f7AkHI2?TMkk16f)NN(wj0H|+! zlUGh(iv+!6Rn=G?Fo=`If)@xcB50$N(Yz{|LjDEzJQ6u&an40{SZZP{DNjI)vIl5J zE)`{hn}mrlsmx>%(0EVt+awx~E>e-7Ab1o48j`$_$^6j(Y7}!C{! z`e^J1^ROZGJdfVMuNjRb(=zJNK2m6^*^XUNd!gh>32DFAT>_{JSR@CLYq9PB#W$s9q4&eXgz{cdMA>7yJpxRK2JLsGq-4(%+&)^< z;hQRgW!&JWQIH)4T)cimAb`1yyp$FBIt`O0Vvq34l_BAmwQbm)*AxDP8{4pU=ag_X zESP9`oZI9IY#Gc!p7i=js58FuNASs>Euip0jduV@ZQQnQI{4$WJj{Yj(bX^>R*N1 zE_FbQ^cm);y8NNz4blS2h{V3JT}$Lt#8CAt`ZrfY;p*e26HTi7M8HXfjvv_Rk<+JQm= zgm+N;Zg#5Pd%PPh9pI*C3t$>PPGUq$(cfgTW+B#!Ihe{^ww}}6CF>+^a?T85UTraM zXI#GQU|IqYvv)jt1G-aP5Z0*9wptiMy`6{V9h3P&M-&1!%c8s}P&jGnPFe><8;u>& zS9aWWKP^5sYsk0-N~Q|gyi*0I9ox{$M4-VO5Lh6Y43-3_n_M+@!sA+11Vf`9Nf9_( zivFl+-_y}HX*FRsR0o`~a+Pi@^xkowHVLR0;_5oXeLSE+>@Ji3 zjbiqNbhe8H8`w0a+~C%+yI!84gtYmf1U09k0RI{wC(1d`AA84 z>Woi=_Wzupf7HDH9TI@-?|=VSK9KF{Tbk9?k{ua=>e^&pg60|lgtR+POwKxG)I213 z;!$r90rle*K2h2Xln8p9s0*_w;qY8e6ICItrAlD=dR~4ctge4$;eD8-WUbwHGCO58 z+k^}@dg3f^0N&9vg=Y%iSiKAw@avb3tw0dXH5n|2pTGfz+aBawDuvvCCHLspwiW0w z4!$q=Vrp{q-Bt5(Otqp6eMNJJKW5{bAn$|*1B8X)Sd~li5i{NyKCh#Imw;pn7VO94 zk3S7!K2O3dI6DoBPtV~UF!V}$fXyxJ^xEAlG;o35=_nz67bD0ty@$5@t9zvQjNa}G90RuPVf z0&3=#Ys!oPO~R?1+Yjv(D?{-{OpL?^t30-O5hqv^svNv1l6xQ&=$@JA+CF0|M|ki- zr|{_NlrT0-P=5`6<3nDhF-wy-?6CXme7VaNMzDH0e%(X#NuwACp=C;Q(7J~layvfc}hk-dI)+W;;T|j1dxj> zQf&M_p$x1O8Ev3m%W}|y&*-2&{nn&{FoPdinV2U?^&(C42Og`S*OZBT0Re@(u!xa; zFH6mo9URz75Hi0eFW=Fcc-d|wknB&O#ol^d@b3Voy@WQTp_<&1%LLE6(J=y}{8SAcTlEYaefY!_$we^RF8gw^KmOqHlf#y(hpJ>68Bm2!MUPi zYWC}I)NQ(TC{hXSY{PEDdQU69u)W{9B@Z+^G^{sPPFSnZosenB{Jtfl7Iiw%#+v}~ z?x>6<<)L6w7)MSbEO1F{4J~$T0mpJ8;iNSfY6K+cCMq&SZ%ksKU5RdJ_7YV(HE~HK z3>)^R?Rg#lk>?8aZUge>vyv@}eCaKLAS!>U0EJJj(J1o*Wz8u@(y10E@Vm}|GG(8h zj+~QjwpY{jRsoTe2QS2EkS_w(=Bff)Nn?~em|s$`e&*nVLJzq4*D2Os=GrhcJ7RQE zVhI6K9^P~55{E+eiHMTC5`;Rs%ah37?tz?**$n}wB1Z?gK(k2zAPBeoAJ;F6Dr5Du z?m~8Pnv`WqoU?~8b8F%jt1?+z9LLBc&Rxpj2SOQw zgz+Dhp!Z88kZ~v|!eT9TXu+4z`&2rrigb-*l-gzi1C$-wc0R<}hB}bCT-m14s+uy0 z4=vU2C0~+#e|G-)i)6%9_YWxINRly~4~033j6B=pzHEi(eTT_9ig=obv6!rK`6oz| z1&`KI3X_zf85q=~#xZEC>BzSm>9fQKlY>zskw^QvW=MnM<>5HTXZ{iAwyYMPj@t5O zoQcqI4|%)7|TO(fDllxpiV%oE6Do<=T%c2?GPTR307%KUq{}X45rdIV<|LVV(9TIAWPxv> zE+P42a$8uw08YU0pvLu)nfopT=hg{si%8fpH&J+k>^8~%oXjCq2S=F%bhD@22_k41 zj+Xj(shff7x?p8WZ7Hm5oH*R-3N#KD2_B(0J`W)jfdZ?Oby0(34uvI7|1^2bIpWsj z+z##{TPFuR24S@1z35mhRz)`O=}JXuC;*6>O!fZF9oM~xVw}ieh!Gi-cakWa-_<>& zBx{Xfr2L2%P>h08DQ!(NXjnK01V%o2mRGlTCv0xFm2gmyC2dqvCQw+&rF4*YMNpW) z3=tzZJ=6o%BH;AOCTg%XCLySajGmlzwfaSCtk)@z(}@7yD+5S1ItJ8I6Z0%nl^h{3 z+^bK}WSu_hK6Jlo0U{kK0Nn~|zK0nXXSMqTwGciiSpJZaBqoalkG$G3SqWvfSS{uP zqB)~!7)KN*P#1`aI|@qTGD;~WB*4#Cm*38=*w>dYZ)V@jzP`A*q^B&G%Fl&)`RamQ zznr}W820_;FZ9NaTI^a)ge($PDN{GZ29?1qd3d=hpaKQFZ?*^Bo>SAnR;sE@%UKA& zrT?c?sB>pLN(fm~$pV3BBL-1*)l12gQD-$`nJZk>Y?8R&%rF^>BqocV*urz7(hQWC zuZ;?2FE1~izqkawh8)p|af81I-bjvUC5B$gAc6eqGNF6`@Wwc>R|$5ha?G#^d!h1} zKt-4GYpc8Ft$6t8)RGNC_l^(CY6M&%kg;Oj>}D}!Q_Q$yLB!%DIEo>kjz6!5kk39x zJESv=ylWtN_fT>#_4KG&dsRX{X~lbQ!Jby4qUR+}F42z`k7<_H8?{Z^?~q zII_N9+V0G1cXnVwa%oAE&^+DTG`9C^qdF8}%zH#pFxY)4oi``TtSzPz6*T-jWpAPATNoRFH&ON z@GN>R4tANF`q|_eVx)Na%GN@2sT4R7QR@V%hWN{Px<2nNyV!#ie1*x5P6<3I`x}Uqxr-*&+VNss*9en&gJxNV=sB5-&6Ey{!VI61z?Zp1DcY%Ix7Ao&TBm9B&?epBFrN~CS8uO*TFPQU$U|Ji@`pSS$^2evdqYyeOJ0N88# A%>V!Z literal 0 HcmV?d00001 diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/Chart.yaml b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/Chart.yaml new file mode 100644 index 00000000..82fb790c --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +appVersion: 2.4.46 +description: A Helm chart to modify Apache deployment +engine: gotpl +name: apache +version: 7.6.0 diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/.helmignore b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/.helmignore new file mode 100644 index 00000000..50af0317 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/.helmignore @@ -0,0 +1,22 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/Chart.yaml b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/Chart.yaml new file mode 100644 index 00000000..85ef7d65 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/Chart.yaml @@ -0,0 +1,22 @@ +annotations: + category: Infrastructure +apiVersion: v1 +appVersion: 0.8.2 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://github.com/bitnami/charts/tree/master/bitnami/common +icon: https://bitnami.com/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- email: containers@bitnami.com + name: Bitnami +name: common +sources: +- https://github.com/bitnami/charts +- http://www.bitnami.com/ +version: 0.8.2 diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/README.md b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/README.md new file mode 100644 index 00000000..9bcdfd6e --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/README.md @@ -0,0 +1,286 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 0.x.x + repository: https://charts.bitnami.com/bitnami +``` + +```bash +$ helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This Helm chart has been tested on top of [Bitnami Kubernetes Production Runtime](https://kubeprod.io/) (BKPR). Deploy BKPR to get automated TLS certificates, logging and monitoring for your applications. + +## Prerequisites + +- Kubernetes 1.12+ +- Helm 2.12+ or Helm 3.0-beta3+ + +## Parameters + +The following table lists the helpers available in the library which are scoped in different sections. + +### Affinities + +| Helper identifier | Description | Expected Input | +|-------------------------------------|-----------------------------------------------------------------|------------------------------------------------------------------| +| `common.affinities.node.soft` | Return a soft nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.node.hard` | Return a hard nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.pod.soft` | Return a soft podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | +| `common.affinities.pod.hard` | Return a hard podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | + +### Capabilities + +| Helper identifier | Description | Expected Input | +|------------------------------------------------|-----------------------------------------------------------------|----------------------------| +| `common.capabilities.deployment.apiVersion` | Return the appropriate apiVersion for deployment. | `.` Chart context | +| `common.capabilities.statefulset.apiVersion` | Return the appropriate apiVersion for statefulset. | `.` Chart context | +| `common.capabilities.ingress.apiVersion` | Return the appropriate apiVersion for ingress. | `.` Chart context | + +### Errors + +| Helper identifier | Description | Expected Input | +|------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------| +| `common.errors.upgrade.passwords.empty` | It will ensure required passwords are given when we are upgrading a chart. If `validationErrors` is not empty it will throw an error and will stop the upgrade action. | `dict "validationErrors" (list $validationError00 $validationError01) "context" $` | + +### Images + +| Helper identifier | Description | Expected Input | +|--------------------------------|-----------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------| +| `common.images.image` | Return the proper and full image name | `dict "imageRoot" .Values.path.to.the.image "global" $`, see [ImageRoot](#imageroot) for the structure. | +| `common.images.pullSecrets` | Return the proper Docker Image Registry Secret Names | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global` | + +### Labels + +| Helper identifier | Description | Expected Input | +|--------------------------------|-----------------------------------------------------------------|-----------------------------| +| `common.labels.standard` | Return Kubernetes standard labels | `.` Chart context | +| `common.labels.matchLabels` | Return the proper Docker Image Registry Secret Names | `.` Chart context | + +### Names + +| Helper identifier | Description | Expected Inpput | +|--------------------------------|-----------------------------------------------------------------|-----------------------------| +| `common.names.name` | Expand the name of the chart or use `.Values.nameOverride` | `.` Chart context | +| `common.names.fullname` | Create a default fully qualified app name. | `.` Chart context | +| `common.names.chart` | Chart name plus version | `.` Chart context | + +### Secrets + +| Helper identifier | Description | Expected Input | +|--------------------------------|-----------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `common.secrets.name` | Generate the name of the secret. | `dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $` see [ExistingSecret](#existingsecret) for the structure. | +| `common.secrets.key` | Generate secret key. | `dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName"` see [ExistingSecret](#existingsecret) for the structure. | + +### Storage + +| Helper identifier | Description | Expected Input | +|--------------------------------|-----------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------| +| `common.affinities.node.soft` | Return a soft nodeAffinity definition | `dict "persistence" .Values.path.to.the.persistence "global" $`, see [Persistence](#persistence) for the structure. | + +### TplValues + +| Helper identifier | Description | Expected Input | +|--------------------------------|-----------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------| +| `common.tplvalues.render` | Renders a value that contains template | `dict "value" .Values.path.to.the.Value "context" $`, value is the value should rendered as template, context frecuently is the chart context `$` or `.` | + +### Utils + +| Helper identifier | Description | Expected Input | +|--------------------------------|-----------------------------------------------------------------|------------------------------------------------------------------------| +| `common.utils.fieldToEnvVar` | Build environment variable name given a field. | `dict "field" "my-password"` | +| `common.utils.secret.getvalue` | Print instructions to get a secret value. | `dict "secret" "secret-name" "field" "secret-value-field" "context" $` | +| `common.utils.getValueFromKey` | Gets a value from `.Values` object given its key path | `dict "key" "path.to.key" "context" $` | + +### Validations + +| Helper identifier | Description | Expected Input | +|--------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `common.validations.values.single.empty` | Validate a value must not be empty. | `dict "valueKey" "path.to.value" "secret" "secret.name" "field" "my-password" "context" $` secret and field are optional. In case they are given, the helper will generate a how to get instruction. See [ValidateValue](#validatevalue) | +| `common.validations.values.multiple.empty` | Validate a multiple values must not be empty. It returns a shared error for all the values. | `dict "required" (list $validateValueConf00 $validateValueConf01) "context" $`. See [ValidateValue](#validatevalue) | +| `common.validations.values.mariadb.passwords` | This helper will ensure required password for MariaDB are not empty. It returns a shared error for all the values. | `dict "secret" "mariadb-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use postgresql chart and the helper. | +| `common.validations.values.postgresql.passwords` | This helper will ensure required password for PostgreSQL are not empty. It returns a shared error for all the values. | `dict "secret" "postgresql-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use postgresql chart and the helper. | + +### Warnings + +| Helper identifier | Description | Expected Input | +|--------------------------------|-----------------------------------------------------------------|------------------------------------------------------------------| +| `common.warnings.rollingTag` | Warning about using rolling tag. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy. Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets. + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possiblity of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +$ helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 --decode) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 --decode) +``` + +## Notable changes + +N/A diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_affinities.tpl b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_affinities.tpl new file mode 100644 index 00000000..40f575cb --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_affinities.tpl @@ -0,0 +1,94 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" .context) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + namespaces: + - {{ .context.Release.Namespace }} + topologyKey: kubernetes.io/hostname + weight: 1 +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" .context) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + namespaces: + - {{ .context.Release.Namespace }} + topologyKey: kubernetes.io/hostname +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_capabilities.tpl b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_capabilities.tpl new file mode 100644 index 00000000..143bef2a --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_capabilities.tpl @@ -0,0 +1,33 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "apps/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- end -}} +{{- end -}} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_errors.tpl b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_errors.tpl new file mode 100644 index 00000000..d6d3ec65 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_errors.tpl @@ -0,0 +1,20 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Through error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: you must provide your current passwords when upgrade the release%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_images.tpl b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_images.tpl new file mode 100644 index 00000000..aafde9f3 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_images.tpl @@ -0,0 +1,43 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" $) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := .imageRoot.registry -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $tag := .imageRoot.tag | toString -}} +{{- if .global }} + {{- if .global.imageRegistry }} + {{- $registryName = .global.imageRegistry -}} + {{- end -}} +{{- end -}} +{{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- if .global }} + {{- range .global.imagePullSecrets -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) }} +imagePullSecrets: + {{- range $pullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_labels.tpl b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_labels.tpl new file mode 100644 index 00000000..252066c7 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_labels.tpl @@ -0,0 +1,18 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Kubernetes standard labels +*/}} +{{- define "common.labels.standard" -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Labels to use on deploy.spec.selector.matchLabels and svc.spec.selector +*/}} +{{- define "common.labels.matchLabels" -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_names.tpl b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_names.tpl new file mode 100644 index 00000000..adf2a74f --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_names.tpl @@ -0,0 +1,32 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.names.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_secrets.tpl b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_secrets.tpl new file mode 100644 index 00000000..ebfb5d42 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_secrets.tpl @@ -0,0 +1,57 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/master/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- $name = .name -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/master/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_storage.tpl b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_storage.tpl new file mode 100644 index 00000000..60e2a844 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_storage.tpl @@ -0,0 +1,23 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} + +{{- $storageClass := .persistence.storageClass -}} +{{- if .global -}} + {{- if .global.storageClass -}} + {{- $storageClass = .global.storageClass -}} + {{- end -}} +{{- end -}} + +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else }} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} + +{{- end -}} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_tplvalues.tpl b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_tplvalues.tpl new file mode 100644 index 00000000..2db16685 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,13 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $) }} +*/}} +{{- define "common.tplvalues.render" -}} + {{- if typeIs "string" .value }} + {{- tpl .value .context }} + {{- else }} + {{- tpl (.value | toYaml) .context }} + {{- end }} +{{- end -}} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_utils.tpl b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_utils.tpl new file mode 100644 index 00000000..74774a3c --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_utils.tpl @@ -0,0 +1,45 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ .context.Release.Namespace }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 --decode) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_validations.tpl b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_validations.tpl new file mode 100644 index 00000000..05d1edba --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_validations.tpl @@ -0,0 +1,278 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s=$%s' to the command.%s" .valueKey .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} + +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (not $existingSecret) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliar function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliar function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliar function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliar function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Validate PostgreSQL required passwords are not empty. + +Usage: +{{ include "common.validations.values.postgresql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where postgresql values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.postgresql.passwords" -}} + {{- $existingSecret := include "common.postgresql.values.existingSecret" . -}} + {{- $enabled := include "common.postgresql.values.enabled" . -}} + {{- $valueKeyPostgresqlPassword := include "common.postgresql.values.key.postgressPassword" . -}} + {{- $enabledReplication := include "common.postgresql.values.enabled.replication" . -}} + {{- $valueKeyPostgresqlReplicationEnabled := include "common.postgresql.values.key.replicationPassword" . -}} + + {{- if and (not $existingSecret) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredPostgresqlPassword := dict "valueKey" $valueKeyPostgresqlPassword "secret" .secret "field" "postgresql-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlPassword -}} + + {{- if (eq $enabledReplication "true") -}} + {{- $requiredPostgresqlReplicationPassword := dict "valueKey" $valueKeyPostgresqlReplicationEnabled "secret" .secret "field" "postgresql-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliar function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliar function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliar function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliar function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliar function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliar function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_warnings.tpl b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_warnings.tpl new file mode 100644 index 00000000..ae10fa41 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/templates/_warnings.tpl @@ -0,0 +1,14 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/ +{{- end }} + +{{- end -}} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/values.yaml b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/values.yaml new file mode 100644 index 00000000..9ecdc93f --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/charts/common/values.yaml @@ -0,0 +1,3 @@ +## bitnami/common +## It is required by CI/CD tools and processes. +exampleValue: common-chart diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/templates/_helpers.tpl b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/templates/_helpers.tpl new file mode 100644 index 00000000..e2e14018 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/templates/_helpers.tpl @@ -0,0 +1,263 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "apache.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "apache.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "apache.labels" -}} +app.kubernetes.io/name: {{ include "apache.name" . }} +helm.sh/chart: {{ include "apache.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Labels to use on deploy.spec.selector.matchLabels and svc.spec.selector +*/}} +{{- define "apache.matchLabels" -}} +app.kubernetes.io/name: {{ include "apache.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Return the proper Apache image name +*/}} +{{- define "apache.image" -}} +{{- $registryName := .Values.image.registry -}} +{{- $repositoryName := .Values.image.repository -}} +{{- $tag := .Values.image.tag | toString -}} +{{/* +Helm 2.11 supports the assignment of a value to a variable defined in a different scope, +but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. +Also, we can't use a single if because lazy evaluation is not an option +*/}} +{{- if .Values.global }} + {{- if .Values.global.imageRegistry }} + {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} + {{- else -}} + {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} + {{- end -}} +{{- else -}} + {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Apache Docker Image Registry Secret Names +*/}} +{{- define "apache.imagePullSecrets" -}} +{{/* +Helm 2.11 supports the assignment of a value to a variable defined in a different scope, +but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. +Also, we can't use a single if because lazy evaluation is not an option +*/}} +{{- if .Values.global }} +{{- if .Values.global.imagePullSecrets }} +imagePullSecrets: +{{- range .Values.global.imagePullSecrets }} + - name: {{ . }} +{{- end }} +{{- else if or .Values.image.pullSecrets .Values.metrics.image.pullSecrets }} +imagePullSecrets: +{{- range .Values.image.pullSecrets }} + - name: {{ . }} +{{- end }} +{{- range .Values.metrics.image.pullSecrets }} + - name: {{ . }} +{{- end }} +{{- end -}} +{{- else if or .Values.image.pullSecrets .Values.metrics.image.pullSecrets }} +imagePullSecrets: +{{- range .Values.image.pullSecrets }} + - name: {{ . }} +{{- end }} +{{- range .Values.metrics.image.pullSecrets }} + - name: {{ . }} +{{- end }} +{{- end -}} +{{- end -}} + +{{/* +Return the proper image name (for the metrics image) +*/}} +{{- define "apache.metrics.image" -}} +{{- $registryName := .Values.metrics.image.registry -}} +{{- $repositoryName := .Values.metrics.image.repository -}} +{{- $tag := .Values.metrics.image.tag | toString -}} +{{/* +Helm 2.11 supports the assignment of a value to a variable defined in a different scope, +but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. +Also, we can't use a single if because lazy evaluation is not an option +*/}} +{{- if .Values.global }} + {{- if .Values.global.imageRegistry }} + {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} + {{- else -}} + {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} + {{- end -}} +{{- else -}} + {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if mouting a static web page +*/}} +{{- define "apache.useHtdocs" -}} +{{ default "" (or .Values.cloneHtdocsFromGit.enabled .Values.htdocsConfigMap .Values.htdocsPVC) }} +{{- end -}} + +{{/* +Return associated volume +*/}} +{{- define "apache.htdocsVolume" -}} +{{- if .Values.cloneHtdocsFromGit.enabled }} +emptyDir: {} +{{- else if .Values.htdocsConfigMap }} +configMap: + name: {{ .Values.htdocsConfigMap }} +{{- else if .Values.htdocsPVC }} +persistentVolumeClaim: + claimName: {{ .Values.htdocsPVC }} +{{- end }} +{{- end -}} + +{{/* +Validate data +*/}} +{{- define "apache.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "apache.validateValues.htdocs" .) -}} +{{- $messages := append $messages (include "apache.validateValues.htdocsGit" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + {{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "apache.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Validate data (htdocs) +*/}} +{{- define "apache.validateValues.htdocs" -}} +{{- if or (and .Values.cloneHtdocsFromGit.enabled (or .Values.htdocsPVC .htdocsConfigMap )) (and .Values.htdocsPVC (or .Values.htdocsConfigMap .Values.cloneHtdocsFromGit.enabled )) (and .Values.htdocsConfigMap (or .Values.htdocsPVC .Values.cloneHtdocsFromGit.enabled )) }} +apache: htdocs + You have selected more than one way of deploying htdocs. Please select only one of htdocsConfigMap cloneHtdocsFromGit or htdocsVolume +{{- end }} +{{- end -}} + +{{/* +Validate data (htdocs git) +*/}} +{{- define "apache.validateValues.htdocsGit" -}} +{{- if .Values.cloneHtdocsFromGit.enabled }} + {{- if not .Values.cloneHtdocsFromGit.repository }} +apache: htdocs-git-repository + You did not specify a git repository to clone. Please set cloneHtdocsFromGit.repository + {{- end }} + {{- if not .Values.cloneHtdocsFromGit.branch }} +apache: htdocs-git-branch + You did not specify a branch to checkout in the git repository. Please set cloneHtdocsFromGit.branch + {{- end }} +{{- end -}} +{{- end -}} + +{{/* +Validate values of Apache - Incorrect extra volume settings +*/}} +{{- define "apache.validateValues.extraVolumes" -}} +{{- if and (.Values.extraVolumes) (not .Values.extraVolumeMounts) -}} +apache: missing-extra-volume-mounts + You specified extra volumes but not mount points for them. Please set + the extraVolumeMounts value +{{- end -}} +{{- end -}} + +{{/* +Return the proper git image name +*/}} +{{- define "git.image" -}} +{{- $registryName := .Values.git.registry -}} +{{- $repositoryName := .Values.git.repository -}} +{{- $tag := .Values.git.tag | toString -}} +{{/* +Helm 2.11 supports the assignment of a value to a variable defined in a different scope, +but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. +Also, we can't use a single if because lazy evaluation is not an option +*/}} +{{- if .Values.global }} + {{- if .Values.global.imageRegistry }} + {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} + {{- else -}} + {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} + {{- end -}} +{{- else -}} + {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} +{{- end -}} +{{- end -}} + +{{/* +Get the vhosts config map name. +*/}} +{{- define "apache.vhostsConfigMap" -}} +{{- if .Values.vhostsConfigMap -}} + {{- printf "%s" (tpl .Values.vhostsConfigMap $) -}} +{{- else -}} + {{- printf "%s-vhosts" (include "apache.fullname" . ) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the httpd.conf config map name. +*/}} +{{- define "apache.httpdConfConfigMap" -}} +{{- if .Values.httpdConfConfigMap -}} + {{- printf "%s" (tpl .Values.httpdConfConfigMap $) -}} +{{- else -}} + {{- printf "%s-httpd-conf" (include "apache.fullname" . ) -}} +{{- end -}} +{{- end -}} + +{{/* +Renders a value that contains template. +Usage: +{{ include "apache.tplValue" ( dict "value" .Values.path.to.the.Value "context" $) }} +*/}} +{{- define "apache.tplValue" -}} + {{- if typeIs "string" .value }} + {{- tpl .value .context }} + {{- else }} + {{- tpl (.value | toYaml) .context }} + {{- end }} +{{- end -}} + + diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/templates/deployment.yaml b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/templates/deployment.yaml new file mode 100644 index 00000000..45077121 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/templates/deployment.yaml @@ -0,0 +1,172 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "apache.fullname" . }} + labels: {{- include "apache.labels" . | nindent 4 }} +spec: + selector: + matchLabels: {{- include "apache.matchLabels" . | nindent 6 }} + replicas: {{ .Values.replicaCount }} + template: + metadata: + labels: {{- include "apache.labels" . | nindent 8 }} + {{- if or .Values.podAnnotations (and .Values.metrics.enabled .Values.metrics.podAnnotations) }} + annotations: + {{- if .Values.podAnnotations }} + {{- include "apache.tplValue" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} + {{- include "apache.tplValue" (dict "value" .Values.metrics.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: +{{- include "apache.imagePullSecrets" . | nindent 6 }} + hostAliases: + - ip: "127.0.0.1" + hostnames: + - "status.localhost" + {{- if .Values.affinity }} + affinity: {{- include "apache.tplValue" (dict "value" .Values.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{- include "apache.tplValue" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{- include "apache.tplValue" (dict "value" .Values.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.cloneHtdocsFromGit.enabled }} + initContainers: + - name: git-clone-repository + image: {{ include "git.image" . }} + imagePullPolicy: {{ .Values.git.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + git clone {{ .Values.cloneHtdocsFromGit.repository }} --branch {{ .Values.cloneHtdocsFromGit.branch }} /app + resources: {{- toYaml .Values.cloneHtdocsFromGit.resources | nindent 12 }} + volumeMounts: + - name: htdocs + mountPath: /app + containers: + - name: git-repo-syncer + image: {{ include "git.image" . }} + imagePullPolicy: {{ .Values.git.pullPolicy | quote }} + command: + - /bin/bash + - -ec + - | + while true; do + cd /app && git pull origin {{ .Values.cloneHtdocsFromGit.branch }} + sleep {{ .Values.cloneHtdocsFromGit.interval }} + done + resources: {{- toYaml .Values.cloneHtdocsFromGit.resources | nindent 12 }} + volumeMounts: + - name: htdocs + mountPath: /app + {{- else }} + containers: + {{- end }} + - name: apache + image: {{ include "apache.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" .Values.image.debug | quote }} + {{- if .Values.extraEnvVars }} + {{- include "apache.tplValue" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: 8080 + - name: https + containerPort: 8443 + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: {{ .Values.livenessProbe.path }} + port: http + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: {{ .Values.readinessProbe.path }} + port: http + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + {{- end }} + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- end }} + volumeMounts: + {{- if (include "apache.useHtdocs" .) }} + - name: htdocs + mountPath: /app + {{- end }} + {{- if or (.Files.Glob "files/vhosts/*.conf") (.Values.vhostsConfigMap) }} + - name: vhosts + mountPath: /vhosts + {{- end }} + {{- if or (.Files.Glob "files/httpd.conf") (.Values.httpdConfConfigMap) }} + - name: httpd-conf + mountPath: /opt/bitnami/apache/conf/httpd.conf + subPath: httpd.conf + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- include "common.tplvalues.render" ( dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "apache.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + command: ['/bin/apache_exporter', '--scrape_uri', 'http://status.localhost:8080/server-status/?auto'] + ports: + - name: metrics + containerPort: 9117 + livenessProbe: + httpGet: + path: /metrics + port: metrics + initialDelaySeconds: 15 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /metrics + port: metrics + initialDelaySeconds: 5 + timeoutSeconds: 1 + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} + {{- end }} + volumes: + {{- if (include "apache.useHtdocs" .) }} + - name: htdocs + {{- include "apache.htdocsVolume" . | nindent 10 }} + {{- end }} + {{- if or (.Files.Glob "files/vhosts/*.conf") (.Values.vhostsConfigMap) }} + - name: vhosts + configMap: + name: {{ include "apache.vhostsConfigMap" . }} + {{- end }} + {{- if or (.Files.Glob "files/httpd.conf") (.Values.httpdConfConfigMap) }} + - name: httpd-conf + configMap: + name: {{ include "apache.httpdConfConfigMap" . }} + {{- end }} + {{- if .Values.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.extraVolumes "context" $) | nindent 8 }} + {{- end }} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/values.yaml b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/values.yaml new file mode 100644 index 00000000..3437982b --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-config/values.yaml @@ -0,0 +1,310 @@ +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry and imagepullSecrets +## +# global: +# imageRegistry: myRegistryName +# imagePullSecrets: +# - myRegistryKeySecretName + +## Bitnami Apache image version +## ref: https://hub.docker.com/r/bitnami/apache/tags/ +## +image: + registry: docker.io + repository: bitnami/apache + tag: 2.4.46-debian-10-r62 + ## Specify a imagePullPolicy + ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + # pullSecrets: + # - myRegistryKeySecretName + + ## Set to true if you would like to see extra information on logs + ## ref: https://github.com/bitnami/minideb-extras/#turn-on-bash-debugging + ## + debug: false + +## Bitnami Git image version +## ref: https://hub.docker.com/r/bitnami/git/tags/ +## +git: + registry: docker.io + repository: bitnami/git + tag: 2.29.0-debian-10-r0 + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + # pullSecrets: + # - myRegistryKeySecretName + +## String to partially override apache.fullname template (will maintain the release name) +## +# nameOverride: + +## String to fully override apache.fullname template +## +# fullnameOverride: + +## Number of Apache replicas to deploy +## +replicaCount: 1 + +## Pod affinity preset +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## Allowed values: soft, hard +## +podAffinityPreset: "" + +## Pod anti-affinity preset +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## Allowed values: soft, hard +## +podAntiAffinityPreset: soft + +## Node affinity preset +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity +## Allowed values: soft, hard +## +nodeAffinityPreset: + ## Node affinity type + ## Allowed values: soft, hard + type: "" + ## Node label key to match + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## Node label values to match + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + +## Affinity for pod assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set +## +affinity: {} + +## Node labels for pod assignment +## Ref: https://kubernetes.io/docs/user-guide/node-selection/ +## +nodeSelector: {} + +## Tolerations for pod assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] + +## Get the server static content from a git repository +## +cloneHtdocsFromGit: + enabled: false + # repository: + # branch: + interval: 60 + resources: {} + +## Name of a config map with the server static content +## +# htdocsConfigMap: + +## Name of a PVC with the server static content +## +# htdocsPVC: + +## Name of a config map with the virtual hosts content +## +# vhostsConfigMap: + +## Name of a config map with the httpd.conf file contents +## +# httpdConfConfigMap: + +## Pod annotations +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +podAnnotations: {} + +## Apache pods' resource requests and limits +## ref: http://kubernetes.io/docs/user-guide/compute-resources/ +## +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: {} + # cpu: 100m + # memory: 128Mi + requests: {} + # cpu: 100m + # memory: 128Mi + +## Apache container's liveness and readiness probes +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes +## +livenessProbe: + enabled: true + path: "/" + port: http + initialDelaySeconds: 180 + periodSeconds: 20 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 +readinessProbe: + enabled: true + path: "/" + port: http + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + +## Ingress paramaters +## +ingress: + ## Set to true to enable ingress record generation + ## + enabled: false + + ## Set this to true in order to add the corresponding annotations for cert-manager + ## + certManager: false + + ## When the ingress is enabled, a host pointing to this will be created + ## + hostname: example.local + + ## Ingress annotations done as key:value pairs + ## For a full list of possible ingress annotations, please see + ## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md + ## + ## If tls is set to true, annotation ingress.kubernetes.io/secure-backends: "true" will automatically be set + ## If certManager is set to true, annotation kubernetes.io/tls-acme: "true" will automatically be set + annotations: {} + # kubernetes.io/ingress.class: nginx + + ## The list of additional hostnames to be covered with this ingress record. + ## Most likely the hostname above will be enough, but in the event more hosts are needed, this is an array + ## hosts: + ## - name: example.local + ## path: / + + ## The tls configuration for the ingress + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + ## + tls: + - hosts: + - example.local + secretName: example.local-tls + + secrets: + ## If you're providing your own certificates, please use this to add the certificates as secrets + ## key and certificate should start with -----BEGIN CERTIFICATE----- or + ## -----BEGIN RSA PRIVATE KEY----- + ## + ## name should line up with a tlsSecret set further up + ## If you're using cert-manager, this is unneeded, as it will create the secret for you if it is not set + ## + ## It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + # - name: apache.local-tls + # key: + # certificate: + +## Prometheus Exporter / Metrics +## +metrics: + enabled: false + ## Bitnami Apache Prometheus Exporter image + ## ref: https://hub.docker.com/r/bitnami/apache-exporter/tags/ + ## + image: + registry: docker.io + repository: bitnami/apache-exporter + tag: 0.8.0-debian-10-r186 + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + # pullSecrets: + # - myRegistryKeySecretName + ## Metrics exporter pod Annotation and Labels + ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + ## + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9117" + ## Apache Prometheus exporter resource requests and limits + ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: {} + # cpu: 100m + # memory: 128Mi + requests: {} + # cpu: 100m + # memory: 128Mi + +## Array to add extra volumes (evaluated as a template) +## +extraVolumes: [] + +## Array to add extra mounts (normally used with extraVolumes, evaluated as a template) +## +extraVolumeMounts: [] + +## An array to add extra env vars +## +extraEnvVars: [] + +## Service paramaters +## +service: + ## Service type + ## + type: LoadBalancer + ## HTTP Port + ## + port: 80 + ## HTTPS Port + ## + httpsPort: 443 + ## Specify the nodePort(s) value(s) for the LoadBalancer and NodePort service types. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + http: "" + https: "" + ## Set the LoadBalancer service type to internal only. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + # loadBalancerIP: + ## Provide any additional annotations which may be required. This can be used to + ## set the LoadBalancer service type to internal only. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + annotations: {} + + ## Enable client source IP preservation + ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/default-values.yaml b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/default-values.yaml new file mode 100644 index 00000000..ef8deec2 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/default-values.yaml @@ -0,0 +1,3 @@ +## Number of Apache replicas to deploy +## +replicaCount: 2 diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/restore-values.yaml b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/restore-values.yaml new file mode 100644 index 00000000..69243f81 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/restore-values.yaml @@ -0,0 +1,3 @@ +## Number of Apache replicas to deploy +## +replicaCount: 1 diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/values-mapping.json b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/values-mapping.json new file mode 100644 index 00000000..043d62e8 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/values-mapping.json @@ -0,0 +1,14 @@ +[ + { + "name": "replica-count", + "property": { + "description": "Number of replicas for scaling", + "type": "integer", + "required": false + }, + "input-param": false, + "dictionary-name": "replica-count", + "dictionary-source": "capability", + "dependencies": [] + } +] diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/values.yaml.vtl b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/values.yaml.vtl new file mode 100644 index 00000000..a76d6ba2 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba/Templates/k8s-configs/deployment-values/values.yaml.vtl @@ -0,0 +1,3 @@ +## Number of Apache replicas to deploy +## +replicaCount: ${replica-count} diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-profiles/cnf-cds-base-profile.tar.gz b/tutorials/ApacheCNF/templates/cba/Templates/k8s-profiles/cnf-cds-base-profile.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..ee8465cd7c6084f081a458fe96bb7b5fc13c4c24 GIT binary patch literal 213 zcmb2|=3ua0(-OzP{PwCh*C7Lu)`va2yB_SBbYn^Dxt$_m+BWR@h;}iJK<2O z)FnLsL;YkGm1gdfC)ZZRUq5>2eAV`MHOBXLo{icwgDWWch~k;$$1nf0TBSXgYwnHC zO==gzIyYQ%<6apTd%`yM@~$YajZ)`hcNX!Vx4r#8cy0czhwqAKy53*MHh)`T>PDXY z2f7FMSIqivvis!zjb_UK=L;M!6p3;O4oTIkmfgC0?RjO*_Oc15151}X_WaObKmv6~ NCAUot{mlRr1OU;dWCH*I literal 0 HcmV?d00001 diff --git a/tutorials/ApacheCNF/templates/cba/Templates/k8s-profiles/node-port-profile.tar.gz b/tutorials/ApacheCNF/templates/cba/Templates/k8s-profiles/node-port-profile.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..ef37a9e6cbe21359b5e68777515da8c446c1166b GIT binary patch literal 225 zcmV<703QDziwFQ4=aXRs0PWRF4uUWc2H;t9ipD*pr7cZ3gy9CJN=*na(*g-AJ(_p$ zLRJX6(YR3}vEOEzc9O3CnYvS2XQ|qBvS^hFdRZ3mVVGbngaABx)CmoNFv6IKD5LhC zgxIzt3^Qm=BQ@Yz{`x^i=`P!;*h8r44=P6MI#o%n8xNd6P|7OXE7N=>_@g1`5o2(& z=j41jPW7JuNC2Tc#GFyWZ~14O&zgUPAP=^(%H^xJx9 + + + + 4.0.0 + + + org.onap.ccsdk.cds.components.cba + test-blueprint-kotlin-parent + 1.2.0 + + + apache + 1.2.0 + pom + + + + ccsdkapps + ccsdkapps + + + + + + org.onap.ccsdk.cds.blueprintsprocessor.modules + processor-core + 1.2.0 + compile + + + org.onap.ccsdk.cds.blueprintsprocessor.functions + k8s-connection-plugin + 1.2.0 + compile + + + com.att.aft + dme2 + 3.1.200-oss + compile + + + org.onap.ccsdk.cds.blueprintsprocessor.modules + selfservice-api + + + diff --git a/tutorials/ApacheCNF/templates/cba2dd.py b/tutorials/ApacheCNF/templates/cba2dd.py new file mode 100644 index 00000000..02cf6085 --- /dev/null +++ b/tutorials/ApacheCNF/templates/cba2dd.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# COPYRIGHT NOTICE STARTS HERE + +# Copyright 2020 . Samsung Electronics Co., Ltd. +# +# 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. + +# COPYRIGHT NOTICE ENDS HERE + +import os +import argparse +import json + +# +# Script to convert given Enriched CDS CBA model to Data Dictionary output +# Usage: +# ./cba2dd.py --cba_dir | python3 -m json.tool +# + +def get_resources_definition_file(cba_dir): + definitions_dir = cba_dir + os.sep + "Definitions" + resource_definition_file = definitions_dir + os.sep + "resources_definition_types.json" + if not os.path.exists(definitions_dir): + raise RuntimeError("'%s' directory does not exists or is not CBA directory" % cba_dir) + if not os.path.exists(resource_definition_file): + raise RuntimeError("'%s' file does not exists in CBA Definitions directory. CBA is not Enriched!" % resource_definition_file) + return resource_definition_file + +def create_dd(cba_dir): + with open(get_resources_definition_file(cba_dir)) as f: + output_json = json.load(f) + dd = [] + for _, entry in output_json.items(): + dd.append(build_dd_entry(entry)) + print(json.dumps(dd)) + +def build_dd_entry(definition_entry): + """Builds Data Dictionary entry from given dictionary entry. Given entry + itself is added as value for "definition" key. + { + "name": "", + "tags": "", + "data_type": "", + "description": "", + "entry_schema": "", + "updatedBy": "", + "definition": definition_entry + } + """ + out_dict = {} + out_dict["name"] = definition_entry["name"] + out_dict["tags"] = definition_entry["tags"] + out_dict["data_type"] = definition_entry["property"]["type"] + out_dict["description"] = definition_entry["property"]["description"] + out_dict["entry_schema"] = definition_entry["property"]["type"] + out_dict["updatedBy"] = definition_entry["updated-by"] + out_dict["definition"] = definition_entry + return out_dict + +def main(): + description = """Script to convert given Enriched CDS CBA model to Data Dictionary output. +Example: + ./cba2dd.py --cba_dir cba | python3 -m json.tool + """ + parser = argparse.ArgumentParser(description=description, + formatter_class=argparse.RawTextHelpFormatter) + parser.add_argument('--cba_dir', + help='Path to CDS CBA model main directory', + default='') + args = parser.parse_args() + try: + create_dd(args.cba_dir) + except Exception as e: + print(e) + parser.print_help() + exit(1) + +if __name__ == '__main__': + main() diff --git a/tutorials/ApacheCNF/templates/helm/.gitignore b/tutorials/ApacheCNF/templates/helm/.gitignore new file mode 100644 index 00000000..17d6b367 --- /dev/null +++ b/tutorials/ApacheCNF/templates/helm/.gitignore @@ -0,0 +1 @@ +/*.tgz diff --git a/tutorials/ApacheCNF/templates/helm/Makefile b/tutorials/ApacheCNF/templates/helm/Makefile new file mode 100644 index 00000000..5bcea8fb --- /dev/null +++ b/tutorials/ApacheCNF/templates/helm/Makefile @@ -0,0 +1,17 @@ +vf-modules = apache +.PHONY: build clean $(vf-modules:=-build) $(vf-modules:-clean) $(vf-modules:=-package) + +package: $(vf-modules:=-package) +build: $(vf-modules:=-build) +clean: $(vf-modules:=-clean) + +$(vf-modules:=-package): %-package: %-build + mv $(@:package=)*.tgz helm_$(@:-package=).tgz + +$(vf-modules:=-build): %-build: %-clean + helm repo add bitnami https://charts.bitnami.com/bitnami + helm pull bitnami/apache --version 7.6.0 + +$(vf-modules:=-clean): + rm -f $(@:-clean=)-*.tgz + rm -f helm_$(@:-clean=).tgz diff --git a/tutorials/ApacheCNF/templates/helm/README.txt b/tutorials/ApacheCNF/templates/helm/README.txt new file mode 100644 index 00000000..63429e91 --- /dev/null +++ b/tutorials/ApacheCNF/templates/helm/README.txt @@ -0,0 +1,7 @@ +Helm content of onboarding package + +To create necessary archives, please ensure you have [helm] and [make] installed first. + +In case it's your first time you're using helm, please issue `helm init -c` command to initialize your helm client + +To create necessary artifacts, issue `make` command diff --git a/tutorials/ApacheCNF/templates/tools/tail_all.sh b/tutorials/ApacheCNF/templates/tools/tail_all.sh new file mode 100644 index 00000000..d18674ea --- /dev/null +++ b/tutorials/ApacheCNF/templates/tools/tail_all.sh @@ -0,0 +1,161 @@ +#!/bin/bash +# COPYRIGHT NOTICE STARTS HERE + +# Copyright 2020 . Samsung Electronics Co., Ltd. +# +# 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. + +# COPYRIGHT NOTICE ENDS HERE + +set -e + +get_pod_name() { + kubectl -n ${NAMESPACE} get pod -l app="$1" -o jsonpath='{ .items[0].metadata.name }' +} + +exec_in_pod() { + local pod="$1" + local container="$2" + shift 2 + local cmd="$@" + kubectl --namespace ${NAMESPACE} exec ${pod} --container ${container} -- sh -c "${cmd}" +} + +pod_logs() { + local pod="$1" + local container="$2" + local options="$3" + shift 3 + kubectl --namespace ${NAMESPACE} logs ${pod} --container ${container} ${options:+"${options}"} +} + +k8s_tail() { + local operation="$1" + local file_to_tail="$2" + local pod_label="$3" + local container="$4" + if [ -z ${container} ]; then + container=${pod_label} + fi + mkdir -p ${CACHE_FILE_DIR} + local pod=$(get_pod_name ${pod_label}) + file_path_savable_form="$(sed 's#/#__#g' <<<"$file_to_tail")" + LINECOUNT_CACHE_FILE=${CACHE_FILE_DIR}/${pod}-${container}-${file_path_savable_form} + local line_count=0 + if [ "${operation}" == "start" ]; then + if [ "${file_to_tail}" == "POD_LOG" ]; then + line_count=$(pod_logs ${pod} ${container} "" | wc -l) + else + if ! line_count=$(exec_in_pod ${pod} ${container} "wc -l ${file_to_tail}"); then + echo "Failed to get file ${file_to_tail} line count, maybe it does not exist. Using linecount 0." >&2 + line_count=0 + else + # parse out linecount from wc -l output + line_count=$(echo -e "${line_count}" | tail -1 | cut -d' ' -f1) + fi + fi + echo "${line_count}" > ${LINECOUNT_CACHE_FILE} + echo "Saved file ${file_to_tail} of POD ${pod_label} linecount ${line_count} into file ${LINECOUNT_CACHE_FILE}" + fi + if [ "${operation}" == "collect" ]; then + if [ ! -f ${LINECOUNT_CACHE_FILE} ]; then + echo "Linecount cache file ${LINECOUNT_CACHE_FILE} not found. Either tailing was not started or POD has restarted. Colected from log beginning." >&2 + start_line=0 + else + start_line=$(cat ${LINECOUNT_CACHE_FILE}) + fi + echo "Tail pod's ${pod_label} container ${container} file ${file_to_tail} starting from line ${start_line} onwards" >&2 + if [ "${file_to_tail}" == "POD_LOG" ]; then + current_line_count=$(pod_logs ${pod} ${container} "" | wc -l) + lines_from_end=$(( ${current_line_count}-${start_line} )) + echo "Execute kubectl logs for ${pod} POD's ${container} container. Log ${lines_from_end} lines from end" + pod_logs ${pod} ${container} --tail=${lines_from_end} + else + echo "Execute cmd "tail -n +${start_line} ${file_to_tail}" inside ${pod} POD's ${container} container" + exec_in_pod ${pod} ${container} "tail -n +${start_line} ${file_to_tail}" + fi + fi +} + +tail_it() { + local operation=$1 + for tail in "${TAILS[@]}" + do + tailarray=(${tail}) + result=$(k8s_tail ${operation} ${tailarray[@]}) + if [ "${operation}" == "collect" ]; then + mkdir -p ${RESULT_DIR} + log_file=$(basename ${tailarray[0]}) + if [ "${log_file}" == "POD_LOG" ]; then + log_file=${log_file}.log + fi + pod=${tailarray[1]} + container="${pod:-tailarray[2]}" + out_file=${RESULT_DIR}/${pod}_${container}_${log_file} + echo -e "${result}" > ${out_file} + echo "Saved tail content to log file ${out_file}" + else + echo -e "${result}" + fi + done +} + + +##### MAIN ##### +if [ -f ./tail_config ]; then +. ./tail_config +fi +NAMESPACE=${NAMESPACE:-onap} +CACHE_FILE_DIR=${CACHE_FILE_DIR:-.k8s_tail} +RESULT_DIR=${RESULT_DIR:-./tail_results} +DEFAULT_TAILS=() +TAILS=("${TAILS[@]:-${DEFAULT_TAILS[@]}}") + +case "$1" in + -h|--help|help|?|"") + echo "Script usage:" + echo "$0 start - Start pods' log tailing" + echo "$0 collect - Collect all logs currently tailed or get all logs as whole" + echo "" + echo "If start is not called before collect is called, collect gathers all logs completely. " + echo "Otherwise logs are collected only from the linecount of the time of start call." + echo "" + echo "Log files collected is configured with 'tail_config' file in the same directory with the script." + echo "Config file needs to fontain bash array variable named TAILS=() and format of each entry in array is" + echo " []" + echo "where is actual file path inside the pod or special string 'POD_LOG' that means kubectl logs" + echo "where optional is to specify POD's container if many containers in the pod. By default same name as pod is used." + echo "" + echo 'Example: TAILS=(' + echo ' "/app/logs/apih/metrics.log so"' + echo ' "/app/logs/bpmn/debug.log so-bpmn-infra"' + echo ' "/app/logs/vnfm-adapter/debug.log so-vnfm-adapter"' + echo ' "/var/log/onap/sdnc/karaf.log sdnc"' + echo ' "/tmp/app.out network-name-gen"' + echo ' "POD_LOG cds-blueprints-processor"' + echo ' "POD_LOG multicloud multicloud"' + echo ' "POD_LOG multicloud-k8s multicloud-k8s"' + echo ' "POD_LOG multicloud-k8s framework-artifactbroker"' + echo ' "/app/logs/openstack/error.log so-openstack-adapter"' + echo ' "/app/logs/openstack/debug.log so-openstack-adapter"' + echo ' )' + echo "" + ;; + start|collect) + tail_it $1 + ;; + *) + echo "Wrong usage, check '$0 -h'" >&2 + exit 1 + ;; +esac diff --git a/tutorials/ApacheCNF/templates/tools/tail_config b/tutorials/ApacheCNF/templates/tools/tail_config new file mode 100644 index 00000000..ca49793c --- /dev/null +++ b/tutorials/ApacheCNF/templates/tools/tail_config @@ -0,0 +1,18 @@ +#!/bin/false + +NAMESPACE="onap" + +TAILS=( + "/app/logs/apih/debug.log so" + "/app/logs/apih/error.log so" + "/app/logs/bpmn/debug.log so-bpmn-infra" + "/app/logs/openstack/error.log so-openstack-adapter" + "/app/logs/openstack/debug.log so-openstack-adapter" + "/var/log/onap/sdnc/karaf.log sdnc" + "POD_LOG network-name-gen" + "POD_LOG cds-blueprints-processor" + "POD_LOG multicloud multicloud" + "POD_LOG multicloud-k8s multicloud-k8s" + "POD_LOG multicloud-k8s framework-artifactbroker" + "POD_LOG msb-iag msb-iag" +) -- 2.16.6