Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.


DRAFT

Table of Contents

Introduction

...

rApp package rapp-hello-world.csar generated.


ACM Compositions for Kubernetes Deployment

To construct a seamless ACM topology for Kubernetes (k8s), it is imperative to adhere to a comprehensive TOSCA definition that encapsulates essential elements.

ACM Definition Overview

The following code snippets provide a foundational framework, encompassing data types, node types, and specific configurations necessary for a robust ACM deployment:

Code Block
languageyml
{
  "tosca_definitions_version": "tosca_simple_yaml_1_3",
  "data_types": {
    "onap.datatypes.ToscaConceptIdentifier": {
      "derived_from": "tosca.datatypes.Root",
      "properties": {
        "name": {
          "type": "string",
          "required": true
        },
        "version": {
          "type": "string",
          "required": true
        }
      }
    }
  },
  "node_types": {
    "org.onap.policy.clamp.acm.Participant": {
      "version": "1.0.1",
      "derived_from": "tosca.nodetypes.Root",
      "properties": {
        "provider": {
          "type": "string",
          "required": false
        }
      }
    },
    "org.onap.policy.clamp.acm.AutomationCompositionElement": {
      "version": "1.0.1",
      "derived_from": "tosca.nodetypes.Root",
      "properties": {
        "provider": {
          "type": "string",
          "required": false
        },
        "participantType": {
          "type": "onap.datatypes.ToscaConceptIdentifier",
          "required": true
        },
        "startPhase": {
          "type": "integer",
          "required": false,
          "constraints": [
            {
              "greater-or-equal": 0
            }
          ],
          "metadata": {
            "common": true
          },
          "description": "A value indicating the start phase in which this automation composition element will be started, the first start phase is zero. Automation Composition Elements are started in their start_phase order and stopped in reverse start phase order. Automation Composition Elements with the same start phase are started and stopped simultaneously"
        },
        "passiveToRunningTimeout": {
          "type": "integer",
          "required": false,
          "constraints": [
            {
              "greater_or_equal": 0
            }
          ],
          "default": 60,
          "metadata": {
            "common": true
          },
          "description": "The maximum time in seconds to wait for a state chage from passive to running"
        },
        "runningToPassiveTimeout": {
          "type": "integer",
          "required": false,
          "constraints": [
            {
              "greater_or_equal": 0
            }
          ],
          "default": 60,
          "metadata": {
            "common": true
          },
          "description": "The maximum time in seconds to wait for a state chage from running to passive"
        },
        "passiveToUninitializedTimeout": {
          "type": "integer",
          "required": false,
          "constraints": [
            {
              "greater_or_equal": 0
            }
          ],
          "default": 60,
          "metadata": {
            "common": true
          },
          "description": "The maximum time in seconds to wait for a state chage from passive to uninitialized"
        }
      }
    },
    "org.onap.policy.clamp.acm.AutomationComposition": {
      "version": "1.0.1",
      "derived_from": "tosca.nodetypes.Root",
      "properties": {
        "provider": {
          "type": "string",
          "required": false,
          "metadata": {
            "common": true
          }
        },
        "elements": {
          "type": "list",
          "required": true,
          "metadata": {
            "common": true
          },
          "entry_schema": {
            "type": "onap.datatypes.ToscaConceptIdentifier"
          }
        }
      }
    },
    "org.onap.policy.clamp.acm.K8SMicroserviceAutomationCompositionElement": {
      "version": "1.0.0",
      "derived_from": "org.onap.policy.clamp.acm.AutomationCompositionElement",
      "properties": {
        "chart": {
          "type": "string",
          "required": true
        },
        "configs": {
          "type": "list",
          "required": false
        },
        "requirements": {
          "type": "string",
          "required": false
        },
        "templates": {
          "type": "list",
          "required": false,
          "entry_schema": null
        },
        "values": {
          "type": "string",
          "required": true
        }
      }
    }
  },
  "topology_template": {
    "node_templates": {
      "org.onap.k8s.acm.K8SAutomationCompositionParticipant": {
        "version": "2.3.4",
        "type": "org.onap.policy.clamp.acm.Participant",
        "type_version": "1.0.1",
        "description": "Participant for K8S",
        "properties": {
          "provider": "ONAP"
        }
      },
      "onap.policy.clamp.ac.element.K8S_StarterAutomationCompositionElement": {
        "version": "1.2.3",
        "type": "org.onap.policy.clamp.acm.K8SMicroserviceAutomationCompositionElement",
        "type_version": "1.0.0",
        "description": "Automation composition element for the K8S microservice for AC Element Starter",
        "properties": {
          "provider": "ONAP",
          "startPhase": 0,
          "uninitializedToPassiveTimeout": 300,
          "podStatusCheckInterval": 30
        }
      },
      "onap.policy.clamp.ac.element.AutomationCompositionDefinition": {
        "version": "1.2.3",
        "type": "org.onap.policy.clamp.acm.AutomationComposition",
        "type_version": "1.0.1",
        "description": "Automation composition for rapp deployment",
        "properties": {
          "provider": "ONAP",
          "elements": [
            {
              "name": "onap.policy.clamp.ac.element.K8S_StarterAutomationCompositionElement",
              "version": "1.2.3"
            }
          ]
        }
      }
    }
  }
}


The provided ACM TOSCA definition includes key elements necessary for defining an ACM topology for Kubernetes (k8s). However, to avoid errors, ensure that the definitions are complete and correctly referenced.

Required Definitions

The ACM TOSCA definition includes key data types and node types such as ToscaConceptIdentifier, Participant, AutomationCompositionElement, AutomationComposition, and K8SMicroserviceAutomationCompositionElement. These definitions represent building blocks for ACM topologies, specifically for Kubernetes deployments.

  1. ToscaConceptIdentifier:

    • Properties: name and version.
  2. Participant:

    • Properties: provider (optional).
  3. AutomationCompositionElement:

    • Properties: provider (optional), participantType (referencing ToscaConceptIdentifier), and additional timing-related properties.
  4. AutomationComposition:

    • Properties: provider (optional), elements (list of ToscaConceptIdentifier).
  5. K8SMicroserviceAutomationCompositionElement:

    • Derived from AutomationCompositionElement.
    • Properties: chart, configs, requirements, templates, and values.
  6. Topology Template:

    • Node Templates for relevant ACM entities.

Reference Flow

  1. Participant Definition:

    • Ensure that Participant definitions are referenced correctly in node templates.
  2. Automation Composition Element:

    • Use AutomationCompositionElement in the node templates and ensure correct referencing of the ToscaConceptIdentifier for participantType.
  3. Automation Composition:

    • Reference the correct AutomationCompositionElement in the AutomationComposition definition.
  4. K8S Microservice Automation Composition Element:

    • Ensure that the K8SMicroserviceAutomationCompositionElement is used for Kubernetes-specific compositions.
  5. Top-Level Node Templates:

    • Node templates like K8SAutomationCompositionParticipant and others should reference the appropriate definitions.

Errors and Debugging

When utilizing the provided ACM TOSCA definition for Kubernetes (k8s), it is essential to include all key elements to define the ACM topology accurately. Failure to incorporate required definitions may lead to errors during the deployment process. Common indicators of missing components include repeated YAML separator lines (---) and unexpected empty sections. To illustrate, if the definitions for org.onap.policy.clamp.acm.AutomationCompositionElement or org.onap.policy.clamp.acm.Participant are absent, errors such as NullPointerException or unexpected behavior during deployment might occur. Therefore, it is crucial to thoroughly review and complete the TOSCA definition, ensuring all necessary components are correctly specified to avoid potential issues.

  • If errors occur, check the console logs for NullPointerExceptions or missing property issues.
  • The error may indicate missing references or incorrect properties in the TOSCA definitions.
  • Ensure that all referenced elements (e.g., ToscaConceptIdentifier, Participant, etc.) are correctly defined and referenced.

For instance, if the definitions for org.onap.policy.clamp.acm.AutomationCompositionElement or org.onap.policy.clamp.acm.Participant are absent, errors such as NullPointerException or unexpected behavior during deployment might occur.

Code Block
languagejava
java.lang.NullPointerException: Cannot invoke "org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate.getProperties()" because the return value of "java.util.Map.get(Object)" is null
        at com.oransc.rappmanager.models.AcmInterceptor.injectToscaServiceTemplate(AcmInterceptor.java:57) ~[rapp-manager-models-0.1.0-SNAPSHOT.jar!/:0.1.0-SNAPSHOT]
        at com.oransc.rappmanager.dme.service.DmeAcmInterceptor.injectToscaServiceTemplate(DmeAcmInterceptor.java:68) ~[rapp-manager-dme-0.1.0-SNAPSHOT.jar!/:0.1.0-SNAPSHOT]
        at com.oransc.rappmanager.acm.service.AcmDeployer.createComposition(AcmDeployer.java:85) ~[rapp-manager-acm-0.1.0-SNAPSHOT.jar!/:0.1.0-SNAPSHOT]
        at com.oransc.rappmanager.acm.service.AcmDeployer.primeRapp(AcmDeployer.java:187) ~[rapp-manager-acm-0.1.0-SNAPSHOT.jar!/:0.1.0-SNAPSHOT]
        at com.oransc.rappmanager.service.RappService.lambda$primeRapp$0(RappService.java:53) ~[!/:0.1.0-SNAPSHOT]
        at java.base/java.util.stream.MatchOps$1MatchSink.accept(Unknown Source) ~[na:na]
        at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(Unknown Source) ~[na:na]
        at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(Unknown Source) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(Unknown Source) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source) ~[na:na]
        at java.base/java.util.stream.MatchOps$MatchTask.doLeaf(Unknown Source) ~[na:na]
        at java.base/java.util.stream.MatchOps$MatchTask.doLeaf(Unknown Source) ~[na:na]
        at java.base/java.util.stream.AbstractShortCircuitTask.compute(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.CountedCompleter.exec(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.ForkJoinTask.doExec(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.ForkJoinPool.scan(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.ForkJoinPool.runWorker(Unknown Source) ~[na:na]
        at java.base/java.util.concurrent.ForkJoinWorkerThread.run(Unknown Source) ~[na:na] 


Code Block
languagejava
java.lang.NullPointerException: Cannot invoke "org.onap.policy.clamp.models.acm.concepts.AutomationComposition.getElements()" because "automationComposition" is null
        at com.oransc.rappmanager.models.AcmInterceptor.injectAutomationComposition(AcmInterceptor.java:84) ~[rapp-manager-models-0.0.1.jar!/:0.0.1]
        at com.oransc.rappmanager.acm.service.AcmDeployer.deployRappInstance(AcmDeployer.java:141) ~[rapp-manager-acm-0.0.1.jar!/:0.0.1]
        at com.oransc.rappmanager.service.RappService.deployRappInstance(RappService.java:106) ~[!/:0.0.1]
        at com.oransc.rappmanager.rest.RappInstanceController.lambda$deployRappInstance$10(RappInstanceController.java:95) ~[!/:0.0.1]
        at java.base/java.util.Optional.map(Unknown Source) ~[na:na]
        at com.oransc.rappmanager.rest.RappInstanceController.lambda$deployRappInstance$12(RappInstanceController.java:95) ~[!/:0.0.1]
        at java.base/java.util.Optional.map(Unknown Source) ~[na:na]
        at com.oransc.rappmanager.rest.RappInstanceController.deployRappInstance(RappInstanceController.java:93) ~[!/:0.0.1]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na]


ACM Instance for Kubernetes Deployment

The following example showcases an ACM instance designed for Kubernetes deployment:

Code Block
languagetext
{
  "name": "DemoInstance0",
  "version": "1.0.1",
  "compositionId": "COMPOSITIONID",
  "description": "Demo automation composition instance 0",
  "elements": {
    "709c62b3-8918-41b9-a747-d21eb79c6c21": {
      "id": "709c62b3-8918-41b9-a747-d21eb79c6c21",
      "definition": {
        "name": "onap.policy.clamp.ac.element.K8S_StarterAutomationCompositionElement",
        "version": "1.2.3"
      },
      "description": "Starter Automation Composition Element for the Hello World",
      "properties": {
        "chart": {
          "chartId": {
            "name": "hello-world-chart",
            "version": "0.1.0"
          },
          "namespace": "nonrtric",
          "releaseName": "hello-world-chart",
          "podName": "hello-world-chart",
          "repository": {
            "repoName": "local",
            "address": "http://10.101.1.90:8879/charts"
          }
        }
      }
    }
  }
}


In this instance, "DemoInstance0" is specified with a version of "1.0.1," associated with a composition ID "COMPOSITIONID," and described as a demo automation composition. The instance contains a single element with the ID "709c62b3-8918-41b9-a747-d21eb79c6c21." This element is defined as the "K8S_StarterAutomationCompositionElement" with version "1.2.3." It represents the starter automation composition element for the Hello World service.

The element's properties include a reference to the Helm chart named "hello-world-chart" with version "0.1.0." The chart is intended for deployment in the "nonrtric" namespace with a release name, pod name, and repository details pointing to the local repository at "http://10.101.1.90:8879/charts."

This structured representation provides a clear overview of the ACM instance designed for deploying the Hello World service on Kubernetes.


SME service exposure for "Hello World" REST endpoints

To expose "Hello World" microservice endpoints through the Service Management and Exposure (SME), you need to create SME configurations and package them within the same rApp package that contains the Kubernetes participant.

SME Configuration Structure

The SME configuration consists of three directories: providers, serviceapis, and invokers, each containing specific JSON files.

providers/provider-function-1.json

Code Block
languagetext
{
  "apiProvDomInfo": "Provider domain",
  "apiProvFuncs": [
    {
      "apiProvFuncInfo": "Hello World as APF",
      "apiProvFuncRole": "APF",
      "regInfo": {
        "apiProvPubKey": "APF-PublicKey"
      }
    },
    {
      "apiProvFuncInfo": "Hello World as AEF",
      "apiProvFuncRole": "AEF",
      "regInfo": {
        "apiProvPubKey": "AEF-PublicKey"
      }
    }
  ],
  "regSec": "PSK"
}


serviceapis/api-set-1.json


Code Block
languagetext
{
  "apiName": "Hello World API Set 1",
  "description": "Simple Hello World API",
  "aefProfiles": [
    {
      "aefId": "Hello World as AEF",
      "description": "Simple Hello World API",
      "versions": [
        {
          "apiVersion": "v1",
          "resources": [
            {
              "resourceName": "helloworld",
              "commType": "REQUEST_RESPONSE",
              "uri": "/helloworld/v1",
              "operations": [
                "GET"
              ]
            }
          ]
        }
      ],
      "protocol": "HTTP_1_1",
      "securityMethods": [
        "PSK"
      ],
      "interfaceDescriptions": [
        {
          "ipv4Addr": "string",
          "port": 30951,
          "securityMethods": [
            "PKI"
          ]
        },
        {
          "ipv4Addr": "string",
          "port": 30951,
          "securityMethods": [
            "PKI"
          ]
        }
      ]
    }
  ]
}


invokers/invoker-app1.json


Code Block
languagetext
[
  {
    "apiInvokerInformation": "Invoker App 1",
    "apiList": [
      {}
    ],
    "notificationDestination": "http://invoker-app1:8086/callback",
    "onboardingInformation": {
      "apiInvokerPublicKey": "{PUBLIC_KEY_INVOKER_1}",
      "apiInvokerCertificate": "apiInvokerCertificate"
    },
    "requestTestNotification": true
  }
]


Querying Available APIs

After configuring SME, you can query the available APIs exposed by SME. Replace <NAMESPACE> with your Kubernetes namespace.


Code Block
languagebash
CAPIF_HOST=http://$(kubectl get service capifcore -n nonrtric -o jsonpath='{.spec.clusterIP}'):8090

curl -sS --location "$CAPIF_HOST/service-apis/v1/allServiceAPIs?api-invoker-id=api_invoker_id_Invoker_App_1" --header 'Accept: application/json' | jq

This command queries the SME to retrieve information about all available service APIs for the specified API invoker.