From 7c3f39504a14c056d860e09ece970ccde349053f Mon Sep 17 00:00:00 2001 From: JakobKrieg Date: Tue, 4 Aug 2020 20:46:50 +0200 Subject: [PATCH] Adding Modeling Concepts documentation from COnfluence to RDT Issue-ID: CCSDK-2615 Change-Id: Ib5dfaecc96e8fac1dda07aa6c13aba5ded81efee Signed-off-by: JakobKrieg --- docs/conf.py | 2 + docs/index.rst | 1 + docs/media/dd_mapping_template_rel.png | Bin 0 -> 62055 bytes docs/modelingconcepts/artifact-type.rst | 186 ++++ docs/modelingconcepts/cba.rst | 36 + docs/modelingconcepts/data-dictionary.rst | 113 +++ docs/modelingconcepts/data-type.rst | 231 +++++ docs/modelingconcepts/dynamic-payload.rst | 78 ++ docs/modelingconcepts/enrichment.rst | 56 ++ docs/modelingconcepts/expression.rst | 101 +++ docs/modelingconcepts/flexible-plug-in.rst | 122 +++ docs/modelingconcepts/node-type.rst | 1032 +++++++++++++++++++++++ docs/modelingconcepts/overview.rst | 48 ++ docs/modelingconcepts/scripts.rst | 27 + docs/modelingconcepts/southbound-interfaces.rst | 23 + docs/modelingconcepts/template.rst | 23 + docs/modelingconcepts/test.rst | 40 + docs/modelingconcepts/tosca-meta.rst | 80 ++ docs/modelingconcepts/workflow.rst | 322 +++++++ 19 files changed, 2521 insertions(+) create mode 100644 docs/media/dd_mapping_template_rel.png create mode 100644 docs/modelingconcepts/artifact-type.rst create mode 100644 docs/modelingconcepts/cba.rst create mode 100644 docs/modelingconcepts/data-dictionary.rst create mode 100644 docs/modelingconcepts/data-type.rst create mode 100644 docs/modelingconcepts/dynamic-payload.rst create mode 100644 docs/modelingconcepts/enrichment.rst create mode 100644 docs/modelingconcepts/expression.rst create mode 100644 docs/modelingconcepts/flexible-plug-in.rst create mode 100644 docs/modelingconcepts/node-type.rst create mode 100644 docs/modelingconcepts/overview.rst create mode 100644 docs/modelingconcepts/scripts.rst create mode 100644 docs/modelingconcepts/southbound-interfaces.rst create mode 100644 docs/modelingconcepts/template.rst create mode 100644 docs/modelingconcepts/test.rst create mode 100644 docs/modelingconcepts/tosca-meta.rst create mode 100644 docs/modelingconcepts/workflow.rst diff --git a/docs/conf.py b/docs/conf.py index d211470a6..de84a196d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -7,6 +7,8 @@ linkcheck_ignore = [ 'http://localhost', ] +extensions = ['sphinx_tabs.tabs'] + intersphinx_mapping = {} html_last_updated_fmt = '%d-%b-%y %H:%M' diff --git a/docs/index.rst b/docs/index.rst index 9427fa9a2..bf6bba508 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -74,6 +74,7 @@ Modeling Concept Links: .. toctree:: :maxdepth: 1 + modelingconcepts/overview microservices/controllerBlueprintStudioProcessorMS microservices/bluePrintsProcessorMS microservices/expression diff --git a/docs/media/dd_mapping_template_rel.png b/docs/media/dd_mapping_template_rel.png new file mode 100644 index 0000000000000000000000000000000000000000..cfe98e140b800058a3f02093cb846bc6b504e1c1 GIT binary patch literal 62055 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

cE^s}D&{@m-I1qHW$qNk=2Iv<>Y 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

0fDF7wC_#*9xHi3 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 R1O$Ap>D;)Sd&w^RzW`S1L!$ry literal 0 HcmV?d00001 diff --git a/docs/modelingconcepts/artifact-type.rst b/docs/modelingconcepts/artifact-type.rst new file mode 100644 index 000000000..15a968e18 --- /dev/null +++ b/docs/modelingconcepts/artifact-type.rst @@ -0,0 +1,186 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts#Concepts-1386016968 by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +.. _artifact_type: + +Artifact Type +------------------------------------- + +Represents the **type of a artifact**, used to **identify** the +**implementation** of the functionality supporting this type of artifact. + +`TOSCA definition `_ + +This node was created, derived from ``tosca.artifacts.Root`` to be the root TOSCA node for all artifact. + +.. code-block:: JSON + :caption: **tosca.artifacts.Implementation** + + { + "description": "TOSCA base type for implementation artifacts", + "version": "1.0.0", + "derived_from": "tosca.artifacts.Root" + } + +**Bellow is a list of supported artifact types** + +.. tabs:: + + .. tab:: Velocity + + **artifact-template-velocity** + + Represents an Apache Velocity template. + + Apache Velocity allow to insert **logic** (if / else / loops / etc) when processing the output of a template/text. + + File must have **.vtl** extension. + + The **template** can represent anything, such as device config, payload to interact with 3rd party systems, + :ref:`resource-accumulator template`, etc... + + Often a template will be **parameterized**, and each **parameter** + must be defined within an mapping file (see 'Mapping' in this tab). + + `Velocity reference document `_ + + `Here `_ + is the TOSCA artifact type: + + .. code-block:: JSON + :caption: **artifact-template-velocity** + + { + "description": "TOSCA base type for implementation artifacts", + "version": "1.0.0", + "derived_from": "tosca.artifacts.Root" + } + + .. tab:: Jinja + + **artifact-template-jinja** + + Represents an Jinja template. + + Jinja template allow to insert **logic** (if / else / loops / etc) when processing the output of a template/text. + + File must have **.jinja** extension. + + The **template** can represent **anything**, such as device config, + payload to interact with 3rd party systems, :ref:`resource-accumulator template`, etc... + + Often a template will be parameterized, and each parameter must be defined within an :ref:`mapping file`. + + `Jinja reference document `_ + + `Here `_ + is the TOSCA artifact type: + + .. code-block:: JSON + :caption: **artifact-template-jinja** + + { + "description": " Jinja Template used for Configuration", + "version": "1.0.0", + "file_ext": [ + "jinja" + ], + "derived_from": "tosca.artifacts.Implementation" + } + + .. tab:: Mapping + + **artifact-mapping-resource** + + This type is meant to represent **mapping** files defining the **contract of each resource** to be resolved. + + Each **parameter** in a template **must** have a corresponding mapping definition, + modeled using datatype-resource-assignment (see :ref:`data_type`-> resources-asignment). + + Hence the mapping file is meant to be a list of entries defined using datatype-resource-assignment + (see :ref:`data_type`-> resources-asignment). + + File must have **.json** extension. + + The **template** can represent **anything**, such as device config, + payload to interact with 3rd party systems, resource-accumulator template, etc... + + `Here `_ + is the TOSCA artifact type: + + .. code-block:: JSON + :caption: **artifact-mapping-resource** + + { + "description": "Resource Mapping File used along with Configuration template", + "version": "1.0.0", + "file_ext": [ + "json" + ], + "derived_from": "tosca.artifacts.Implementation" + } + + The mapping file basically contains a reference to the data dictionary to use + to resolve a particular resource. + + The data dictionary defines the HOW and the mapping defines the WHAT. + + **Relation between data dictionary, mapping and template.** + + Below are two examples using color coding to help understand the relationships. + + In orange is the information regarding the template. As mentioned before, + template is part of the blueprint itself, and for the blueprint to know what template to use, + the name has to match. + + In green is the relationship between the value resolved within the template, + and how it's mapped coming from the blueprint. + + In blue is the relationship between a resource mapping to a data dictionary. + + In red is the relationship between the resource name to be resolved and the HEAT environment variables. + + The key takeaway here is that whatever the value is for each color, it has to match all across. + This means both right and left hand side are equivalent; it's all on the designer to express + the modeling for the service. That said, best practice is example 1. + + .. image:: ../media/dd_mapping_template_rel.png + :scale: 100 % + :align: center + + .. tab:: Directed Graph + + **artifact-directed-graph** + + Represents a directed graph. + + This is to represent a **workflow**. + + File must have **.xml** extension. + + Here is the list of executors currently supported (see here for explanation and full potential list: + `Service Logic Interpreter Nodes `_ + + * execute + * block + * return + * break + * exit + + `Here `_ + is the TOSCA artifact type: + + .. code-block:: json + :caption: **artifact-directed-graph** + + { + "description": "Directed Graph File", + "version": "1.0.0", + "file_ext": [ + "json", + "xml" + ], + "derived_from": "tosca.artifacts.Implementation" + } diff --git a/docs/modelingconcepts/cba.rst b/docs/modelingconcepts/cba.rst new file mode 100644 index 000000000..a400ef614 --- /dev/null +++ b/docs/modelingconcepts/cba.rst @@ -0,0 +1,36 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts#Concepts-66498 by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +.. _cba: + +Controller Blueprint Archive (.cba) +------------------------------------- + +The **C**\ ontroller **B**\ lueprint **A**\ rchive is the overall service design, fully model-driven, intent based +**package** needed for provisioning and configuration management automation. + +The CBA is **.zip** file, comprised of the following folder structure, the files may vary: + +.. code-block:: + + ├── Definitions + │ ├── blueprint.json Overall TOSCA service template (worfklow + node_template) + │ ├── artifact_types.json (generated by enrichment) + │ ├── data_types.json (generated by enrichment) + │ ├── node_types.json (generated by enrichment) + │ ├── relationship_types.json (generated by enrichment) + │ └── resources_definition_types.json (generated by enrichment) + ├── Environments Contains *.properties files as required by the service + ├── Plans Contains Directed Graph + ├── Tests Contains uat.yaml file for testing the cba actions within a cba **package + ├── Scripts Contains scripts + │ ├── python Python scripts + │ └── kotlin Kotlin scripts + ├── TOSCA-Metadata + │ └── TOSCA.meta Meta-data of overall package + └── Templates Contains combination of mapping and template + +To process a CBA for any service we need to enrich it first. This will gather all the node- type, data-type, +artifact-type, data-dictionary definitions provided in the blueprint.json. \ No newline at end of file diff --git a/docs/modelingconcepts/data-dictionary.rst b/docs/modelingconcepts/data-dictionary.rst new file mode 100644 index 000000000..f2dbc3524 --- /dev/null +++ b/docs/modelingconcepts/data-dictionary.rst @@ -0,0 +1,113 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts#Concepts-1386016968 by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +.. _data_dictionary: + +Data Dictionary +----------------- + +A data dictionary **models the how** a specific **resource** can be **resolved**. + +A resource is a **variable/parameter** in the context of the service. +It can be anything, but it should not be confused with SDC or Openstack resources. + +A data dictionary can have **multiple sources** to handle resolution in different ways. + +The main goal of data dictionary is to define **re-usable** entity that could be shared. + +**Creation** of data dictionaries is a **standalone** activity, separated from the blueprint design. + +As part of modelling a data dictionary entry, the following generic information should be provided: + +.. list-table:: + :widths: 25 50 25 + :header-rows: 1 + + * - Property + - Description + - Scope + * - updated-by + - The creator + - Mandatory + * - tags + - Information related + - Mandatory + * - sources + - List of resource source instance (see :ref:`resource source`) + - Mandatory + * - property + - Defines type and description, as nested JSON + - Mandatory + * - name + - Data dictionary name + - Mandatory + +**Bellow are properties that all the resource source can have** + +The modeling does allow for **data translation** between external capability +and CDS for both input and output key mapping. + +.. list-table:: + :widths: 25 50 25 + :header-rows: 1 + + * - Property + - Description + - Scope + * - input-key-mapping + - map of resources required to perform the request/query. The left hand-side is what is used within + the query/request, the right hand side refer to a data dictionary instance. + - Optional + * - output-key-mapping + - name of the resource to be resolved mapped to the value resolved by the request/query. + - Optional + * - key-dependencies + - | list of data dictionary instances to be resolved prior the resolution of this specific resource. + | during run time execution the key dependencies are recursively sorted and resolved + in batch processing using the `acyclic graph algorithm + `_ + - Optional + +**Example:** + +``vf-module-model-customization-uuid`` and ``vf-module-label`` are two data dictionaries. +A SQL table, VF_MODULE_MODEL, exist to correlate them. + +Here is how input-key-mapping, output-key-mapping and key-dependencies can be used: + +.. list-table:: + :widths: 100 + :header-rows: 1 + + * - vf-module-label data dictionary + * - .. code-block:: JSON + + + { + "name" : "vf-module-label", + "tags" : "vf-module-label", + "updated-by" : "adetalhouet", + "property" : { + "description" : "vf-module-label", + "type" : "string" + }, + "sources" : { + "primary-db" : { + "type" : "source-primary-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" ] + } + } + } + } \ No newline at end of file diff --git a/docs/modelingconcepts/data-type.rst b/docs/modelingconcepts/data-type.rst new file mode 100644 index 000000000..d9861a23c --- /dev/null +++ b/docs/modelingconcepts/data-type.rst @@ -0,0 +1,231 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts#Concepts-1581473264 by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +.. _data_type: + +Data type +------------------------------------- + +Represents the **schema** of a specific type of **data**. + +Supports both **primitive** and **complex** data types: + +.. list-table:: + :widths: 50 50 + :header-rows: 1 + + * - Primitive + - Complex + * - * string + * integer + * float + * double + * boolean + * timestamp + * null + - * json + * list + * array +For complex data type, an **entry schema** is required, defining the +type of value contained within the complex type, if list or array. + +Users can **create** as many **data type** as needed. + +.. note:: + + **Creating Custom Data Types:** + + To create a custom data-type you can use a POST call to CDS endpoint: + ":/api/v1/model-type" + + .. code-block:: python + :caption: **Payload:** + + { + + "model-name": "", + "derivedFrom": "tosca.datatypes.Root", + + "definitionType": "data_type", + + "definition": { + + "description": "", + + "version": "", + + "properties": {}, + + "derived_from": "tosca.datatypes.Root" + + }, + + "description": "", + + "tags": ",datatypes.Root.data_type", + + "creationDate": "", + + "updatedBy": "" + + } + +Data type are useful to manipulate data during resource resolution. +They can be used to format the JSON output as needed. + +List of existing data type: +``_ + +`TOSCA specification +`_ + +**Below is a list of existing data types** + +.. tabs:: + + .. tab:: resource-assignment + + **datatype-resource-assignment** + + Used to define entries within artifact-mapping-resource + (see tab Artifact Type -> artifact-mapping-resource) + + That datatype represent a **resource** to be resolved. We also refer + this as an **instance of a data dictionary** as it's directly linked to + its definition. + + .. list-table:: + :widths: 50 50 + :header-rows: 1 + + * - Property + - Description + * - property + - Defines how the resource looks like (see datatype-property on the right tab) + * - input-param + - Whether the resource can be provided as input. + * - dictionary-name + - Reference to the name of the data dictionary (see :ref:`data_dictionary`). + * - dictionary-source + - Reference the source to use to resolve the resource (see :ref:`resource source`). + * - dependencies + - List of dependencies required to resolve this resource. + * - updated-date + - Date when mapping was upload. + * - updated-by + - Name of the person that updated the mapping. + + ``_ + + .. code-block:: JSON + :caption: **datatype-resource-assignment** + + { + "version": "1.0.0", + "description": "This is Resource Assignment Data Type", + "properties": { + "property": { + "required": true, + "type": "datatype-property" + }, + "input-param": { + "required": true, + "type": "boolean" + }, + "dictionary-name": { + "required": false, + "type": "string" + }, + "dictionary-source": { + "required": false, + "type": "string" + }, + "dependencies": { + "required": true, + "type": "list", + "entry_schema": { + "type": "string" + } + }, + "updated-date": { + "required": false, + "type": "string" + }, + "updated-by": { + "required": false, + "type": "string" + } + }, + "derived_from": "tosca.datatypes.Root" + } + + .. tab:: property + + **datatype-property** + + Used to defined the **property** entry of a **resource assignment**. + + .. list-table:: + :widths: 25 75 + :header-rows: 1 + + * - Property + - Description + * - type + - Whether it's a primitive type, or a defined data-type + * - description + - Description of for the property + * - required + - Whether it's required or not + * - default + - If there is a default value to provide + * - entry_schema + - If the type is a complex one, such as list, define what is the type of element within the list. + + ``_ + + .. code-block:: JSON + :caption: **datatype-property** + + { + "version": "1.0.0", + "description": "This is Resource Assignment Data Type", + "properties": { + "property": { + "required": true, + "type": "datatype-property" + }, + "input-param": { + "required": true, + "type": "boolean" + }, + "dictionary-name": { + "required": false, + "type": "string" + }, + "dictionary-source": { + "required": false, + "type": "string" + }, + "dependencies": { + "required": true, + "type": "list", + "entry_schema": { + "type": "string" + } + }, + "updated-date": { + "required": false, + "type": "string" + }, + "updated-by": { + "required": false, + "type": "string" + } + }, + "derived_from": "tosca.datatypes.Root" + } \ No newline at end of file diff --git a/docs/modelingconcepts/dynamic-payload.rst b/docs/modelingconcepts/dynamic-payload.rst new file mode 100644 index 000000000..731df542f --- /dev/null +++ b/docs/modelingconcepts/dynamic-payload.rst @@ -0,0 +1,78 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +Dynamic Payload +------------------------------------- + +One of the most important API provided by the run time is to execute a CBA Package. + +The nature of this API **request** and **response** is **model +driven** and **dynamic**. + +Here is how the a **generic request** and **response** look like. + +.. list-table:: + :widths: 50 50 + :header-rows: 1 + + * - request + - response + * - .. code-block:: json + + { + "commonHeader": { + "originatorId": "", + "requestId": "", + "subRequestId": "" + }, + "actionIdentifiers": { + "blueprintName": "", + "blueprintVersion": "", + "actionName": "", + "mode": "" + }, + "payload": { + "$actionName-request": { + "$actionName-properties": { + } + } + } + } + + - .. code-block:: json + + { + "commonHeader": { + "originatorId": "", + "requestId": "", + "subRequestId": "" + }, + "actionIdentifiers": { + "blueprintName": "", + "blueprintVersion": "", + "actionName": "", + "mode": "" + }, + "payload": { + "$actionName-response": { + } + } + } + +The ``actionName``, under the ``actionIdentifiers`` refers to the name of a +Workflow (see :ref:`workflow`) + +The content of the ``payload`` is what is fully dynamic / model driven. + +The first **top level element** will always be either +``$actionName-request`` for a request or ``$actionName-response`` for a response. + +Then the **content within this element** is fully based on the +**workflow** **inputs** and **outputs**. + +During the :ref:`enrichment` CDS will aggregate all the resources +defined to be resolved as input (see :ref:`node_type` -> Source -> Input), within mapping definition files +(see :ref:`artifact_type` -> Mapping), as data-type, that will then be use as type +of an input called ``$actionName-properties``. \ No newline at end of file diff --git a/docs/modelingconcepts/enrichment.rst b/docs/modelingconcepts/enrichment.rst new file mode 100644 index 000000000..8ea1ed3a7 --- /dev/null +++ b/docs/modelingconcepts/enrichment.rst @@ -0,0 +1,56 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +.. _enrichment: + +Enrichment +----------- + +The idea is that the CBA is a self-sufficient package, hence requires +all the various types definition its using. + +Reason for this is the types its using might evolve. In order for the +CBA to be bounded to the version it has been using when it has been +designed, these types are embedded in the CBA, so if they change, the +CBA is not affected. + +The enrichment process will complete the package by providing all the +definition of types used: + +* gather all the node-type used and put them into a :file:`node_types.json` file +* gather all the data-type used and put them into a :file:`data_types.json` file +* gather all the artifact-type used and put them into a :file:`artifact_types.json` file +* gather all the data dictionary definitions used from within the mapping files and put them + into a :file:`resources_definition_types.json` file + +.. warning:: + Before uploading a CBA, it must be enriched. If your package is already enrich, + you do not need to perform enrichment again. + +The enrichment can be run using REST API, and required the **.zip** file as input. +It will return an :file:`enriched-cba.zip` file. + +.. code-block:: bash + + curl -X POST \ + 'http://{{ip}}:{{cds-designtime}}/api/v1/blueprint-model/enrich' \ + -H 'content-type: multipart/form-data' \ + -F file=@cba.zip + +The enrichment process will also, for all resources to be resolved as input and default: + +* dynamically gather them under a data-type, named ``dt-${actionName}-properties`` +* will add it as a input of the workflow, as follow using this name: ``${actionName}-properties`` + +Example for workflow named *resource-assignment*: + +.. code-block:: JSON + :caption: **dynamic input** + + { + "resource-assignment-properties": { + "required": true, + "type": "dt-resource-assignment-properties" + } \ No newline at end of file diff --git a/docs/modelingconcepts/expression.rst b/docs/modelingconcepts/expression.rst new file mode 100644 index 000000000..639f700ef --- /dev/null +++ b/docs/modelingconcepts/expression.rst @@ -0,0 +1,101 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts#Concepts-198012600 by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + + +.. _expression: + +Expression +------------------------------------- + +TOSCA provides for a set of functions to reference elements within the template or to retrieve runtime values. + +**Below is a list of supported expressions** + +.. tabs:: + + .. tab:: get_input + + **get_input** + + The **get_input** function is used to retrieve the values of properties declared + within the inputs section of a TOSCA Service Template. + + Within CDS, this is mainly Workflow inputs. + + `TOSCA specification + `_ + + **Example:** + + ``_ + + .. code-block:: JSON + + "resolution-key": { + "get_input": "resolution-key" + } + + .. tab:: get_property + + **get_property** + + The **get_property** function is used to retrieve property values between modelable + entities defined in the same service template. + + `TOSCA specification + `_ + + **Example:** + + TBD + + .. tab:: get_attribute + + **get_attribute** + + The **get_attribute** function is used to retrieve the values of named attributes declared + by the referenced node or relationship template name. + + `TOSCA specification + `_ + + **Example:** + + ``_ + + .. code-block:: JSON + + "get_attribute": [ + "resource-assignment", + "assignment-params" + ] + + .. tab:: get_operation_output + + **get_operation_output** + + The **get_operation_output** function is used to retrieve property values between modelable + entities defined in the same service template. + + `TOSCA specification + `_ + + **Example:** + + TBD + + .. tab:: get_artifact + + **get_artifact** + + The **get_artifact** function is used to retrieve property values between modelable + entities defined in the same service template. + + `TOSCA specification + `_ + + **Example:** + + TBD \ No newline at end of file diff --git a/docs/modelingconcepts/flexible-plug-in.rst b/docs/modelingconcepts/flexible-plug-in.rst new file mode 100644 index 000000000..1b302e4eb --- /dev/null +++ b/docs/modelingconcepts/flexible-plug-in.rst @@ -0,0 +1,122 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts#Concepts-2026349199 by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +External Systems support +------------------------------------- + +Interaction with **external systems** is made **dynamic**, removing +development cycle to support new endpoint. + +In order to define the external system information, TOSCA provides +**dsl_definitions**. Link to TOSCA spec `info 1 +`_, +`info 2 `_. + +Use cases: + +* Resource resolution using **REST** (see tab Node Type) or **SQL** (see tab Node Type) external systems +* **gRPC** is supported for remote execution +* Any REST endpoint can be dynamically injected as part of the scripting framework. + +Here are some examples on how to populate the system information within the package: + +.. list-table:: + :widths: 100 + :header-rows: 1 + + * - token-auth + * - .. code-block:: JSON + + { + . . . + "dsl_definitions": { + "ipam-1": { + "type": "token-auth", + "url": "http://netbox-nginx.netprog:8080", + "token": "Token 0123456789abcdef0123456789abcdef01234567" + } + } + +.. list-table:: + :widths: 100 + :header-rows: 1 + + * - basic-auth + * - .. code-block:: JSON + + { + . . . + "dsl_definitions": { + "ipam-1": { + "type": "basic-auth", + "url": "http://localhost:8080", + "username": "bob", + "password": "marley" + } + } + . . . + } + +.. list-table:: + :widths: 100 + :header-rows: 1 + + * - ssl-basic-auth + * - .. code-block:: JSON + + { + . . . + "dsl_definitions": { + "ipam-1": { + "type" : "ssl-basic-auth", + "url" : "http://localhost:32778", + "keyStoreInstance": "JKS or PKCS12", + "sslTrust": "trusture", + "sslTrustPassword": "trustore password", + "sslKey": "keystore", + "sslKeyPassword: "keystore password" + } + } + . . . + } + +.. list-table:: + :widths: 100 + :header-rows: 1 + + * - grpc-executor + * - .. code-block:: JSON + + { + . . . + "dsl_definitions": { + "remote-executor": { + "type": "token-auth", + "host": "cds-command-executor.netprog", + "port": "50051", + "token": "Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==" + }, + } + . . . + } + +.. list-table:: + :header-rows: 1 + + * - maria-db + * - .. code-block:: JSON + + { + . . . + "dsl_definitions": { + "netprog-db": { + "type": "maria-db", + "url": "jdbc:mysql://10.195.196.123:32050/netprog", + "username": "netprog", + "password": "netprog" + } + } + . . . + } \ No newline at end of file diff --git a/docs/modelingconcepts/node-type.rst b/docs/modelingconcepts/node-type.rst new file mode 100644 index 000000000..9f86e0b26 --- /dev/null +++ b/docs/modelingconcepts/node-type.rst @@ -0,0 +1,1032 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts#Concepts-703799064 by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +.. _node_type: + +Node type +----------- + +`TOSCA definition +`_ + +In CDS, we have mainly two distinct types: components and source. We have some other type as well, +listed in the other section. + +.. tabs:: + + .. tab:: Component + + **Component:** + + Used to represent a **functionality** along with its **contract**, such as **inputs**, **ouputs**, and **attributes** + + `Here `_ + is the root component TOSCA node type from which other node type will derive: + + .. code-block:: json + :caption: **tosca.nodes.Component** + + { + "description": "This is default Component Node", + "version": "1.0.0", + "derived_from": "tosca.nodes.Root" + } + + **Bellow is a list of supported components** + + .. tabs:: + + .. tab:: resource-resolution + + **component-resource-resolution:** + + Used to perform resolution of **resources**. + + Requires as many as artifact-mapping-resource (see :ref:`artifact_type` -> Mapping) AND + artifact-template-velocity (see :ref:`artifact_type` -> Jinja) as needed. + + **Output result:** + + Will put the resolution result as an **attribute** in the workflow context called **assignment-params**. + + Using the :ref:`undefined `, this attribute can be retrieve to be + provided as workflow output (see :ref:`workflow`). + + **Specify which template to resolve:** + + Currently, resolution is bounded to a template. To specify which template to use, you + need to fill in the `artifact-prefix-names` field. + + See :ref:`template` to understand what the artifact prefix name is. + + **Storing the result:** + + To store each resource being resolved, along with their status, and the resolved template, `store-result` should be set to `true`. + + Also, when storing the data, it must be in the context of either a `resource-id` and `resource-type`, or based on a given `resolution-key` + + + The concept of resource-id / resource-type, or resolution-key, is to uniquely identify a specific resolution that + has been performed for a given action. Hence the resolution-key has to be unique for a given blueprint name, blueprint version, action name. + + Through the combination of the fields mentioned previously, one could retrieved what has been resolved. This is useful to manage the life-cycle of the resolved resource, the life-cycle of the template, along with sharing with external systems the outcome of a given resolution. + + The resource-id / resource-type combo is more geared to uniquely identify a resource in AAI, or external system. For example, for a given AAI resource, say a PNF, you can trigger a given CDS action, and then you will be able to manage all the resolved resources bound to this PNF. Even we could have a history of what has been assigned, unassigned for this given AAI resource. + + .. warning:: Important not to confuse and AAI resource (e.g. a topology element, + or service related element) with the resources resolved by CDS, which can be seen + as parameters required to derived a network configuration. + + **Run the resolution multiple time:** + + If you need to run the same resolution component multiple times, use the field `occurence`. + This will add the notion of occurrence to the resolution, and if storing the results, resources + and templates, they will be accessible for each occurrence. + + Occurrence is a number between 1 and N; when retrieving information + for a given occurrence, the first iteration starts at 1. + + This feature is useful when you need to apply the same configuration accross network elements. + + `Here `_ + is the definition: + + .. code-block:: json + :caption: **component-resource-resolution** + + { + "description": "This is Resource Assignment Component API", + "version": "1.0.0", + "attributes": { + "assignment-params": { + "required": true, + "type": "string" + } + }, + "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" + }, + "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" + }, + "status": { + "required": true, + "type": "string" + } + } + } + } + } + }, + "derived_from": "tosca.nodes.Component" + } + + .. tab:: script-executor + + **component-script-executor:** + + Used to **execute** a script to perform **NETCONF, RESTCONF, SSH commands** + from within the runtime container of CDS. + + Two type of scripts are supported: + + * Kotlin: offer a way more integrated scripting framework, along + with a way faster processing capability. See more about Kotlin script: https://github.com/Kotlin/KEEP/blob/master/proposals/scripting-support.md + * Python: uses Jython which is bound to Python 2.7, end of life Januray 2020. + See more about Jython: https://www.jython.org/ + + The `script-class-reference` field need to reference + + * for kotlin: the package name up to the class. e.g. com.example.Bob + * for python: it has to be the path from the Scripts folder, e.g. Scripts/python/Bob.py + + `Here `_ + is the definition + + .. _test_test_test: + + .. code-block:: json + :caption: **component-script-executor** + + { + "description": "This is Netconf Transaction Configuration Component API", + "version": "1.0.0", + "interfaces": { + "ComponentScriptExecutor": { + "operations": { + "process": { + "inputs": { + "script-type": { + "description": "Script type, kotlin type is supported", + "required": true, + "type": "string", + "default": "internal", + "constraints": [ + { + "valid_values": [ + "kotlin", + "jython", + "internal" + ] + } + ] + }, + "script-class-reference": { + "description": "Kotlin Script class name with full package or jython script name.", + "required": true, + "type": "string" + }, + "dynamic-properties": { + "description": "Dynamic Json Content or DSL Json reference.", + "required": false, + "type": "json" + } + }, + "outputs": { + "response-data": { + "description": "Execution Response Data in JSON format.", + "required": false, + "type": "string" + }, + "status": { + "description": "Status of the Component Execution ( success or failure )", + "required": true, + "type": "string" + } + } + } + } + } + }, + "derived_from": "tosca.nodes.Component" + } + + .. tab:: remote-script-executor + + **component-remote-script-executor:** + + Used to **execute** a python script in a dedicated micro-service, providing a Python 3.6 environment. + + **Output result:** + + prepare-environment-logs: will contain the logs for all the pip install of ansible_galaxy setup + + execute-command-logs: will contain the execution logs of the script, that were printed into stdout + + Using the get_attribute expression (see :ref:`expression` -> get_attribute), + this attribute can be retrieve to be provided as workflow output (see :ref:`workflow`). + + **Params:** + + The `command` field need to reference the path from the Scripts folder of the + scripts to execute, e.g. Scripts/python/Bob.py + + The `packages` field allow to provide a list of **PIP package** to install in the target environment, + or a requirements.txt file. Also, it supports **Ansible role**. + + If **requirements.txt** is specified, then it should be **provided** as + part of the **Environment** folder of the CBA. + + .. code-block:: json + :caption: **Example** + + "packages": [ + { + "type": "pip", + "package": [ + "requirements.txt" + ] + }, + { + "type": "ansible_galaxy", + "package": [ + "juniper.junos" + ] + } + ] + + The `argument-properties` allows to specified input argument to the script to execute. They should be + expressed in a DSL, and they will be ordered as specified. + + .. code-block:: json + :caption: **Example** + + "ansible-argument-properties": { + "arg0": "-i", + "arg1": "Scripts/ansible/inventory.yaml", + "arg2": "--extra-vars", + "arg3": { + "get_attribute": [ + "resolve-ansible-vars", + "", + "assignment-params", + "ansible-vars" + ] + } + } + } + + The `dynamic-properties` can be anything that needs to be passed to the + script that couldn't be passed as an argument, such as JSON object, etc... If used, they will be passed + in as the last argument of the Python script. + + `Here `_ + is the definition + + .. code-block:: json + :caption: **component-remote-script-executor** + + { + "description": "This is Remote Python Execution Component.", + "version": "1.0.0", + "attributes": { + "prepare-environment-logs": { + "required": false, + "type": "string" + }, + "execute-command-logs": { + "required": false, + "type": "list", + "entry_schema": { + "type": "string" + } + }, + "response-data": { + "required": false, + "type": "json" + } + }, + "capabilities": { + "component-node": { + "type": "tosca.capabilities.Node" + } + }, + "interfaces": { + "ComponentRemotePythonExecutor": { + "operations": { + "process": { + "inputs": { + "endpoint-selector": { + "description": "Remote Container or Server selector name.", + "required": false, + "type": "string", + "default": "remote-python" + }, + "dynamic-properties": { + "description": "Dynamic Json Content or DSL Json reference.", + "required": false, + "type": "json" + }, + "argument-properties": { + "description": "Argument Json Content or DSL Json reference.", + "required": false, + "type": "json" + }, + "command": { + "description": "Command to execute.", + "required": true, + "type": "string" + }, + "packages": { + "description": "Packages to install based on type.", + "required": false, + "type" : "list", + "entry_schema" : { + "type" : "dt-system-packages" + } + } + } + } + } + } + }, + "derived_from": "tosca.nodes.Component" + } + + .. tab:: remote-ansible-executor + + **component-remote-ansible-executor:** + + Used to **execute** an ansible playbook hosted in AWX/Anisble Tower. + + **Ouput result:** + + ansible-command-status: status of the command + + ansible-command-logs: will contain the execution logs of the playbook + + Using the get_attribute expression, this attribute can be retrieve to be provided as workflow output (see Workflow). + + **Param:** + + TBD + + `Here `_ + is the definition + + .. code-block:: json + :caption: **component-remote-script-executor** + + { + "description": "This is Remote Ansible Playbook (AWX) Execution Component.", + "version": "1.0.0", + "attributes": { + "ansible-command-status": { + "required": true, + "type": "string" + }, + "ansible-command-logs": { + "required": true, + "type": "string" + } + }, + "capabilities": { + "component-node": { + "type": "tosca.capabilities.Node" + } + }, + "interfaces": { + "ComponentRemoteAnsibleExecutor": { + "operations": { + "process": { + "inputs": { + "job-template-name": { + "description": "Primary key or name of the job template to launch new job.", + "required": true, + "type": "string" + }, + "limit": { + "description": "Specify host limit for job template to run.", + "required": false, + "type": "string" + }, + "inventory": { + "description": "Specify inventory for job template to run.", + "required": false, + "type": "string" + }, + "extra-vars" : { + "required" : false, + "type" : "json", + "description": "json formatted text that contains extra variables to pass on." + }, + "tags": { + "description": "Specify tagged actions in the playbook to run.", + "required": false, + "type": "string" + }, + "skip-tags": { + "description": "Specify tagged actions in the playbook to omit.", + "required": false, + "type": "string" + }, + "endpoint-selector": { + "description": "Remote AWX Server selector name.", + "required": true, + "type": "string" + } + } + } + } + } + }, + "derived_from": "tosca.nodes.Component" + } + + .. tab:: Source + + **Source:** + + Used to represent a **type of source** to **resolve** a **resource**, along with the expected **properties** + + Defines the **contract** to resolve a resource. + + `Here `_ + is the root component TOSCA node type from which other node type will derive: + + .. code-block:: + :caption: **tosca.nodes.Component** + + { + "description": "TOSCA base type for Resource Sources", + "version": "1.0.0", + "derived_from": "tosca.nodes.Root" + } + + **Bellow is a list of supported sources** + + .. tabs:: + .. tab:: input + + **Input:** + + Expects the **value to be provided as input** to the request. + + `Here `_ + is the Definition + + .. code-block:: + :caption: **source-input** + + { + "description": "This is Input Resource Source Node Type", + "version": "1.0.0", + "properties": {}, + "derived_from": "tosca.nodes.ResourceSource" + } + + .. tab:: default + + **Default:** + + Expects the **value to be defaulted** in the model itself. + + `Here `_ + is the Definition + + .. code-block:: json + :caption: **source-default** + + { + "description": "This is Default Resource Source Node Type", + "version": "1.0.0", + "properties": {}, + "derived_from": "tosca.nodes.ResourceSource" + } + + .. tab:: rest + + **REST** + + Expects the **URI along with the VERB and the payload**, if needed. + + CDS is currently deployed along the side of SDNC, hence the **default** rest + **connection** provided by the framework is to **SDNC MDSAL**. + + .. list-table:: + :widths: 25 50 25 + :header-rows: 1 + + * - Property + - Description + - Scope + * - type + - Expected output value, only JSON supported for now + - Optional + * - verb + - HTTP verb for the request - default value is GET + - Optional + * - payload + - Payload to sent + - Optional + * - endpoint-selector + - **Specific REST system** to interact with to (see **Dynamic Endpoint**) + - Optional + * - url-path + - URI + - Mandatory + * - path + - JSON path to the value to fetch from the response + - Mandatory + * - expression-type + - Path expression type - default value is JSON_PATH + - Optional + + `Here `_ + is the definition: + + .. code-block:: json + :caption: **source-rest** + + { + "description": "This is Rest Resource Source Node Type", + "version": "1.0.0", + "properties": { + "type": { + "required": false, + "type": "string", + "default": "JSON", + "constraints": [ + { + "valid_values": [ + "JSON" + ] + } + ] + }, + "verb": { + "required": false, + "type": "string", + "default": "GET", + "constraints": [ + { + "valid_values": [ + "GET", "POST", "DELETE", "PUT" + ] + } + ] + }, + "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", + "default": "JSON_PATH", + "constraints": [ + { + "valid_values": [ + "JSON_PATH", + "JSON_POINTER" + ] + } + ] + }, + "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" + } + + .. tab:: sql + + **SQL** + + Expects the **SQL query** to be modeled; that SQL query can be parameterized, + and the parameters be other resources resolved through other means. + If that's the case, this data dictionary definition will have to define ``key-dependencies`` along with ``input-key-mapping``. + + CDS is currently deployed along the side of SDNC, hence the **primary** database + **connection** provided by the framework is to **SDNC database**. + + .. list-table:: + :widths: 25 50 25 + + * - Property + - Description + - Scope + * - type + - Database type, only SQL supported for now + - Mandatory + * - endpoint-selector + - Specific Database system to interact with to (see **Dynamic Endpoint**) + - Optional + * - query + - Statement to execute + - Mandatory + + + `Here `_ + is the definition: + + .. code-block:: json + :caption: **source-db** + + { + "description": "This is Database Resource Source Node Type", + "version": "1.0.0", + "properties": { + "type": { + "required": true, + "type": "string", + "constraints": [ + { + "valid_values": [ + "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" + } + + .. tab:: capability + + **Capability:** + + Expects a **script** to be provided. + + .. list-table:: + :widths: 25 50 25 + :header-rows: 1 + + * - Property + - Description + - Scope + * - script-type + - The type of the script - default value is Koltin + - Optional + * - script-class-reference + - The name of the class to use to create an instance of the script + - Mandatory + + `Here `_ + is the definition: + + .. code-block:: json + :caption: **source-capability** + + { + "description": "This is Component Resource Source Node Type", + "version": "1.0.0", + "properties": { + "script-type": { + "required": true, + "type": "string", + "default": "kotlin", + "constraints": [ + { + "valid_values": [ + "internal", + "kotlin", + "jython" + ] + } + ] + }, + "script-class-reference": { + "description": "Capability reference name for internal and kotlin, for jython script file path", + "required": true, + "type": "string" + }, + "key-dependencies": { + "description": "Resource Resolution dependency dictionary names.", + "required": true, + "type": "list", + "entry_schema": { + "type": "string" + } + } + }, + "derived_from": "tosca.nodes.ResourceSource" + } + + .. tab:: Other + + **Other:** + + .. tabs:: + + .. tab:: DG + + **dg-generic:** + + Identifies a Directed Graph used as **imperative workflow**. + + .. list-table:: + :widths: 40 40 20 + :header-rows: 1 + + * - Property + - Description + - Scope + * - dependency-node-templates + - The node template the workflow depends on + - Required + + `Here `_ + is the definition: + + .. code-block:: json + :caption: **dg-generic** + + { + "description": "This is Generic Directed Graph Type", + "version": "1.0.0", + "properties": { + "content": { + "required": true, + "type": "string" + }, + "dependency-node-templates": { + "required": true, + "description": "Dependent Step Components NodeTemplate name.", + "type": "list", + "entry_schema": { + "type": "string" + } + } + }, + "derived_from": "tosca.nodes.DG" + } + + A node_template of this type always provide one artifact, of type artifact-directed-graph, + which will be located under the Plans/ folder within the CBA. + + .. code-block:: json + :caption: **node_template example** + + "config-deploy-process" : { + "type" : "dg-generic", + "properties" : { + "content" : { + "get_artifact" : [ "SELF", "dg-config-deploy-process" ] + }, + "dependency-node-templates" : [ "nf-account-collection", "execute" ] + }, + "artifacts" : { + "dg-config-deploy-process" : { + "type" : "artifact-directed-graph", + "file" : "Plans/CONFIG_ConfigDeploy.xml" + } + } + } + + In the DG bellow, the execute node refers to the node_template. + + .. code-block:: xml + :caption: **Plans/CONFIG_ConfigDeploy.xml** + + + + + + + + + + + + + + + + + + + + + + + + + + + .. tab:: VNF + + **tosca.nodes.VNF** + + Identifies a VNF, can be used to **correlate** any type of **VNF** related **information**. + + https://github.com/onap/ccsdk-cds/blob/master/components/model-catalog/definition-type/starter-type/node_type/tosca.nodes.Vnf.json + + .. code-block:: json + :caption: **tosca.nodes.vnf** + + { + "description": "This is VNF Node Type", + "version": "1.0.0", + "derived_from": "tosca.nodes.Root" + } + + **vnf-netconf-device** + + Represents the VNF information to **establish** a **NETCONF communication**. + + https://github.com/onap/ccsdk-cds/blob/master/components/model-catalog/definition-type/starter-type/node_type/vnf-netconf-device.json + + .. code-block:: json + :caption: **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 + } + } + } + }, + "derived_from": "tosca.nodes.Vnf" + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/modelingconcepts/overview.rst b/docs/modelingconcepts/overview.rst new file mode 100644 index 000000000..80ce8c6c9 --- /dev/null +++ b/docs/modelingconcepts/overview.rst @@ -0,0 +1,48 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +Modeling Concepts +================== + +CDS is a framework to automate the **resolution of resources** for +**instantiation** and any **config** provisioning operation, such as +day0, day1 or day2 configuration. + +CDS has a both **design time** and **run time** activities; during +design time, **Designer** can **define** what **actions** are required +for a given service, along with anything comprising the action. The +design produce a :ref:`CBA Package`. Its **content** is driven from a +**catalog** of **reusable data dictionary** and **component**, +delivering a reusable and simplified **self service** experience. + +DS modelling is mainly based on `TOSCA +standard, `_ +using JSON as reprensentation. + +Most of the TOSCA modeled entity presented in the bellow documentation +can be found +`here `_. + +.. toctree:: + :caption: Table of Contents + :maxdepth: 1 + + CBA + Tosca.Meta + dynamic-payload + enrichment + Flexible Plug-in + expression + data-dictionary + data-type + artifact-type + node-type + workflow + template + scripts + southbound-interfaces + test + + diff --git a/docs/modelingconcepts/scripts.rst b/docs/modelingconcepts/scripts.rst new file mode 100644 index 000000000..eb1cbd7bc --- /dev/null +++ b/docs/modelingconcepts/scripts.rst @@ -0,0 +1,27 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts#Concepts-703799064 by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +Scripts +------------- + +Library ++++++++++++++++++ + +NetconfClient ++++++++++++++++++ + +In order to facilitate NETCONF interaction within scripts, a python NetconfClient binded to our Kotlin implementation is made available. +This NetconfClient can be used when using the component-netconf-executor. + +The client can be find here: https://github.com/onap/ccsdk-cds/blob/master/components/scripts/python/ccsdk_netconf/netconfclient.py + +ResolutionHelper ++++++++++++++++++ + +When executing a component executor script, designer might want to perform +resource resolution along with template meshing directly from the script itself. + +The helper can be find here: +https://github.com/onap/ccsdk-cds/blob/master/components/scripts/python/ccsdk_netconf/common.py \ No newline at end of file diff --git a/docs/modelingconcepts/southbound-interfaces.rst b/docs/modelingconcepts/southbound-interfaces.rst new file mode 100644 index 000000000..53d700750 --- /dev/null +++ b/docs/modelingconcepts/southbound-interfaces.rst @@ -0,0 +1,23 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts#Concepts-384293385 by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +Southbound Interfaces +------------------------- + +CDS comes with native python 3.6 support and Ansible AWX (Ansible Tower): +idea is Network Ops are familiar with Python and/or Ansible, and our goal is not to dictate the SBI to use for +their operations. Ansible and Python provide already many, and well adopted, +SBI libraries, hence they could be utilized as needed. + +CDS also provide native support for the following libraries: + +* NetConf +* REST +* CLI +* SSH +* gRPC (hence gNMI / gNOI should be supported) + +CDS also has extensible REST support, meaning any RESTful interface used for network interaction can be used, +such as external VNFM or EMS. \ No newline at end of file diff --git a/docs/modelingconcepts/template.rst b/docs/modelingconcepts/template.rst new file mode 100644 index 000000000..951b51b6c --- /dev/null +++ b/docs/modelingconcepts/template.rst @@ -0,0 +1,23 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts#Concepts-1256902502 by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +.. _template: + +Template +----------- + +A template is an **artifact**, and uses artifact-mapping-resource (see :ref:`artifact_type` -> Mapping) +and artifact-template-velocity (see :ref:`artifact_type` -> Velocity). + +A template is **parameterized** and each parameter must be defined in a corresponding **mapping file**. + +In order to know which mapping correlates to which template, the file name must start with an ``artifact-prefix``, +serving as identifier to the overall template + mapping. + +The **requirement** is as follows: + +``${artifact-prefix}-template`` + +``${artifact-prefix}-mapping`` \ No newline at end of file diff --git a/docs/modelingconcepts/test.rst b/docs/modelingconcepts/test.rst new file mode 100644 index 000000000..89003e0dc --- /dev/null +++ b/docs/modelingconcepts/test.rst @@ -0,0 +1,40 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts#Concepts-2603186 by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +Tests +-------- + +The **tests** folder contains the **uat.yaml** file for execution the cba actions for sunny day and rainy day +scenario using mock data. The process to generate the uat file is documented TBD. The file can be dragged +and drop to the Tests folder after the test for all actions are executed. + +NOTE: You need to activate the "uat" Spring Boot profile in order to enable the spy/verify endpoints. +They are disabled by default because the mocks created at runtime can potentially cause collateral problems in production. +You can either pass an option to JVM (``-Dspring.profiles.active=uat``) or set and export an +environment variable (``export spring_profiles_active=uat``). + +A quick outline of the UAT generation process follows: + +1. Create a minimum :file:`uat.yaml` containing only the NB requests to be sent to the BlueprintsProcessor (BPP) service; +2. Submit the blueprint CBA and this draft :file:`uat.yaml` to BPP in a single HTTP POST call: + + ``curl -u ccsdkapps:ccsdkapps -F cba=@ -F uat=@ http://localhost:8080/api/v1/uat/spy`` +3. If your environment is properly setup, at the end this service will generate the complete :file:`uat.yaml`; +4. Revise the generate file, eventually removing superfluous message fields; +5. Include this file in your CBA under :file:`Tests/uat.yaml`; +6. Submit the candidate CBA + UAT to be validated by BPP, that now will create runtime mocks to simulate + all SB collaborators, by running: + + ``$ curl -u ccsdkapps:ccsdkapps -F cba=@ http://localhost:8080/api/v1/uat/verify`` +7. Once validated, your CBA enhanced with its corresponding UAT is eligible + to be integrated into the CDS project, under the folder :file:`components/model-catalog/blueprint-model/uat-blueprints`. + +Reference link for sample generated uat.yaml file for pnf plug & play use case: +`uat.yaml file `_. + +As UAT is part of unit testing, it runs in jenkins job +`ccsdk-cds-master-verify-java `_ +whenever a new commit/patch pushed on gerrit in ccsdk/cds repo. \ No newline at end of file diff --git a/docs/modelingconcepts/tosca-meta.rst b/docs/modelingconcepts/tosca-meta.rst new file mode 100644 index 000000000..f4fed1479 --- /dev/null +++ b/docs/modelingconcepts/tosca-meta.rst @@ -0,0 +1,80 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +Tosca Meta +------------ + +Tosca meta file captures the model entities that compose the cba package name, version, type and searchable tags. + +.. list-table:: + :widths: 20 15 15 50 + :header-rows: 1 + + * - Attribute + - R/C/O + - Data Type + - Description + * - TOSCA-Meta-File-Version + - Required + - String + - The attribute that holds TOSCA-Meta-File-Version. Set to 1.0.0 + * - CSAR-Version + - Required + - String + - The attribute that holds CSAR-version. Set to 1.0 + * - Created-By + - Required + - String + - The attribute that holds the entry points + * - Entry-Definitions + - Required + - String + - The attribute that holds the entry points file PATH to the main cba tosca definition file + or non tosca script file. + * - Template-Name + - Required + - String + - The attribute that holds the blueprint name + * - Template-Version + - Required + - String + - | The attribute that holds the blueprint version + | + | X.Y.Z + | + | X=Major version + | Y=Minor Version + | Z=Revision Version + | + | X=Ex. 1.0.0 + * - Template-Type + - Required + - String + - | The attribute that holds the blueprint package types. + | Valid Options: + * "DEFAULT" – .JSON file consistent of tosca based cba package that describes the package intent. + * "KOTLIN_DSL" – .KT file consistent of tosca based cba package that describes the package intent + composed using Domain Specific Language (DSL). + * "GENERIC_SCRIPT" – Script file consistent of NONE tosca based cba package that describes the package intent + using DSL Language. + | If not specified in the tosca.meta file the default is "DEFAULT" + * - Template-Tags + - Required + - String + - The attribute that holds the blueprint package comma delimited list of Searchable attributes. + +**Template Type Reference** + +**Default Template Type** + +https://gerrit.onap.org/r/gitweb?p=ccsdk/cds.git;a=blob;f=components/model-catalog/blueprint-model/test-blueprint/capability_cli/TOSCA-Metadata/TOSCA.meta;hb=refs/heads/master + +**KOTLIN_DSL Template Type** + +https://gerrit.onap.org/r/gitweb?p=ccsdk/cds.git;a=blob;f=components/model-catalog/blueprint-model/test-blueprint/resource-audit/TOSCA-Metadata/TOSCA.meta;hb=refs/heads/master + +**GENERIC_SCRIPT Template Type** + +https://gerrit.onap.org/r/gitweb?p=ccsdk/cds.git;a=tree;f=ms/py-executor/test/resources/sample-cba/1.0.0;hb=refs/heads/master \ No newline at end of file diff --git a/docs/modelingconcepts/workflow.rst b/docs/modelingconcepts/workflow.rst new file mode 100644 index 000000000..d9c7dc956 --- /dev/null +++ b/docs/modelingconcepts/workflow.rst @@ -0,0 +1,322 @@ +.. This work is a derivative of https://wiki.onap.org/display/DW/Modeling+Concepts#Concepts-100023263 by IBM +.. used under Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright (C) 2020 Deutsche Telekom AG. + +.. _workflow: + +Workflow +--------- + +.. note:: + + **Workflow Scope within CDS Framework** + + The workflow is within the scope of the micro provisioning and configuration + management in **controller domain** and does NOT account for the MACRO service orchestration workflow which is covered by the SO Project. + +A workflow defines an overall action to be taken on the service, hence is an +entry-point for the run-time execution of the :ref:`CBA Package `. + +A workflow also defines **inputs** and **outputs** that will defined the **payload contract** +of the **request** and **response** (see :ref:`Dynamic API`) + +A workflow can be **composed** of one or multiple **sub-actions** to execute. + +A CBA package can have as **many workflows** as needed. + +.. _workflow_single_action: + +Single action +************** + +The workflow is directly backed by a component (see :ref:`node_type` -> Component). + +In the example bellow, the target of the workflow's steps resource-assignment is ``resource-assignment`` +which actually is the name of the ``node_template`` defined after, of type ``component-resource-resolution``. + +`Link to example +`_ + + +.. code-block:: json + :caption: **Example** + + . . . + "topology_template": { + "workflows": { + "resource-assignment": { + "steps": { + "resource-assignment": { + "description": "Resource Assign Workflow", + "target": "resource-assignment" + ] + } + }, + "inputs": { + "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" + ] + } + } + } + }, + "node_templates": { + "resource-assignment": { + "type": "component-resource-resolution", + "interfaces": { + "ResourceResolutionComponent": { + "operations": { + "process": { + "inputs": { + "artifact-prefix-names": [ + "vf-module-1" + ] + } + } + } + } + }, + "artifacts": { + "vf-module-1-template": { + "type": "artifact-template-velocity", + "file": "Templates/vf-module-1-template.vtl" + }, + "vf-module-1-mapping": { + "type": "artifact-mapping-resource", + "file": "Templates/vf-module-1-mapping.json" + } + } + } + } + . . . + +.. _workflow_multiple_actions: + +Multiple sub-actions +********************** + +The workflow is backed by a Directed Graph engine, dg-generic (see :ref:`node_type` -> DG, +and is an **imperative** workflow. + +A DG used as workflow for CDS is composed of multiple execute nodes; each individual +execute node refers to an modelled Component (see :ref:`node_type` -> Component) instance. + +In the example above, you can see the target of the workflow's steps execute-script is +``execute-remote-ansible-process``, which is a node_template of type ``dg_generic`` + +`Link of example +`_ + +.. code-block:: json + :caption: **workflow plan example** + + . . . + "topology_template": { + "workflows": { + "execute-remote-ansible": { + "steps": { + "execute-script": { + "description": "Execute Remote Ansible Script", + "target": "execute-remote-ansible-process" + ] + } + }, + "inputs": { + "ip": { + "required": false, + "type": "string" + }, + "username": { + "required": false, + "type": "string" + }, + "password": { + "required": false, + "type": "string" + }, + "execute-remote-ansible-properties": { + "description": "Dynamic PropertyDefinition for workflow(execute-remote-ansible).", + "required": true, + "type": "dt-execute-remote-ansible-properties" + } + }, + "outputs": { + "ansible-variable-resolution": { + "type": "json", + "value": { + "get_attribute": [ + "resolve-ansible-vars", + "assignment-params" + ] + } + }, + "prepare-environment-logs": { + "type": "string", + "value": { + "get_attribute": [ + "execute-remote-ansible", + "prepare-environment-logs" + ] + } + }, + "execute-command-logs": { + "type": "string", + "value": { + "get_attribute": [ + "execute-remote-ansible", + "execute-command-logs" + ] + } + } + } + } + }, + "node_templates": { + "execute-remote-ansible-process": { + "type": "dg-generic", + "properties": { + "content": { + "get_artifact": [ + "SELF", + "dg-execute-remote-ansible-process" + ] + }, + "dependency-node-templates": [ + "resolve-ansible-vars", + "execute-remote-ansible" + ] + }, + "artifacts": { + "dg-execute-remote-ansible-process": { + "type": "artifact-directed-graph", + "file": "Plans/CONFIG_ExecAnsiblePlaybook.xml" + } + } + } + +Properties of a workflow +************************** + +.. list-table:: + :widths: 25 75 + :header-rows: 1 + + * - Property + - Description + * - workflow-name + - Defines the name of the action that can be triggered by external system + * - inputs + - | They are two types of inputs, the dynamic ones, and the static one. + | + + .. tabs:: + + .. tab:: static + + Specified at workflow level + + * can be inputs for the Component(s), see the inputs section of the component of interest. + * represent inputs to derived custom logic within scripting + + These will end up under ``${actionName}-request`` section of the payload (see Dynamic API) + + .. tab:: dynamic + + Represent the resources defined as input (see :ref:`node_type` -> Source -> Input) + within mapping definition files (see :ref:`artifact_type` -> Mapping). + + The **enrichment process** will (see :ref:`enrichment`) + + * dynamically gather all of them under a data-type, named ``dt-${actionName}-properties`` + * will add it as a input of the workflow, as follow using this name: ``${actionName}-properties`` + + Example for workflow named `resource-assignment`: + + .. code-block:: json + :caption: **dynamic input** + + "resource-assignment-properties": { + "required": true, + "type": "dt-resource-assignment-properties" + } + * - outputs + - | Defines the outputs of the execution; there can be as many output as needed. + | Depending on the Component (see :ref:`node_type` -> Component) of use, some attribute might be retrievable. + + .. list-table:: + :widths: 50 50 + :header-rows: 1 + + * - type + - value + * - data type (complex / primitive) + - value resolvable using :ref:`expression` -> get_attribute + * - steps + - | Defines the actual step to execute as part of the workflow + | + .. list-table:: + :widths: 25 25 50 + :header-rows: 1 + + * - step-name + - description + - target + * - name of the step + - step description + - | a node_template implementing on of the supported Node Type (see :ref:`node_type` -> DG), + either a Component or a DG + | (see :ref:`workflow_single_action` or :ref:`workflow_multiple_actions`) + +Example: + +.. code-block:: json + :caption: **workflow example** + + { + "workflow": { + "resource-assignment": { <- workflow-name + "inputs": { + "vnf-id": { <- static inputs + "required": true, + "type": "string" + }, + "resource-assignment-properties": { <- dynamic inputs + "required": true, + "type": "dt-resource-assignment-properties" + } + }, + "steps": { + "call-resource-assignment": { <- step-name + "description": "Resource Assignment Workflow", + "target": "resource-assignment-process" <- node_template targeted by the step + } + }, + "outputs": { + "template-properties": { <- output + "type": "json", <- complex type + "value": { + "get_attribute": [ <- uses expression to retrieve attribute from context + "resource-assignment", + "assignment-params" + ] + } + } + } + } + } + } + +`TOSCA definition `_ + -- 2.16.6