Added demo energy saving rapp 20/14520/4
authorsaul.gill <saul.gill@est.tech>
Fri, 30 May 2025 14:26:39 +0000 (15:26 +0100)
committersaul.gill <saul.gill@est.tech>
Tue, 3 Jun 2025 15:36:49 +0000 (16:36 +0100)
Added all rapp artifacts
Altered generate.sh to work when executed from anywhere
Altered patch-sample-rapps.sh to add chartmuseum url
Added README instructions

Issue-ID: NONRTRIC-1078
Change-Id: Ic3b393b94457e476b707f8c80f639a4647b8ece8
Signed-off-by: saul.gill <saul.gill@est.tech>
44 files changed:
sample-rapp-generator/es-demo-rapp/Demo_Energy_Saving_rApp.postman_collection.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/Dockerfile [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/README.md [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/cloudEventConsumerFor-itdep-installation.sh [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/cloudEventProducerFor-itdep-installation.sh [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/Chart.yaml [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/resources/config/config.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/NOTES.txt [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/_helpers.tpl [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/configmap.yaml [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/deployment.yaml [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/hpa.yaml [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/ingress.yaml [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/service.yaml [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/serviceaccount.yaml [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/values.yaml [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Definitions/asd.yaml [new file with mode: 0755]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Definitions/asd_types.yaml [new file with mode: 0755]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Acm/definition/compositions.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Acm/instances/es-instance.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Acm/instances/k8s-instance.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Acm/instances/kserve-instance.json [new file with mode: 0755]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/invokers/invoker-app1.json [new file with mode: 0755]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/invokers/invoker-influxdb.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/invokers/invoker-kserve-predictor.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/invokers/invoker-ncmp.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/providers/es-model-provider-function.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/providers/provider-function-1.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/serviceapis/api-set-1.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/serviceapis/api-set-2.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/serviceapis/api-set-kserve-predictor.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/TOSCA-Metadata/TOSCA.meta [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/asd.mf [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/src/assist.py [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/src/config.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/src/data.py [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/src/input.json [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/src/main.py [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/src/ncmp_client.py [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/src/requirements.txt [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/src/sme_client.py [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/src/teiv_client.py [new file with mode: 0644]
sample-rapp-generator/generate.sh
scripts/install/patch-sample-rapps.sh

diff --git a/sample-rapp-generator/es-demo-rapp/Demo_Energy_Saving_rApp.postman_collection.json b/sample-rapp-generator/es-demo-rapp/Demo_Energy_Saving_rApp.postman_collection.json
new file mode 100644 (file)
index 0000000..d7202cd
--- /dev/null
@@ -0,0 +1,997 @@
+{
+       "info": {
+               "_postman_id": "4dab7b43-234f-4695-b0ad-11bc178b1a62",
+               "name": "Demo Energy Saving rApp",
+               "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+               "_exporter_id": "14764781"
+       },
+       "item": [
+               {
+                       "name": "Energy Saving Usecase",
+                       "item": [
+                               {
+                                       "name": "Cleanup",
+                                       "item": [
+                                               {
+                                                       "name": "Get All Templates ACM-Direct",
+                                                       "event": [
+                                                               {
+                                                                       "listen": "test",
+                                                                       "script": {
+                                                                               "exec": [
+                                                                                       "pm.test(\"Status code is 200\", function () {",
+                                                                                       "    pm.response.to.have.status(200);",
+                                                                                       "    let jsonResponse = JSON.parse(responseBody);",
+                                                                                       "    let compositionCleanId = jsonResponse.service_templates[0].metadata.compositionId;",
+                                                                                       "    console.log(\"compositionCleanId: \" + compositionCleanId);",
+                                                                                       "    pm.collectionVariables.set(\"compositionCleanId\", compositionCleanId); // Fixed variable name",
+                                                                                       "});"
+                                                                               ],
+                                                                               "type": "text/javascript",
+                                                                               "packages": {}
+                                                                       }
+                                                               }
+                                                       ],
+                                                       "protocolProfileBehavior": {
+                                                               "disableBodyPruning": true
+                                                       },
+                                                       "request": {
+                                                               "auth": {
+                                                                       "type": "basic",
+                                                                       "basic": [
+                                                                               {
+                                                                                       "key": "password",
+                                                                                       "value": "{{ACM_PWD}}",
+                                                                                       "type": "string"
+                                                                               },
+                                                                               {
+                                                                                       "key": "username",
+                                                                                       "value": "{{ACM_USER}}",
+                                                                                       "type": "string"
+                                                                               }
+                                                                       ]
+                                                               },
+                                                               "method": "GET",
+                                                               "header": [],
+                                                               "body": {
+                                                                       "mode": "raw",
+                                                                       "raw": "",
+                                                                       "options": {
+                                                                               "raw": {
+                                                                                       "language": "json"
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "url": {
+                                                                       "raw": "http://{{REMOTE-IP}}:{{ACM_PORT}}/onap/policy/clamp/acm/v2/compositions",
+                                                                       "protocol": "http",
+                                                                       "host": [
+                                                                               "{{REMOTE-IP}}"
+                                                                       ],
+                                                                       "port": "{{ACM_PORT}}",
+                                                                       "path": [
+                                                                               "onap",
+                                                                               "policy",
+                                                                               "clamp",
+                                                                               "acm",
+                                                                               "v2",
+                                                                               "compositions"
+                                                                       ]
+                                                               }
+                                                       },
+                                                       "response": []
+                                               },
+                                               {
+                                                       "name": "Get Template ACM-Direct",
+                                                       "event": [
+                                                               {
+                                                                       "listen": "test",
+                                                                       "script": {
+                                                                               "exec": [
+                                                                                       ""
+                                                                               ],
+                                                                               "type": "text/javascript",
+                                                                               "packages": {}
+                                                                       }
+                                                               }
+                                                       ],
+                                                       "protocolProfileBehavior": {
+                                                               "disableBodyPruning": true
+                                                       },
+                                                       "request": {
+                                                               "auth": {
+                                                                       "type": "basic",
+                                                                       "basic": [
+                                                                               {
+                                                                                       "key": "password",
+                                                                                       "value": "{{ACM_PWD}}",
+                                                                                       "type": "string"
+                                                                               },
+                                                                               {
+                                                                                       "key": "username",
+                                                                                       "value": "{{ACM_USER}}",
+                                                                                       "type": "string"
+                                                                               }
+                                                                       ]
+                                                               },
+                                                               "method": "GET",
+                                                               "header": [],
+                                                               "body": {
+                                                                       "mode": "raw",
+                                                                       "raw": "",
+                                                                       "options": {
+                                                                               "raw": {
+                                                                                       "language": "json"
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "url": {
+                                                                       "raw": "http://{{REMOTE-IP}}:{{ACM_PORT}}/onap/policy/clamp/acm/v2/compositions/{{compositionCleanId}}",
+                                                                       "protocol": "http",
+                                                                       "host": [
+                                                                               "{{REMOTE-IP}}"
+                                                                       ],
+                                                                       "port": "{{ACM_PORT}}",
+                                                                       "path": [
+                                                                               "onap",
+                                                                               "policy",
+                                                                               "clamp",
+                                                                               "acm",
+                                                                               "v2",
+                                                                               "compositions",
+                                                                               "{{compositionCleanId}}"
+                                                                       ]
+                                                               }
+                                                       },
+                                                       "response": []
+                                               },
+                                               {
+                                                       "name": "Get All Instances ACM-Direct",
+                                                       "event": [
+                                                               {
+                                                                       "listen": "test",
+                                                                       "script": {
+                                                                               "exec": [
+                                                                                       "pm.test(\"Status code is 200\", function () {",
+                                                                                       "    pm.response.to.have.status(200);",
+                                                                                       "    let jsonResponse = JSON.parse(responseBody);",
+                                                                                       "    let instanceCleanId = jsonResponse.automationCompositionList[0].instanceId;",
+                                                                                       "    console.log(\"instanceCleanId: \" + instanceCleanId);",
+                                                                                       "    pm.collectionVariables.set(\"instanceCleanId\", instanceCleanId); // Fixed variable name",
+                                                                                       "});"
+                                                                               ],
+                                                                               "type": "text/javascript",
+                                                                               "packages": {}
+                                                                       }
+                                                               }
+                                                       ],
+                                                       "protocolProfileBehavior": {
+                                                               "disableBodyPruning": true
+                                                       },
+                                                       "request": {
+                                                               "auth": {
+                                                                       "type": "basic",
+                                                                       "basic": [
+                                                                               {
+                                                                                       "key": "password",
+                                                                                       "value": "{{ACM_PWD}}",
+                                                                                       "type": "string"
+                                                                               },
+                                                                               {
+                                                                                       "key": "username",
+                                                                                       "value": "{{ACM_USER}}",
+                                                                                       "type": "string"
+                                                                               }
+                                                                       ]
+                                                               },
+                                                               "method": "GET",
+                                                               "header": [],
+                                                               "body": {
+                                                                       "mode": "raw",
+                                                                       "raw": "{\r\n  \"name\": \"K8DemoInstance0\",\r\n  \"version\": \"1.0.1\",\r\n  \"compositionId\": \"{{compositionId}}\",\r\n  \"description\": \"Demo automation composition instance 0\",\r\n  \"elements\": {\r\n    \"d7be552e-bcc5-4478-b64d-797dbaec8f55\": {\r\n      \"id\": \"d7be552e-bcc5-4478-b64d-797dbaec8f55\",\r\n      \"definition\": {\r\n        \"name\": \"onap.policy.clamp.ac.element.K8S_StarterAutomationCompositionElement\",\r\n        \"version\": \"1.2.3\"\r\n      },\r\n      \"description\": \"Starter Automation Composition Element for the Hello World\",\r\n      \"properties\": {\r\n        \"chart\": {\r\n          \"chartId\": {\r\n            \"name\": \"hello-world-chart\",\r\n            \"version\": \"0.1.0\"\r\n          },\r\n          \"namespace\": \"nonrtric\",\r\n          \"releaseName\": \"hello-world-chart\",\r\n          \"podName\": \"hello-world-chart\",\r\n          \"repository\": {\r\n            \"repoName\": \"local\",\r\n            \"address\": \"UPDATE_THIS_CHART_MUSEUM_GET_CHARTS_URI\"\r\n          },\r\n          \"overrideParams\": {\r\n            \"appId\": \"DO_NOT_CHANGE_THIS_RAPP_INSTANCE_ID\",\r\n            \"smeDiscoveryEndpoint\": \"DO_NOT_CHANGE_THIS_SME_DISCOVERY_ENDPOINT\"\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n}",
+                                                                       "options": {
+                                                                               "raw": {
+                                                                                       "language": "json"
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "url": {
+                                                                       "raw": "http://{{REMOTE-IP}}:{{ACM_PORT}}/onap/policy/clamp/acm/v2/compositions/{{compositionCleanId}}/instances",
+                                                                       "protocol": "http",
+                                                                       "host": [
+                                                                               "{{REMOTE-IP}}"
+                                                                       ],
+                                                                       "port": "{{ACM_PORT}}",
+                                                                       "path": [
+                                                                               "onap",
+                                                                               "policy",
+                                                                               "clamp",
+                                                                               "acm",
+                                                                               "v2",
+                                                                               "compositions",
+                                                                               "{{compositionCleanId}}",
+                                                                               "instances"
+                                                                       ]
+                                                               }
+                                                       },
+                                                       "response": []
+                                               },
+                                               {
+                                                       "name": "Get Instance ACM-Direct",
+                                                       "event": [
+                                                               {
+                                                                       "listen": "test",
+                                                                       "script": {
+                                                                               "exec": [
+                                                                                       ""
+                                                                               ],
+                                                                               "type": "text/javascript",
+                                                                               "packages": {}
+                                                                       }
+                                                               }
+                                                       ],
+                                                       "protocolProfileBehavior": {
+                                                               "disableBodyPruning": true
+                                                       },
+                                                       "request": {
+                                                               "auth": {
+                                                                       "type": "basic",
+                                                                       "basic": [
+                                                                               {
+                                                                                       "key": "password",
+                                                                                       "value": "{{ACM_PWD}}",
+                                                                                       "type": "string"
+                                                                               },
+                                                                               {
+                                                                                       "key": "username",
+                                                                                       "value": "{{ACM_USER}}",
+                                                                                       "type": "string"
+                                                                               }
+                                                                       ]
+                                                               },
+                                                               "method": "GET",
+                                                               "header": [],
+                                                               "body": {
+                                                                       "mode": "raw",
+                                                                       "raw": "{\r\n  \"name\": \"K8DemoInstance0\",\r\n  \"version\": \"1.0.1\",\r\n  \"compositionId\": \"{{compositionId}}\",\r\n  \"description\": \"Demo automation composition instance 0\",\r\n  \"elements\": {\r\n    \"d7be552e-bcc5-4478-b64d-797dbaec8f55\": {\r\n      \"id\": \"d7be552e-bcc5-4478-b64d-797dbaec8f55\",\r\n      \"definition\": {\r\n        \"name\": \"onap.policy.clamp.ac.element.K8S_StarterAutomationCompositionElement\",\r\n        \"version\": \"1.2.3\"\r\n      },\r\n      \"description\": \"Starter Automation Composition Element for the Hello World\",\r\n      \"properties\": {\r\n        \"chart\": {\r\n          \"chartId\": {\r\n            \"name\": \"hello-world-chart\",\r\n            \"version\": \"0.1.0\"\r\n          },\r\n          \"namespace\": \"nonrtric\",\r\n          \"releaseName\": \"hello-world-chart\",\r\n          \"podName\": \"hello-world-chart\",\r\n          \"repository\": {\r\n            \"repoName\": \"local\",\r\n            \"address\": \"UPDATE_THIS_CHART_MUSEUM_GET_CHARTS_URI\"\r\n          },\r\n          \"overrideParams\": {\r\n            \"appId\": \"DO_NOT_CHANGE_THIS_RAPP_INSTANCE_ID\",\r\n            \"smeDiscoveryEndpoint\": \"DO_NOT_CHANGE_THIS_SME_DISCOVERY_ENDPOINT\"\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n}",
+                                                                       "options": {
+                                                                               "raw": {
+                                                                                       "language": "json"
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "url": {
+                                                                       "raw": "http://{{REMOTE-IP}}:{{ACM_PORT}}/onap/policy/clamp/acm/v2/compositions/{{compositionCleanId}}/instances/{{instanceCleanId}}",
+                                                                       "protocol": "http",
+                                                                       "host": [
+                                                                               "{{REMOTE-IP}}"
+                                                                       ],
+                                                                       "port": "{{ACM_PORT}}",
+                                                                       "path": [
+                                                                               "onap",
+                                                                               "policy",
+                                                                               "clamp",
+                                                                               "acm",
+                                                                               "v2",
+                                                                               "compositions",
+                                                                               "{{compositionCleanId}}",
+                                                                               "instances",
+                                                                               "{{instanceCleanId}}"
+                                                                       ]
+                                                               }
+                                                       },
+                                                       "response": []
+                                               },
+                                               {
+                                                       "name": "Undeploy Rapp Instance ACM-Direct",
+                                                       "request": {
+                                                               "auth": {
+                                                                       "type": "basic",
+                                                                       "basic": [
+                                                                               {
+                                                                                       "key": "password",
+                                                                                       "value": "{{ACM_PWD}}",
+                                                                                       "type": "string"
+                                                                               },
+                                                                               {
+                                                                                       "key": "username",
+                                                                                       "value": "{{ACM_USER}}",
+                                                                                       "type": "string"
+                                                                               }
+                                                                       ]
+                                                               },
+                                                               "method": "PUT",
+                                                               "header": [],
+                                                               "body": {
+                                                                       "mode": "raw",
+                                                                       "raw": "{\r\n    \"deployOrder\": \"UNDEPLOY\"\r\n}",
+                                                                       "options": {
+                                                                               "raw": {
+                                                                                       "language": "json"
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "url": {
+                                                                       "raw": "http://{{REMOTE-IP}}:{{ACM_PORT}}/onap/policy/clamp/acm/v2/compositions/{{compositionCleanId}}/instances/{{instanceCleanId}}",
+                                                                       "protocol": "http",
+                                                                       "host": [
+                                                                               "{{REMOTE-IP}}"
+                                                                       ],
+                                                                       "port": "{{ACM_PORT}}",
+                                                                       "path": [
+                                                                               "onap",
+                                                                               "policy",
+                                                                               "clamp",
+                                                                               "acm",
+                                                                               "v2",
+                                                                               "compositions",
+                                                                               "{{compositionCleanId}}",
+                                                                               "instances",
+                                                                               "{{instanceCleanId}}"
+                                                                       ]
+                                                               }
+                                                       },
+                                                       "response": []
+                                               },
+                                               {
+                                                       "name": "Delete Instance ACM-Direct",
+                                                       "event": [
+                                                               {
+                                                                       "listen": "test",
+                                                                       "script": {
+                                                                               "exec": [
+                                                                                       "pm.test(\"Status code is 201\", function () {",
+                                                                                       "    pm.response.to.have.status(201);",
+                                                                                       "    let location = pm.response.headers.get('Location')",
+                                                                                       "    console.log(\"location: \" + location)",
+                                                                                       "    let composition1Id = location.split('/')[2];",
+                                                                                       "    console.log(\"compositionId: \" + composition1Id)",
+                                                                                       "    pm.environment.set(\"composition1Id\", composition1Id);",
+                                                                                       "});"
+                                                                               ],
+                                                                               "type": "text/javascript",
+                                                                               "packages": {}
+                                                                       }
+                                                               }
+                                                       ],
+                                                       "request": {
+                                                               "auth": {
+                                                                       "type": "basic",
+                                                                       "basic": [
+                                                                               {
+                                                                                       "key": "password",
+                                                                                       "value": "{{ACM_PWD}}",
+                                                                                       "type": "string"
+                                                                               },
+                                                                               {
+                                                                                       "key": "username",
+                                                                                       "value": "{{ACM_USER}}",
+                                                                                       "type": "string"
+                                                                               }
+                                                                       ]
+                                                               },
+                                                               "method": "DELETE",
+                                                               "header": [],
+                                                               "body": {
+                                                                       "mode": "raw",
+                                                                       "raw": "{\r\n  \"name\": \"K8DemoInstance0\",\r\n  \"version\": \"1.0.1\",\r\n  \"compositionId\": \"{{compositionId}}\",\r\n  \"description\": \"Demo automation composition instance 0\",\r\n  \"elements\": {\r\n    \"d7be552e-bcc5-4478-b64d-797dbaec8f55\": {\r\n      \"id\": \"d7be552e-bcc5-4478-b64d-797dbaec8f55\",\r\n      \"definition\": {\r\n        \"name\": \"onap.policy.clamp.ac.element.K8S_StarterAutomationCompositionElement\",\r\n        \"version\": \"1.2.3\"\r\n      },\r\n      \"description\": \"Starter Automation Composition Element for the Hello World\",\r\n      \"properties\": {\r\n        \"chart\": {\r\n          \"chartId\": {\r\n            \"name\": \"hello-world-chart\",\r\n            \"version\": \"0.1.0\"\r\n          },\r\n          \"namespace\": \"nonrtric\",\r\n          \"releaseName\": \"hello-world-chart\",\r\n          \"podName\": \"hello-world-chart\",\r\n          \"repository\": {\r\n            \"repoName\": \"local\",\r\n            \"address\": \"UPDATE_THIS_CHART_MUSEUM_GET_CHARTS_URI\"\r\n          },\r\n          \"overrideParams\": {\r\n            \"appId\": \"DO_NOT_CHANGE_THIS_RAPP_INSTANCE_ID\",\r\n            \"smeDiscoveryEndpoint\": \"DO_NOT_CHANGE_THIS_SME_DISCOVERY_ENDPOINT\"\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n}",
+                                                                       "options": {
+                                                                               "raw": {
+                                                                                       "language": "json"
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "url": {
+                                                                       "raw": "http://{{REMOTE-IP}}:{{ACM_PORT}}/onap/policy/clamp/acm/v2/compositions/{{compositionCleanId}}/instances/{{instanceCleanId}}",
+                                                                       "protocol": "http",
+                                                                       "host": [
+                                                                               "{{REMOTE-IP}}"
+                                                                       ],
+                                                                       "port": "{{ACM_PORT}}",
+                                                                       "path": [
+                                                                               "onap",
+                                                                               "policy",
+                                                                               "clamp",
+                                                                               "acm",
+                                                                               "v2",
+                                                                               "compositions",
+                                                                               "{{compositionCleanId}}",
+                                                                               "instances",
+                                                                               "{{instanceCleanId}}"
+                                                                       ]
+                                                               }
+                                                       },
+                                                       "response": []
+                                               },
+                                               {
+                                                       "name": "Deprime Rapp ACM-Direct",
+                                                       "request": {
+                                                               "auth": {
+                                                                       "type": "basic",
+                                                                       "basic": [
+                                                                               {
+                                                                                       "key": "password",
+                                                                                       "value": "{{ACM_PWD}}",
+                                                                                       "type": "string"
+                                                                               },
+                                                                               {
+                                                                                       "key": "username",
+                                                                                       "value": "{{ACM_USER}}",
+                                                                                       "type": "string"
+                                                                               }
+                                                                       ]
+                                                               },
+                                                               "method": "PUT",
+                                                               "header": [],
+                                                               "body": {
+                                                                       "mode": "raw",
+                                                                       "raw": "{\r\n    \"primeOrder\": \"DEPRIME\"\r\n}",
+                                                                       "options": {
+                                                                               "raw": {
+                                                                                       "language": "json"
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "url": {
+                                                                       "raw": "http://{{REMOTE-IP}}:{{ACM_PORT}}/onap/policy/clamp/acm/v2/compositions/{{compositionCleanId}}",
+                                                                       "protocol": "http",
+                                                                       "host": [
+                                                                               "{{REMOTE-IP}}"
+                                                                       ],
+                                                                       "port": "{{ACM_PORT}}",
+                                                                       "path": [
+                                                                               "onap",
+                                                                               "policy",
+                                                                               "clamp",
+                                                                               "acm",
+                                                                               "v2",
+                                                                               "compositions",
+                                                                               "{{compositionCleanId}}"
+                                                                       ]
+                                                               }
+                                                       },
+                                                       "response": []
+                                               },
+                                               {
+                                                       "name": "Delete Template ACM-Direct",
+                                                       "request": {
+                                                               "auth": {
+                                                                       "type": "basic",
+                                                                       "basic": [
+                                                                               {
+                                                                                       "key": "password",
+                                                                                       "value": "{{ACM_PWD}}",
+                                                                                       "type": "string"
+                                                                               },
+                                                                               {
+                                                                                       "key": "username",
+                                                                                       "value": "{{ACM_USER}}",
+                                                                                       "type": "string"
+                                                                               }
+                                                                       ]
+                                                               },
+                                                               "method": "DELETE",
+                                                               "header": [],
+                                                               "body": {
+                                                                       "mode": "raw",
+                                                                       "raw": "",
+                                                                       "options": {
+                                                                               "raw": {
+                                                                                       "language": "json"
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "url": {
+                                                                       "raw": "http://{{REMOTE-IP}}:{{ACM_PORT}}/onap/policy/clamp/acm/v2/compositions/{{compositionCleanId}}",
+                                                                       "protocol": "http",
+                                                                       "host": [
+                                                                               "{{REMOTE-IP}}"
+                                                                       ],
+                                                                       "port": "{{ACM_PORT}}",
+                                                                       "path": [
+                                                                               "onap",
+                                                                               "policy",
+                                                                               "clamp",
+                                                                               "acm",
+                                                                               "v2",
+                                                                               "compositions",
+                                                                               "{{compositionCleanId}}"
+                                                                       ]
+                                                               }
+                                                       },
+                                                       "response": []
+                                               },
+                                               {
+                                                       "name": "Get Participants ACM-Direct",
+                                                       "event": [
+                                                               {
+                                                                       "listen": "test",
+                                                                       "script": {
+                                                                               "exec": [
+                                                                                       "pm.test(\"Status code is 201\", function () {",
+                                                                                       "    pm.response.to.have.status(201);",
+                                                                                       "    let location = pm.response.headers.get('Location')",
+                                                                                       "    console.log(\"location: \" + location)",
+                                                                                       "    let composition1Id = location.split('/')[2];",
+                                                                                       "    console.log(\"compositionId: \" + composition1Id)",
+                                                                                       "    pm.environment.set(\"composition1Id\", composition1Id);",
+                                                                                       "});"
+                                                                               ],
+                                                                               "type": "text/javascript",
+                                                                               "packages": {}
+                                                                       }
+                                                               }
+                                                       ],
+                                                       "protocolProfileBehavior": {
+                                                               "disableBodyPruning": true
+                                                       },
+                                                       "request": {
+                                                               "auth": {
+                                                                       "type": "basic",
+                                                                       "basic": [
+                                                                               {
+                                                                                       "key": "password",
+                                                                                       "value": "{{ACM_PWD}}",
+                                                                                       "type": "string"
+                                                                               },
+                                                                               {
+                                                                                       "key": "username",
+                                                                                       "value": "{{ACM_USER}}",
+                                                                                       "type": "string"
+                                                                               }
+                                                                       ]
+                                                               },
+                                                               "method": "GET",
+                                                               "header": [],
+                                                               "body": {
+                                                                       "mode": "raw",
+                                                                       "raw": "{\r\n  \"tosca_definitions_version\": \"tosca_simple_yaml_1_3\",\r\n  \"data_types\": {\r\n    \"onap.datatypes.ToscaConceptIdentifier\": {\r\n      \"derived_from\": \"tosca.datatypes.Root\",\r\n      \"properties\": {\r\n        \"name\": {\r\n          \"type\": \"string\",\r\n          \"required\": true\r\n        },\r\n        \"version\": {\r\n          \"type\": \"string\",\r\n          \"required\": true\r\n        }\r\n      }\r\n    }\r\n  },\r\n  \"node_types\": {\r\n    \"org.onap.policy.clamp.acm.Participant\": {\r\n      \"version\": \"1.0.1\",\r\n      \"derived_from\": \"tosca.nodetypes.Root\",\r\n      \"properties\": {\r\n        \"provider\": {\r\n          \"type\": \"string\",\r\n          \"required\": false\r\n        }\r\n      }\r\n    },\r\n    \"org.onap.policy.clamp.acm.AutomationCompositionElement\": {\r\n      \"version\": \"1.0.1\",\r\n      \"derived_from\": \"tosca.nodetypes.Root\",\r\n      \"properties\": {\r\n        \"provider\": {\r\n          \"type\": \"string\",\r\n          \"required\": false\r\n        },\r\n        \"participantType\": {\r\n          \"type\": \"onap.datatypes.ToscaConceptIdentifier\",\r\n          \"required\": true\r\n        },\r\n        \"startPhase\": {\r\n          \"type\": \"integer\",\r\n          \"required\": false,\r\n          \"constraints\": [\r\n            {\r\n              \"greater-or-equal\": 0\r\n            }\r\n          ],\r\n          \"metadata\": {\r\n            \"common\": true\r\n          },\r\n          \"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\"\r\n        },\r\n        \"passiveToRunningTimeout\": {\r\n          \"type\": \"integer\",\r\n          \"required\": false,\r\n          \"constraints\": [\r\n            {\r\n              \"greater_or_equal\": 0\r\n            }\r\n          ],\r\n          \"default\": 60,\r\n          \"metadata\": {\r\n            \"common\": true\r\n          },\r\n          \"description\": \"The maximum time in seconds to wait for a state chage from passive to running\"\r\n        },\r\n        \"runningToPassiveTimeout\": {\r\n          \"type\": \"integer\",\r\n          \"required\": false,\r\n          \"constraints\": [\r\n            {\r\n              \"greater_or_equal\": 0\r\n            }\r\n          ],\r\n          \"default\": 60,\r\n          \"metadata\": {\r\n            \"common\": true\r\n          },\r\n          \"description\": \"The maximum time in seconds to wait for a state chage from running to passive\"\r\n        },\r\n        \"passiveToUninitializedTimeout\": {\r\n          \"type\": \"integer\",\r\n          \"required\": false,\r\n          \"constraints\": [\r\n            {\r\n              \"greater_or_equal\": 0\r\n            }\r\n          ],\r\n          \"default\": 60,\r\n          \"metadata\": {\r\n            \"common\": true\r\n          },\r\n          \"description\": \"The maximum time in seconds to wait for a state chage from passive to uninitialized\"\r\n        }\r\n      }\r\n    },\r\n    \"org.onap.policy.clamp.acm.AutomationComposition\": {\r\n      \"version\": \"1.0.1\",\r\n      \"derived_from\": \"tosca.nodetypes.Root\",\r\n      \"properties\": {\r\n        \"provider\": {\r\n          \"type\": \"string\",\r\n          \"required\": false,\r\n          \"metadata\": {\r\n            \"common\": true\r\n          }\r\n        },\r\n        \"elements\": {\r\n          \"type\": \"list\",\r\n          \"required\": true,\r\n          \"metadata\": {\r\n            \"common\": true\r\n          },\r\n          \"entry_schema\": {\r\n            \"type\": \"onap.datatypes.ToscaConceptIdentifier\"\r\n          }\r\n        }\r\n      }\r\n    },\r\n    \"org.onap.policy.clamp.acm.K8SMicroserviceAutomationCompositionElement\": {\r\n      \"version\": \"1.0.0\",\r\n      \"derived_from\": \"org.onap.policy.clamp.acm.AutomationCompositionElement\",\r\n      \"properties\": {\r\n        \"chart\": {\r\n          \"type\": \"string\",\r\n          \"required\": true\r\n        },\r\n        \"configs\": {\r\n          \"type\": \"list\",\r\n          \"required\": false\r\n        },\r\n        \"requirements\": {\r\n          \"type\": \"string\",\r\n          \"required\": false\r\n        },\r\n        \"templates\": {\r\n          \"type\": \"list\",\r\n          \"required\": false,\r\n          \"entry_schema\": null\r\n        },\r\n        \"values\": {\r\n          \"type\": \"string\",\r\n          \"required\": true\r\n        }\r\n      }\r\n    }\r\n  },\r\n  \"topology_template\": {\r\n    \"node_templates\": {\r\n      \"org.onap.k8s.acm.K8SAutomationCompositionParticipant\": {\r\n        \"version\": \"2.3.4\",\r\n        \"type\": \"org.onap.policy.clamp.acm.Participant\",\r\n        \"type_version\": \"1.0.1\",\r\n        \"description\": \"Participant for K8S\",\r\n        \"properties\": {\r\n          \"provider\": \"ONAP\"\r\n        }\r\n      },\r\n      \"onap.policy.clamp.ac.element.K8S_StarterAutomationCompositionElement\": {\r\n        \"version\": \"1.2.3\",\r\n        \"type\": \"org.onap.policy.clamp.acm.K8SMicroserviceAutomationCompositionElement\",\r\n        \"type_version\": \"1.0.0\",\r\n        \"description\": \"Automation composition element for the K8S microservice for AC Element Starter\",\r\n        \"properties\": {\r\n          \"provider\": \"ONAP\",\r\n          \"startPhase\": 0,\r\n          \"uninitializedToPassiveTimeout\": 300,\r\n          \"podStatusCheckInterval\": 30\r\n        }\r\n      },\r\n      \"onap.policy.clamp.ac.element.AutomationCompositionDefinition\": {\r\n        \"version\": \"1.2.3\",\r\n        \"type\": \"org.onap.policy.clamp.acm.AutomationComposition\",\r\n        \"type_version\": \"1.0.1\",\r\n        \"description\": \"Automation composition for rapp deployment\",\r\n        \"properties\": {\r\n          \"provider\": \"ONAP\",\r\n          \"elements\": [\r\n            {\r\n              \"name\": \"onap.policy.clamp.ac.element.K8S_StarterAutomationCompositionElement\",\r\n              \"version\": \"1.2.3\"\r\n            }\r\n          ]\r\n        }\r\n      }\r\n    }\r\n  }\r\n}",
+                                                                       "options": {
+                                                                               "raw": {
+                                                                                       "language": "json"
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "url": {
+                                                                       "raw": "http://{{REMOTE-IP}}:{{ACM_PORT}}/onap/policy/clamp/acm/v2/participants",
+                                                                       "protocol": "http",
+                                                                       "host": [
+                                                                               "{{REMOTE-IP}}"
+                                                                       ],
+                                                                       "port": "{{ACM_PORT}}",
+                                                                       "path": [
+                                                                               "onap",
+                                                                               "policy",
+                                                                               "clamp",
+                                                                               "acm",
+                                                                               "v2",
+                                                                               "participants"
+                                                                       ]
+                                                               }
+                                                       },
+                                                       "response": []
+                                               }
+                                       ]
+                               },
+                               {
+                                       "name": "Onboard ES Rapp",
+                                       "request": {
+                                               "method": "POST",
+                                               "header": [
+                                                       {
+                                                               "key": "Content-Type",
+                                                               "value": "multipart/form-data",
+                                                               "type": "text",
+                                                               "disabled": true
+                                                       }
+                                               ],
+                                               "body": {
+                                                       "mode": "formdata",
+                                                       "formdata": [
+                                                               {
+                                                                       "key": "file",
+                                                                       "type": "file",
+                                                                       "src": "/home/saul/Projects/oran-projects/nonrtric-prototyping/es-rapp/rapp-energy-saving.csar"
+                                                               },
+                                                               {
+                                                                       "key": "file2",
+                                                                       "type": "file",
+                                                                       "src": [],
+                                                                       "disabled": true
+                                                               }
+                                                       ]
+                                               },
+                                               "url": {
+                                                       "raw": "http://{{REMOTE-IP}}:{{PORT}}/rapps/{{rappId}}",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "{{REMOTE-IP}}"
+                                                       ],
+                                                       "port": "{{PORT}}",
+                                                       "path": [
+                                                               "rapps",
+                                                               "{{rappId}}"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Get Rapps",
+                                       "request": {
+                                               "method": "GET",
+                                               "header": [],
+                                               "url": {
+                                                       "raw": "http://{{REMOTE-IP}}:{{PORT}}/rapps",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "{{REMOTE-IP}}"
+                                                       ],
+                                                       "port": "{{PORT}}",
+                                                       "path": [
+                                                               "rapps"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Prime Rapp",
+                                       "request": {
+                                               "method": "PUT",
+                                               "header": [],
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": "{\r\n    \"primeOrder\": \"PRIME\"\r\n}",
+                                                       "options": {
+                                                               "raw": {
+                                                                       "language": "json"
+                                                               }
+                                                       }
+                                               },
+                                               "url": {
+                                                       "raw": "http://{{REMOTE-IP}}:{{PORT}}/rapps/{{rappId}}",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "{{REMOTE-IP}}"
+                                                       ],
+                                                       "port": "{{PORT}}",
+                                                       "path": [
+                                                               "rapps",
+                                                               "{{rappId}}"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Get All Rapp Instances",
+                                       "request": {
+                                               "method": "GET",
+                                               "header": [],
+                                               "url": {
+                                                       "raw": "http://{{REMOTE-IP}}:{{PORT}}/rapps/{{rappId}}/instance",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "{{REMOTE-IP}}"
+                                                       ],
+                                                       "port": "{{PORT}}",
+                                                       "path": [
+                                                               "rapps",
+                                                               "{{rappId}}",
+                                                               "instance"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Create Rapp Instance ES",
+                                       "event": [
+                                               {
+                                                       "listen": "test",
+                                                       "script": {
+                                                               "exec": [
+                                                                       "var jsonData = pm.response.json();\r",
+                                                                       "if(jsonData != null && jsonData.rappInstanceId != null) {\r",
+                                                                       "\r",
+                                                                       "pm.collectionVariables.set(\"rappInstanceId\", jsonData.rappInstanceId);\r",
+                                                                       "}"
+                                                               ],
+                                                               "type": "text/javascript",
+                                                               "packages": {}
+                                                       }
+                                               }
+                                       ],
+                                       "request": {
+                                               "method": "POST",
+                                               "header": [],
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": "{\r\n    \"acm\":{\r\n        \"instance\": \"es-instance\"\r\n    },\r\n    \"sme\": {\r\n        \"providerFunction\": \"es-model-provider-function\",\r\n        \"serviceApis\": \"api-set-kserve-predictor\",\r\n        \"invokers\": \"invoker-app1\"\r\n    }\r\n}",
+                                                       "options": {
+                                                               "raw": {
+                                                                       "language": "json"
+                                                               }
+                                                       }
+                                               },
+                                               "url": {
+                                                       "raw": "http://{{REMOTE-IP}}:{{PORT}}/rapps/{{rappId}}/instance",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "{{REMOTE-IP}}"
+                                                       ],
+                                                       "port": "{{PORT}}",
+                                                       "path": [
+                                                               "rapps",
+                                                               "{{rappId}}",
+                                                               "instance"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Get Rapp Instance",
+                                       "request": {
+                                               "method": "GET",
+                                               "header": [],
+                                               "url": {
+                                                       "raw": "http://{{REMOTE-IP}}:{{PORT}}/rapps/{{rappId}}/instance/{{rappInstanceId}}",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "{{REMOTE-IP}}"
+                                                       ],
+                                                       "port": "{{PORT}}",
+                                                       "path": [
+                                                               "rapps",
+                                                               "{{rappId}}",
+                                                               "instance",
+                                                               "{{rappInstanceId}}"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Deploy Rapp Instance",
+                                       "request": {
+                                               "method": "PUT",
+                                               "header": [],
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": "{\r\n    \"deployOrder\": \"DEPLOY\"\r\n}",
+                                                       "options": {
+                                                               "raw": {
+                                                                       "language": "json"
+                                                               }
+                                                       }
+                                               },
+                                               "url": {
+                                                       "raw": "http://{{REMOTE-IP}}:{{PORT}}/rapps/{{rappId}}/instance/{{rappInstanceId}}",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "{{REMOTE-IP}}"
+                                                       ],
+                                                       "port": "{{PORT}}",
+                                                       "path": [
+                                                               "rapps",
+                                                               "{{rappId}}",
+                                                               "instance",
+                                                               "{{rappInstanceId}}"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Undeploy Rapp Instance",
+                                       "request": {
+                                               "method": "PUT",
+                                               "header": [],
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": "{\r\n    \"deployOrder\": \"UNDEPLOY\"\r\n}",
+                                                       "options": {
+                                                               "raw": {
+                                                                       "language": "json"
+                                                               }
+                                                       }
+                                               },
+                                               "url": {
+                                                       "raw": "http://{{REMOTE-IP}}:{{PORT}}/rapps/{{rappId}}/instance/{{rappInstanceId}}",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "{{REMOTE-IP}}"
+                                                       ],
+                                                       "port": "{{PORT}}",
+                                                       "path": [
+                                                               "rapps",
+                                                               "{{rappId}}",
+                                                               "instance",
+                                                               "{{rappInstanceId}}"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Delete Rapp Instance",
+                                       "request": {
+                                               "method": "DELETE",
+                                               "header": [],
+                                               "url": {
+                                                       "raw": "http://{{REMOTE-IP}}:{{PORT}}/rapps/{{rappId}}/instance/{{rappInstanceId}}",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "{{REMOTE-IP}}"
+                                                       ],
+                                                       "port": "{{PORT}}",
+                                                       "path": [
+                                                               "rapps",
+                                                               "{{rappId}}",
+                                                               "instance",
+                                                               "{{rappInstanceId}}"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Deprime Rapp",
+                                       "request": {
+                                               "method": "PUT",
+                                               "header": [],
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": "{\r\n    \"primeOrder\": \"DEPRIME\"\r\n}",
+                                                       "options": {
+                                                               "raw": {
+                                                                       "language": "json"
+                                                               }
+                                                       }
+                                               },
+                                               "url": {
+                                                       "raw": "http://{{REMOTE-IP}}:{{PORT}}/rapps/{{rappId}}",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "{{REMOTE-IP}}"
+                                                       ],
+                                                       "port": "{{PORT}}",
+                                                       "path": [
+                                                               "rapps",
+                                                               "{{rappId}}"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Delete ES Rapp",
+                                       "request": {
+                                               "method": "DELETE",
+                                               "header": [],
+                                               "url": {
+                                                       "raw": "http://{{REMOTE-IP}}:{{PORT}}/rapps/{{rappId}}",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "{{REMOTE-IP}}"
+                                                       ],
+                                                       "port": "{{PORT}}",
+                                                       "path": [
+                                                               "rapps",
+                                                               "{{rappId}}"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Predict",
+                                       "request": {
+                                               "method": "POST",
+                                               "header": [],
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": "{\n    \"signature_name\": \"serving_default\",\n    \"instances\": [\n        [\n            [\n                8.15,\n                11.51,\n                57.12\n            ]\n        ]\n    ]\n}",
+                                                       "options": {
+                                                               "raw": {
+                                                                       "language": "json"
+                                                               }
+                                                       }
+                                               },
+                                               "url": {
+                                                       "raw": "http://{{REMOTE-IP}}:{{PREDICT_PORT}}/v1/models/es-aiml-model:predict",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "{{REMOTE-IP}}"
+                                                       ],
+                                                       "port": "{{PREDICT_PORT}}",
+                                                       "path": [
+                                                               "v1",
+                                                               "models",
+                                                               "es-aiml-model:predict"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               },
+                               {
+                                       "name": "Model readiness",
+                                       "protocolProfileBehavior": {
+                                               "disableBodyPruning": true
+                                       },
+                                       "request": {
+                                               "method": "GET",
+                                               "header": [],
+                                               "body": {
+                                                       "mode": "raw",
+                                                       "raw": "{}",
+                                                       "options": {
+                                                               "raw": {
+                                                                       "language": "json"
+                                                               }
+                                                       }
+                                               },
+                                               "url": {
+                                                       "raw": "http://localhost:40077/v1/models/es-aiml-model",
+                                                       "protocol": "http",
+                                                       "host": [
+                                                               "localhost"
+                                                       ],
+                                                       "port": "40077",
+                                                       "path": [
+                                                               "v1",
+                                                               "models",
+                                                               "es-aiml-model"
+                                                       ]
+                                               }
+                                       },
+                                       "response": []
+                               }
+                       ]
+               }
+       ],
+       "variable": [
+               {
+                       "key": "REMOTE-IP",
+                       "value": "localhost"
+               },
+               {
+                       "key": "ACM_PORT",
+                       "value": "30442"
+               },
+               {
+                       "key": "compositionCleanId",
+                       "value": "969b740c-dde4-410c-ade2-8db2061e1531"
+               },
+               {
+                       "key": "instanceCleanId",
+                       "value": "1aaed9b1-4d23-441f-9107-5e3f36f4f323"
+               },
+               {
+                       "key": "PORT",
+                       "value": "36797"
+               },
+               {
+                       "key": "rappId",
+                       "value": "energy-saving-1"
+               },
+               {
+                       "key": "rappInstanceId",
+                       "value": "083dea57-f177-4c0e-be1b-a3282d16f586"
+               },
+               {
+                       "key": "PREDICT_PORT",
+                       "value": "40077"
+               },
+               {
+                       "key": "ACM_USER",
+                       "value": "runtimeUser"
+               },
+               {
+                       "key": "ACM_PWD",
+                       "value": "ZiboTipdZeyt9]"
+               }
+       ]
+}
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/Dockerfile b/sample-rapp-generator/es-demo-rapp/Dockerfile
new file mode 100644 (file)
index 0000000..85f2335
--- /dev/null
@@ -0,0 +1,28 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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 python:3.10.17-alpine3.21
+
+WORKDIR /app
+
+COPY src/ /app
+
+RUN pip install -r requirements.txt
+
+COPY src/ /app
+
+CMD ["python", "main.py", "--generate_db_data=True", "--use_sme_db=True", "--random_predictions=False" ]
diff --git a/sample-rapp-generator/es-demo-rapp/README.md b/sample-rapp-generator/es-demo-rapp/README.md
new file mode 100644 (file)
index 0000000..e1466e3
--- /dev/null
@@ -0,0 +1,137 @@
+# Energy Saving rApp Demo
+The code, helm chart and rApp specification contained in this directory is used to deploy the Energy Saving rApp demo.
+The demo is designed to showcase the capabilities of the rApp platform in managing energy consumption in a network.
+The instructions below describe how to:
+
+- Deploy the demo in a Kubernetes cluster.
+- Create and deploy the Energy Saving rApp.
+- Confirm that the Energy Saving rApp is running and managing energy consumption in the network.
+- Undeploy the Energy Saving rApp.
+- Troubleshoot any issues that may arise during the deployment or undeployment process.
+
+## Prerequisites
+- A Kubernetes cluster, various versions and sims supported - see [here](https://gerrit.o-ran-sc.org/r/gitweb?p=it/dep.git;a=blob_plain;f=smo-install/README.md;hb=HEAD).
+- See prerequisites [here](https://gerrit.o-ran-sc.org/r/gitweb?p=it/dep.git;a=blob_plain;f=smo-install/README.md;hb=HEAD)
+- A clone of this repository.
+- Postman.
+
+## Deployment Steps
+
+### SMO Installation
+For a complete guide on the installation of the SMO rApp platform,
+please follow the instructions [here](https://gerrit.o-ran-sc.org/r/gitweb?p=it/dep.git;a=blob_plain;f=smo-install/README.md;hb=HEAD).
+
+### Energy Saving rApp Deployment Preparation
+1. The rApp needs to know the address and port of your chart repository. We can do this by running the following command:
+   ```bash
+   cd scripts/install
+   ./patch-sample-rapps.sh -i IP_ADD -p PORT -r "es-demo-rapp/rapp-energy-saving"
+   ```
+2. Navigate to the `es-demo-rapp` directory.
+3. To generate the rApp csar and helm chart, run the following command:
+   ```bash
+   ./generate.sh rapp-energy-saving
+   ```
+4. Make sure to expose the rappmanager service in the `nonrtric` namespace. This is done by running the following command:
+   ```bash
+   kubectl expose service rappmanager --type=NodePort --name=rappmanager-exposed -n nonrtric
+   ```
+5. You will be using the postman collection provided in the main directory of this repository to create the rApp.
+6. Open Postman and import the `rapp-energy-saving.postman_collection.json` file.
+7. It is important to note the collection-level variables in the postman collection.
+    1. REMOTE-IP: This is the location the rappmanager service is deployed/exposed to.
+    2. PORT: This should be the port where the rappmanager is exposed.
+    3. rappId: This is the ID of the rApp you will be creating. It should be unique and can be any alphanumeric string.
+    4. rappInstanceId: It will be automatically populated when you create the rApp instance.
+    5. PREIDCT_PORT: This is the port where the prediction service is running. It should be set to `40077` by default.
+
+### rApp Deployment
+1. In Postman, select the `Onboard ES rApp` request from the collection. Send this request.
+2. Then run the `Get Rapps` request to confirm that the rApp has been onboarded successfully.
+3. Run the `Prime rApp` request to prime the rApp.
+4. Run `Get All Rapp Instances` to confirm that no rApp instance have been created.
+5. Run the `Create Rapp Instance ES` request to create an instance of the rApp.
+6. Run the `Get Rapp Instance` request to confirm that the rApp instance has been created successfully.
+7. Run the `Deploy Rapp Instance` to trigger installation of the rApp instance.
+8. The above deployment can take time, so you can run the `Get Rapp Instance` request to check the status of the rApp instance.
+9. You can also monitor the kubernetes pods in the `nonrtric` namespace to see if the rApp instance helm charts are being deployed.
+
+### Confirmation
+1. To confirm successful running of the demo energy saving rApp, we can look at the kubernetes logs of the pod.
+   ```bash
+   kubectl logs -f app.kubernetes.io/name=energy-saving-rapp -n nonrtric
+   ```
+2. You should see logs indicating that the rApp is running and managing energy consumption in the network.
+3. For example, you should see:
+    1. logs of cells being turned off and on based on the energy consumption in the network.
+    2. Predictions of energy consumption based on the current network load being returned to make poweer management decisions.
+
+## Undeployment
+Undeployment of the rApp can also be done with the Postman collection.
+1. Run the `Undeploy Rapp Instance` request to undeploy the rApp instance. This takes some time.
+2. Run the `Get Rapp Instance` request to confirm that the rApp instance has been undeployed successfully.
+3. Run the `Delete Rapp Instance` request to delete the rApp instance.
+4. Run the `Get All Rapp Instances` request to confirm that no rApp instances are present.
+5. Run the `Deprime rApp` request to deprime the rApp.
+6. Run the `Delete ES Rapp` request to delete the rApp.
+7. This should conclude the undeployment of the Energy Saving rApp.
+
+## Troubleshooting
+If you encounter any issues during the deployment or undeployment of the rApp, please check the following:
+1. Is deployment of the pods stuck in ACM?
+    - Check the logs of the ACM pod and the kubernetes participant in the `onap` namespace.
+    - Is there any indication that install of the pods failed?
+    - Check the deployment status of the pods
+2. Is there an issue with the SME part of the installation?
+    - Check the logs of the servicemanager pod in the `nonrtric` namespace.
+    - Is there any indication that the SME is not able to communicate with the rApp Manager?
+
+### Clean Up
+If there is a case of a failed deployment that cannot be cleaned up via the API, we can use the following steps.
+When cleaning up, it is best to carry out both ACM Cleanup and SME Cleanup - detailed below.
+
+#### ACM Cleanup
+Consult the postman collection under the "Cleanup" directory for the ACM cleanup steps.
+1. Run `Get All Templates ACM-Direct`
+2. Run `Get Template ACM-Direct`
+3. Run `Get All Instances ACM-Direct`
+4. Run `Get Instance ACM-Direct`
+5. The above will populate the postman collection variables with the template and instance IDs.
+6. Run `Undeploy Instance ACM-Direct` to undeploy the instance.
+   Wait for the pods to undeploy (if they are stuck or leftover).
+7. Run `Delete Instance ACM-Direct` to delete the instance.
+8. Run `Delete Template ACM-Direct` to delete the template.
+9. That should conclude the ACM cleanup.
+
+#### SME Cleanup
+SME cleanup requires some manual steps.
+1. Delete all the kong services and routes. Put this in some "script.sh" file and run it. The place where you run it
+   should have access to the cluster.
+   ```bash
+      SERVICEMANAGER_POD=$(kubectl get pods -o custom-columns=NAME:.metadata.name -l app.kubernetes.io/name=servicemanager --no-headers -n nonrtric)
+      if [[ -n $SERVICEMANAGER_POD ]]; then
+      kubectl exec $SERVICEMANAGER_POD -n nonrtric -- ./kongclearup
+      else
+      echo "Error - Servicemanager pod not found, didn't delete Kong routes and services for ServiceManager."
+      fi
+
+   ```
+2. Once the above has been run, we must restart some pods.
+   ```bash
+   kubectl delete pod -l app.kubernetes.io/name=servicemanager -n nonrtric
+   kubectl delete pod -l app.kubernetes.io/name=rappmanager -n nonrtric
+   kubectl delete pod -l app.kubernetes.io/name=capifcore -n nonrtric
+   ```
+3. Wait for these pods to come up again to a `Running` state.
+4. Now we need to add some preloaded SME configurations.
+    1. In the `it/dep` repository, navigate to the `nonrtric/servicemanager-preload` directory.
+    2. Preload some of the nonrtric services by running the following command:
+       ```bash
+       ./servicemanager-preload.sh config-nonrtric.yaml
+       ```
+    3. Preload the SMO services by running the following command:
+       ```bash
+       ./servicemanager-preload.sh config-smo.yaml
+       ```
+5. This should conclude the SME cleanup. Then we can attempt to redeploy the rApp again with whatever
+   changes we made to fix the issues.
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/cloudEventConsumerFor-itdep-installation.sh b/sample-rapp-generator/es-demo-rapp/cloudEventConsumerFor-itdep-installation.sh
new file mode 100644 (file)
index 0000000..2d04057
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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=================================================
+#
+while getopts "u:p:" opt; do
+  case $opt in
+    u) KAFKA_USER="$OPTARG" ;;
+    p) KAFKA_PASSWORD="$OPTARG" ;;
+    *) echo "Usage: $0 [-u KAFKA_USER] [-p KAFKA_PASSWORD]" >&2; exit 1 ;;
+  esac
+done
+
+if [ -z "$KAFKA_USER" ] || [ -z "$KAFKA_PASSWORD" ]; then
+  echo "Error: All arguments (-u, -p) are required." >&2
+  echo "Usage: $0 [-u KAFKA_USER] [-p KAFKA_PASSWORD]" >&2
+  exit 1
+fi
+
+
+KAFKA_NAMESPACE="${1:-onap}"
+KAFKA_TOPIC="${2:-topology-inventory-ingestion}"
+KAFKA_POD_NAME="${3:-onap-strimzi-kafka-0}"
+GROUP_ID="${4:-topology-inventory-ingestion-consumer}"
+OFFSET_RESET="${5:-earliest}"
+
+echo "Consuming messages from Kafka topic '$KAFKA_TOPIC'..."
+
+kubectl exec -it "$KAFKA_POD_NAME" -n "$KAFKA_NAMESPACE" -- /opt/kafka/bin/kafka-console-consumer.sh \
+  --bootstrap-server onap-strimzi-kafka-bootstrap.onap:9092 \
+  --topic "$KAFKA_TOPIC" \
+  --consumer-property security.protocol=SASL_PLAINTEXT \
+  --consumer-property sasl.mechanism=SCRAM-SHA-512 \
+  --consumer-property "sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required username=\"${KAFKA_USER}\" password=\"${KAFKA_PASSWORD}\";" \
+  --group "$GROUP_ID" \
+  --from-beginning \
+  --timeout-ms 60000 \
+  --consumer-property auto.offset.reset="$OFFSET_RESET"
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/cloudEventProducerFor-itdep-installation.sh b/sample-rapp-generator/es-demo-rapp/cloudEventProducerFor-itdep-installation.sh
new file mode 100644 (file)
index 0000000..f4bee87
--- /dev/null
@@ -0,0 +1,66 @@
+#!/bin/bash
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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=================================================
+#
+
+while getopts "u:p:" opt; do
+  case $opt in
+    u) KAFKA_USER="$OPTARG" ;;
+    p) KAFKA_PASSWORD="$OPTARG" ;;
+    *) echo "Usage: $0 [-u KAFKA_USER] [-p KAFKA_PASSWORD]" >&2; exit 1 ;;
+  esac
+done
+
+if [ -z "$KAFKA_USER" ] || [ -z "$KAFKA_PASSWORD" ]; then
+  echo "Error: All arguments (-u, -p) are required." >&2
+  echo "Usage: $0 [-u KAFKA_USER] [-p KAFKA_PASSWORD]" >&2
+  exit 1
+fi
+
+KAFKA_NAMESPACE="${1:-onap}"
+KAFKA_TOPIC="${2:-topology-inventory-ingestion}"
+KAFKA_POD_NAME="${3:-onap-strimzi-kafka-0}"
+FILE_DUPLICATION_FACTOR="${4:-1}" # How many times to use the same CloudEvent file
+FOLDER_OF_CLOUDEVENTS="${5:-events}" # All files in this folder are written to kafka
+# number of generated files == number of files in the $FOLDER_OF_CLOUDEVENTS * $FILE_DUPLICATION_FACTOR
+
+echo "Producing messages to Kafka topic '$KAFKA_TOPIC'..."
+
+# Loop to produce multiple messages
+for ((i=0; i<$FILE_DUPLICATION_FACTOR; i++)); do
+  for file in "$FOLDER_OF_CLOUDEVENTS"/*; do
+    if [ -f "$file" ]; then
+    # Replace new lines and write to kafka
+    sed ':a;N;$!ba;s/\n/ /g' $file | \
+      kubectl exec -i "$KAFKA_POD_NAME" -n "$KAFKA_NAMESPACE" -- /opt/kafka/bin/kafka-console-producer.sh \
+      --bootstrap-server onap-strimzi-kafka-bootstrap.onap:9092 \
+      --topic "$KAFKA_TOPIC" \
+      --producer-property security.protocol=SASL_PLAINTEXT \
+      --producer-property sasl.mechanism=SCRAM-SHA-512 \
+      --producer-property "sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required username=\"${KAFKA_USER}\" password=\"${KAFKA_PASSWORD}\";" \
+      --property parse.headers=true \
+      --property headers.key.separator=::: \
+      --property headers.delimiter=,,, \
+      --property parse.key=false || {
+        echo "Failed to produce message from file $file"
+        exit 1
+      }
+  fi
+  done
+  echo "$((i+1))/$FILE_DUPLICATION_FACTOR rounds completed"
+done
+
+echo "Message production completed."
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/Chart.yaml b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/Chart.yaml
new file mode 100644 (file)
index 0000000..f7b9238
--- /dev/null
@@ -0,0 +1,41 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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=================================================
+#
+
+apiVersion: v2
+name: energy-saving-rapp
+description: A Helm chart for Kubernetes
+
+# A chart can be either an 'application' or a 'library' chart.
+#
+# Application charts are a collection of templates that can be packaged into versioned archives
+# to be deployed.
+#
+# Library charts provide useful utilities or functions for the chart developer. They're included as
+# a dependency of application charts to inject those utilities and functions into the rendering
+# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+type: application
+
+# This is the chart version. This version number should be incremented each time you make changes
+# to the chart and its templates, including the app version.
+# Versions are expected to follow Semantic Versioning (https://semver.org/)
+version: 0.1.0
+
+# This is the version number of the application being deployed. This version number should be
+# incremented each time you make changes to the application. Versions are not expected to
+# follow Semantic Versioning. They should reflect the version the application is using.
+# It is recommended to use it with quotes.
+appVersion: "1.16.0"
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/resources/config/config.json b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/resources/config/config.json
new file mode 100644 (file)
index 0000000..2fbd20f
--- /dev/null
@@ -0,0 +1,35 @@
+{
+  "SME": {
+    "sme_discovery_endpoint": "{{ .Values.environment.smeDiscoveryEndpoint }}",
+    "host": "localhost",
+    "port": 31575,
+    "ncmp_invoker_id": "{{ .Values.environment.appId }}",
+    "ncmp_api_name": "{{ .Values.ncmp.apiName }}",
+    "ncmp_resource_name": "{{ .Values.ncmp.resourceName }}",
+    "resource_id": "{{ .Values.ncmp.resourceId}}",
+    "influxdb_invoker_id": "{{ .Values.environment.appId }}",
+    "influxdb_api_name": "{{ .Values.influxdb.apiName }}",
+    "influxdb_resource_name": "{{ .Values.influxdb.resourceName }}",
+    "kserve_invoker_id": "{{ .Values.environment.appId }}",
+    "kserve_api_name": "{{ .Values.kserve.apiName }}",
+    "kserve_resource_name": "{{ .Values.kserve.resourceName }}",
+    "teiv_invoker_id": "{{ .Values.environment.appId }}",
+    "teiv_api_name": "{{ .Values.teiv.apiName }}",
+    "teiv_resource_name": "{{ .Values.teiv.resourceName }}",
+    "odufunction_id": "{{ .Values.teiv.oduFunctionId }}"
+  },
+  "DB": {
+    "host": "localhost",
+    "port": 8086,
+    "bucket": "{{ .Values.influxdb.bucket }}",
+    "org": "{{ .Values.influxdb.org }}",
+    "token": "{{ .Values.influxdb.token }}",
+    "user": "{{ .Values.influxdb.user }}",
+    "password": "{{ .Values.influxdb.password }}",
+    "example_data_file": "example_data.json",
+    "database": "{{ .Values.influxdb.bucket }}",
+    "measurement": "CellReports",
+    "ssl": false,
+    "address": "http://localhost:8086"
+  }
+}
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/NOTES.txt b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/NOTES.txt
new file mode 100644 (file)
index 0000000..3766040
--- /dev/null
@@ -0,0 +1,41 @@
+{{/*
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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=================================================
+#
+*/}}
+
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+  {{- range .paths }}
+  http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
+  {{- end }}
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "energy-saving.fullname" . }})
+  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+  echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+     NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+           You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "energy-saving.fullname" . }}'
+  export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "energy-saving.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+  echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+  export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "energy-saving.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+  export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+  echo "Visit http://127.0.0.1:8080 to use your application"
+  kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/_helpers.tpl b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/_helpers.tpl
new file mode 100644 (file)
index 0000000..b4e3f0c
--- /dev/null
@@ -0,0 +1,82 @@
+{{/*
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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=================================================
+#
+*/}}
+
+
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "energy-saving.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).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "energy-saving.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 }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "energy-saving.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "energy-saving.labels" -}}
+helm.sh/chart: {{ include "energy-saving.chart" . }}
+{{ include "energy-saving.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "energy-saving.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "energy-saving.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "energy-saving.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "energy-saving.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/configmap.yaml b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/configmap.yaml
new file mode 100644 (file)
index 0000000..1ad33be
--- /dev/null
@@ -0,0 +1,27 @@
+{{/*
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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=================================================
+#
+*/}}
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ include "energy-saving.name" . }}-configmap
+  labels:
+    {{- include "energy-saving.labels" . | nindent 4 }}
+data:
+{{ tpl (.Files.Glob "resources/config/config.json").AsConfig . | indent 2 }}
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/deployment.yaml b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/deployment.yaml
new file mode 100644 (file)
index 0000000..1ce26ac
--- /dev/null
@@ -0,0 +1,97 @@
+{{/*
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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=================================================
+#
+*/}}
+
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ include "energy-saving.fullname" . }}
+  labels:
+    {{- include "energy-saving.labels" . | nindent 4 }}
+spec:
+  {{- if not .Values.autoscaling.enabled }}
+  replicas: {{ .Values.replicaCount }}
+  {{- end }}
+  selector:
+    matchLabels:
+      {{- include "energy-saving.selectorLabels" . | nindent 6 }}
+  template:
+    metadata:
+      {{- with .Values.podAnnotations }}
+      annotations:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      labels:
+        {{- include "energy-saving.selectorLabels" . | nindent 8 }}
+    spec:
+      {{- with .Values.imagePullSecrets }}
+      imagePullSecrets:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      serviceAccountName: {{ include "energy-saving.serviceAccountName" . }}
+      securityContext:
+        {{- toYaml .Values.podSecurityContext | nindent 8 }}
+      containers:
+        - name: {{ .Chart.Name }}
+          securityContext:
+            {{- toYaml .Values.securityContext | nindent 12 }}
+          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+          imagePullPolicy: {{ .Values.image.pullPolicy }}
+          ports:
+            - name: http
+              containerPort: {{ .Values.service.port }}
+              protocol: TCP
+          resources:
+            {{- toYaml .Values.resources | nindent 12 }}
+          env:
+            - name: APP_ID
+              value: {{ .Values.environment.appId | quote }}
+            - name: SME_DISCOVERY_ENDPOINT
+              value: {{ .Values.environment.smeDiscoveryEndpoint | quote }}
+          volumeMounts:
+            - mountPath: /app/config.json
+              name: config
+              subPath: config.json
+          command:
+            {{- if .Values.appStartup.command }}
+            {{- toYaml .Values.appStartup.command | nindent 12 }}
+            {{- end }}
+          args:
+            {{- if .Values.appStartup.args }}
+            {{- toYaml .Values.appStartup.args | nindent 12 }}
+            {{- end }}
+      {{- with .Values.nodeSelector }}
+      nodeSelector:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.affinity }}
+      affinity:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.tolerations }}
+      tolerations:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      volumes:
+        - name: config
+          configMap:
+              name: {{ include "energy-saving.name" . }}-configmap
+              defaultMode: 0755
+              items:
+                - key: config.json
+                  path: config.json
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/hpa.yaml b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/hpa.yaml
new file mode 100644 (file)
index 0000000..4b3a7f2
--- /dev/null
@@ -0,0 +1,51 @@
+{{/*
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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=================================================
+#
+*/}}
+
+{{- if .Values.autoscaling.enabled }}
+apiVersion: autoscaling/v2
+kind: HorizontalPodAutoscaler
+metadata:
+  name: {{ include "energy-saving.fullname" . }}
+  labels:
+    {{- include "energy-saving.labels" . | nindent 4 }}
+spec:
+  scaleTargetRef:
+    apiVersion: apps/v1
+    kind: Deployment
+    name: {{ include "energy-saving.fullname" . }}
+  minReplicas: {{ .Values.autoscaling.minReplicas }}
+  maxReplicas: {{ .Values.autoscaling.maxReplicas }}
+  metrics:
+    {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
+    - type: Resource
+      resource:
+        name: cpu
+        target:
+          type: Utilization
+          averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
+    {{- end }}
+    {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
+    - type: Resource
+      resource:
+        name: memory
+        target:
+          type: Utilization
+          averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
+    {{- end }}
+{{- end }}
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/ingress.yaml b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/ingress.yaml
new file mode 100644 (file)
index 0000000..db3a007
--- /dev/null
@@ -0,0 +1,80 @@
+{{/*
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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=================================================
+#
+*/}}
+
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "energy-saving.fullname" . -}}
+{{- $svcPort := .Values.service.port -}}
+{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
+  {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
+  {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
+  {{- end }}
+{{- end }}
+{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1
+{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+  name: {{ $fullName }}
+  labels:
+    {{- include "energy-saving.labels" . | nindent 4 }}
+  {{- with .Values.ingress.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+spec:
+  {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
+  ingressClassName: {{ .Values.ingress.className }}
+  {{- end }}
+  {{- if .Values.ingress.tls }}
+  tls:
+    {{- range .Values.ingress.tls }}
+    - hosts:
+        {{- range .hosts }}
+        - {{ . | quote }}
+        {{- end }}
+      secretName: {{ .secretName }}
+    {{- end }}
+  {{- end }}
+  rules:
+    {{- range .Values.ingress.hosts }}
+    - host: {{ .host | quote }}
+      http:
+        paths:
+          {{- range .paths }}
+          - path: {{ .path }}
+            {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
+            pathType: {{ .pathType }}
+            {{- end }}
+            backend:
+              {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
+              service:
+                name: {{ $fullName }}
+                port:
+                  number: {{ $svcPort }}
+              {{- else }}
+              serviceName: {{ $fullName }}
+              servicePort: {{ $svcPort }}
+              {{- end }}
+          {{- end }}
+    {{- end }}
+{{- end }}
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/service.yaml b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/service.yaml
new file mode 100644 (file)
index 0000000..c4afd79
--- /dev/null
@@ -0,0 +1,34 @@
+{{/*
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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=================================================
+#
+*/}}
+
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "energy-saving.fullname" . }}
+  labels:
+    {{- include "energy-saving.labels" . | nindent 4 }}
+spec:
+  type: {{ .Values.service.type }}
+  ports:
+    - port: {{ .Values.service.port }}
+      targetPort: http
+      protocol: TCP
+      name: http
+  selector:
+    {{- include "energy-saving.selectorLabels" . | nindent 4 }}
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/serviceaccount.yaml b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/serviceaccount.yaml
new file mode 100644 (file)
index 0000000..fb25c15
--- /dev/null
@@ -0,0 +1,31 @@
+{{/*
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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=================================================
+#
+*/}}
+
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: {{ include "energy-saving.serviceAccountName" . }}
+  labels:
+    {{- include "energy-saving.labels" . | nindent 4 }}
+  {{- with .Values.serviceAccount.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+{{- end }}
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/values.yaml b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/values.yaml
new file mode 100644 (file)
index 0000000..1cc7102
--- /dev/null
@@ -0,0 +1,131 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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=================================================
+#
+
+# Default values for energy-saving.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+replicaCount: 1
+
+image:
+  repository: "nexus3.onap.org:10001/estdemoimages/es-rapp"
+  pullPolicy: Always
+  # Overrides the image tag whose default is the chart appVersion.
+  tag: "0.1.1"
+
+imagePullSecrets: []
+nameOverride: "energy-saving-rapp"
+fullnameOverride: "energy-saving-rapp"
+
+serviceAccount:
+  # Specifies whether a service account should be created
+  create: true
+  # Annotations to add to the service account
+  annotations: {}
+  # The name of the service account to use.
+  # If not set and create is true, a name is generated using the fullname template
+  name: ""
+
+podAnnotations: {}
+
+podSecurityContext: {}
+  # fsGroup: 2000
+
+securityContext: {}
+  # capabilities:
+  #   drop:
+  #   - ALL
+  # readOnlyRootFilesystem: true
+  # runAsNonRoot: true
+  # runAsUser: 1000
+
+service:
+  type: ClusterIP
+  port: 8080
+
+ingress:
+  enabled: false
+  className: ""
+  annotations: {}
+    # kubernetes.io/ingress.class: nginx
+    # kubernetes.io/tls-acme: "true"
+  hosts:
+    - host: chart-example.local
+      paths:
+        - path: /
+          pathType: ImplementationSpecific
+  tls: []
+  #  - secretName: chart-example-tls
+  #    hosts:
+  #      - chart-example.local
+
+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
+
+autoscaling:
+  enabled: false
+  minReplicas: 1
+  maxReplicas: 100
+  targetCPUUtilizationPercentage: 80
+  # targetMemoryUtilizationPercentage: 80
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
+environment:
+  appId: "energy-saving"
+  smeDiscoveryEndpoint: "http://sme-discovery.default.svc.cluster.local:8080/service-apis/v1/allServiceAPIs"
+
+influxdb:
+  token: "WcrfLfqC63uCxfDa15C1sb6WtG5fhzrS"
+  user: "admin"
+  password: "mySuP3rS3cr3tT0keN"
+  bucket: "pm-bucket"
+  org: "est"
+  apiName: "influxdb2-http"
+  resourceName: "root"
+
+
+ncmp:
+  apiName: "ncmp-dmi-plugin-http"
+  resourceName: "root"
+  resourceId: "/_3gpp-common-managed-element:ManagedElement=ManagedElement-002/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction=GNBDUFunction-001/_3gpp-nr-nrm-nrcelldu:NRCellDU=NRCellDU-001/attributes"
+
+kserve:
+  apiName: "es-predictor-http"
+  resourceName: "root"
+
+teiv:
+  apiName: "topology-exposure-http"
+  resourceName: "root"
+  oduFunctionId: "GNBDUFunction-001"
+
+appStartup:
+  command: ["/bin/sh", "-c"]
+  args: [ "python main.py --generate_db_data=True --use_sme_db=True --random_predictions=False" ]
+
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Definitions/asd.yaml b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Definitions/asd.yaml
new file mode 100755 (executable)
index 0000000..727004b
--- /dev/null
@@ -0,0 +1,30 @@
+tosca_definitions_version: tosca_simple_yaml_1_2\r
+\r
+description: rApp energy saving\r
+\r
+imports:\r
+  - asd_types.yaml\r
+\r
+topology_template:\r
+  node_templates:\r
+    applicationServiceDescriptor:\r
+      type: tosca.nodes.asd\r
+      description: "rapp-energy-saving"\r
+      properties:\r
+        descriptor_id: 364545c9-f1b1-48bb-a774-2b999e47692d\r
+        descriptor_invariant_id: 97f18c6e-125d-470e-81a2-a36034989acd\r
+        descriptor_version: 1.0\r
+        schema_version: 2.0\r
+        function_description: rApp description\r
+        provider: Ericsson Software Technology (O-RAN SC NONRTRIC team)\r
+        application_name: rapp-energy-saving\r
+        application_version: 1.0\r
+      artifacts:\r
+        energy-saving:\r
+          type: tosca.artifacts.asd.deploymentItem\r
+          file: "Artifacts/Deployment/HELM/energy-saving-rapp-0.1.0.tgz"\r
+          properties:\r
+            artifact_type: "helm_chart"\r
+            target_server: "chartmuseum"\r
+            target_server_uri: "UPDATE_THIS_CHART_MUSEUM_POST_CHARTS_URI"\r
+            item_id: 1
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Definitions/asd_types.yaml b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Definitions/asd_types.yaml
new file mode 100755 (executable)
index 0000000..7ac8c10
--- /dev/null
@@ -0,0 +1,72 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+description: ASD types definitions version 0.1
+node_types:
+  tosca.nodes.asd:
+    derived_from: tosca.nodes.Root
+    description: "The ASD node type"
+    version: 0.1
+    properties:
+      descriptor_id:
+        type: string # UUID
+        required: true
+        description: Identifier of this ASD. It is in UUID format as specified in RFC 4122
+      descriptor_invariant_id:
+        type: string # UUID
+        required: true
+        description: >
+          Identifier of this descriptor in a version independent manner. This attribute
+          is invariant across versions of ASD. It is in UUID format as specified in RFC 4122
+      descriptor_version:
+        type: string
+        required: true
+        description: Identifies the version of the ASD.
+      schema_version:
+        type: string
+        required: true
+        description: Identifies the Identifies the version of this ASD’s schema.
+      function_description:
+        type: string
+        required: false
+        description: Description of the application service described by this ASD.
+      provider:
+        type: string
+        required: true
+        description: Identifies the provider of the ASD.
+      application_name:
+        type: string
+        required: true
+        description: Name to identify the application service described by this ASD
+      application_version:
+        type: string
+        required: true
+        description: Identifies the version of the application service described by this ASD.
+
+artifact_types:
+tosca.artifacts.asd.deploymentItem:
+  version: 0.1
+  derived_from: tosca.artifacts.Root
+  description: "Describes the artifact type of asd deployment item"
+  file: "Relative path of the artifact in the package"
+  properties:
+    item_id:
+      description: "The identifier of this asd deployment item"
+      required: true
+      type: string
+    artifact_type:
+      description: >
+        Specify artifact type.
+      required: true
+      type: string
+      constraints:
+        - valid_values: ["helm_chart"]
+    target_server:
+      description: >
+        Specify target server for artifact.
+      required: true
+      type: string
+      constraints:
+        - valid_values: [ "chartmuseum" ]
+    target_server_uri:
+      description: "URI of the target server"
+      required: true
+      type: string
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Acm/definition/compositions.json b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Acm/definition/compositions.json
new file mode 100644 (file)
index 0000000..9afd529
--- /dev/null
@@ -0,0 +1,254 @@
+{\r
+  "tosca_definitions_version": "tosca_simple_yaml_1_3",\r
+  "data_types": {\r
+    "onap.datatypes.ToscaConceptIdentifier": {\r
+      "derived_from": "tosca.datatypes.Root",\r
+      "properties": {\r
+        "name": {\r
+          "type": "string",\r
+          "required": true\r
+        },\r
+        "version": {\r
+          "type": "string",\r
+          "required": true\r
+        }\r
+      }\r
+    },\r
+    "org.onap.datatypes.policy.clamp.acm.kserveAutomationCompositionElement.KserveInferenceEntity": {\r
+      "version": "1.0.0",\r
+      "derived_from": "tosca.datatypes.Root",\r
+      "properties": {\r
+        "kserveEntityId": {\r
+          "type": "onap.datatypes.ToscaConceptIdentifier",\r
+          "required": true,\r
+          "description": "The name and version of a Configuration Entity to be handled by the Kserve Automation Composition Element"\r
+        },\r
+        "name": {\r
+          "type": "string",\r
+          "required": true,\r
+          "description": "Inference service name to be created"\r
+        },\r
+        "payload": {\r
+          "type": "string",\r
+          "required": true,\r
+          "description": "Inference Service payload"\r
+        }\r
+      }\r
+    }\r
+  },\r
+  "node_types": {\r
+    "org.onap.policy.clamp.acm.Participant": {\r
+      "version": "1.0.1",\r
+      "derived_from": "tosca.nodetypes.Root",\r
+      "properties": {\r
+        "provider": {\r
+          "type": "string",\r
+          "required": false\r
+        }\r
+      }\r
+    },\r
+    "org.onap.policy.clamp.acm.AutomationCompositionElement": {\r
+      "version": "1.0.1",\r
+      "derived_from": "tosca.nodetypes.Root",\r
+      "properties": {\r
+        "provider": {\r
+          "type": "string",\r
+          "required": false\r
+        },\r
+        "participantType": {\r
+          "type": "onap.datatypes.ToscaConceptIdentifier",\r
+          "required": true\r
+        },\r
+        "startPhase": {\r
+          "type": "integer",\r
+          "required": false,\r
+          "constraints": [\r
+            {\r
+              "greater-or-equal": 0\r
+            }\r
+          ],\r
+          "metadata": {\r
+            "common": true\r
+          },\r
+          "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"\r
+        },\r
+        "passiveToRunningTimeout": {\r
+          "type": "integer",\r
+          "required": false,\r
+          "constraints": [\r
+            {\r
+              "greater_or_equal": 0\r
+            }\r
+          ],\r
+          "default": 60,\r
+          "metadata": {\r
+            "common": true\r
+          },\r
+          "description": "The maximum time in seconds to wait for a state chage from passive to running"\r
+        },\r
+        "runningToPassiveTimeout": {\r
+          "type": "integer",\r
+          "required": false,\r
+          "constraints": [\r
+            {\r
+              "greater_or_equal": 0\r
+            }\r
+          ],\r
+          "default": 60,\r
+          "metadata": {\r
+            "common": true\r
+          },\r
+          "description": "The maximum time in seconds to wait for a state chage from running to passive"\r
+        },\r
+        "passiveToUninitializedTimeout": {\r
+          "type": "integer",\r
+          "required": false,\r
+          "constraints": [\r
+            {\r
+              "greater_or_equal": 0\r
+            }\r
+          ],\r
+          "default": 60,\r
+          "metadata": {\r
+            "common": true\r
+          },\r
+          "description": "The maximum time in seconds to wait for a state chage from passive to uninitialized"\r
+        }\r
+      }\r
+    },\r
+    "org.onap.policy.clamp.acm.AutomationComposition": {\r
+      "version": "1.0.1",\r
+      "derived_from": "tosca.nodetypes.Root",\r
+      "properties": {\r
+        "provider": {\r
+          "type": "string",\r
+          "required": false,\r
+          "metadata": {\r
+            "common": true\r
+          }\r
+        },\r
+        "elements": {\r
+          "type": "list",\r
+          "required": true,\r
+          "metadata": {\r
+            "common": true\r
+          },\r
+          "entry_schema": {\r
+            "type": "onap.datatypes.ToscaConceptIdentifier"\r
+          }\r
+        }\r
+      }\r
+    },\r
+    "org.onap.policy.clamp.acm.KserveAutomationCompositionElement": {\r
+      "version": "1.0.1",\r
+      "derived_from": "org.onap.policy.clamp.acm.AutomationCompositionElement",\r
+      "properties": {\r
+        "kserveInferenceEntities": {\r
+          "type": "list",\r
+          "required": true,\r
+          "entry_schema": {\r
+            "type": "org.onap.datatypes.policy.clamp.acm.kserveAutomationCompositionElement.KserveInferenceEntity",\r
+            "type_version": "1.0.0"\r
+          },\r
+          "description": "The configuration entities of Kserve inference service"\r
+        }\r
+      }\r
+    },\r
+    "org.onap.policy.clamp.acm.K8SMicroserviceAutomationCompositionElement": {\r
+      "version": "1.0.0",\r
+      "derived_from": "org.onap.policy.clamp.acm.AutomationCompositionElement",\r
+      "properties": {\r
+        "chart": {\r
+          "type": "string",\r
+          "required": true\r
+        },\r
+        "configs": {\r
+          "type": "list",\r
+          "required": false\r
+        },\r
+        "requirements": {\r
+          "type": "string",\r
+          "required": false\r
+        },\r
+        "templates": {\r
+          "type": "list",\r
+          "required": false,\r
+          "entry_schema": null\r
+        },\r
+        "values": {\r
+          "type": "string",\r
+          "required": true\r
+        }\r
+      }\r
+    }\r
+  },\r
+  "topology_template": {\r
+    "node_templates": {\r
+      "org.onap.policy.clamp.acm.KserveParticipant": {\r
+        "version": "2.3.4",\r
+        "type": "org.onap.policy.clamp.acm.Participant",\r
+        "type_version": "1.0.1",\r
+        "description": "Participant for Kserve requests",\r
+        "properties": {\r
+          "provider": "ONAP"\r
+        }\r
+      },\r
+      "org.onap.k8s.acm.K8SAutomationCompositionParticipant": {\r
+        "version": "2.3.4",\r
+        "type": "org.onap.policy.clamp.acm.Participant",\r
+        "type_version": "1.0.1",\r
+        "description": "Participant for K8S",\r
+        "properties": {\r
+          "provider": "ONAP"\r
+        }\r
+      },\r
+      "onap.policy.clamp.ac.element.KserveAutomationCompositionElement": {\r
+        "version": "1.2.3",\r
+        "type": "org.onap.policy.clamp.acm.KserveAutomationCompositionElement",\r
+        "type_version": "1.0.1",\r
+        "description": "Automation composition element for the Kserve Requests",\r
+        "properties": {\r
+          "provider": "ONAP",\r
+          "startPhase": 0,\r
+          "participantType": {\r
+            "name": "org.onap.policy.clamp.acm.KserveParticipant",\r
+            "version": "2.3.4"\r
+          },\r
+          "uninitializedToPassiveTimeout": 300,\r
+          "statusCheckInterval": 30\r
+        }\r
+      },\r
+      "onap.policy.clamp.ac.element.K8S_StarterAutomationCompositionElement": {\r
+        "version": "1.2.3",\r
+        "type": "org.onap.policy.clamp.acm.K8SMicroserviceAutomationCompositionElement",\r
+        "type_version": "1.0.0",\r
+        "description": "Automation composition element for the K8S microservice for AC Element Starter",\r
+        "properties": {\r
+          "provider": "ONAP",\r
+          "startPhase": 1,\r
+          "uninitializedToPassiveTimeout": 300,\r
+          "podStatusCheckInterval": 30\r
+        }\r
+      },\r
+      "onap.policy.clamp.ac.element.AutomationCompositionDefinition": {\r
+        "version": "1.2.3",\r
+        "type": "org.onap.policy.clamp.acm.AutomationComposition",\r
+        "type_version": "1.0.1",\r
+        "description": "Automation composition for rapp deployment",\r
+        "properties": {\r
+          "provider": "ONAP",\r
+          "elements": [\r
+            {\r
+              "name": "onap.policy.clamp.ac.element.K8S_StarterAutomationCompositionElement",\r
+              "version": "1.2.3"\r
+            },\r
+            {\r
+              "name": "onap.policy.clamp.ac.element.KserveAutomationCompositionElement",\r
+              "version": "1.2.3"\r
+            }\r
+          ]\r
+        }\r
+      }\r
+    }\r
+  }\r
+}
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Acm/instances/es-instance.json b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Acm/instances/es-instance.json
new file mode 100644 (file)
index 0000000..4b5e18f
--- /dev/null
@@ -0,0 +1,56 @@
+{
+  "name": "ESInstance0",
+  "version": "1.0.1",
+  "compositionId": "DO_NOT_CHANGE_THIS_COMPOSITION_ID",
+  "description": "Energy Saving automation composition instance 0",
+  "elements": {
+    "d7be552e-bcc5-4478-b64d-797dbaec8f55": {
+      "id": "d7be552e-bcc5-4478-b64d-797dbaec8f55",
+      "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": "energy-saving-rapp",
+            "version": "0.1.0"
+          },
+          "namespace": "nonrtric",
+          "releaseName": "energy-saving-rapp",
+          "podName": "energy-saving-rapp",
+          "repository": {
+            "repoName": "local",
+            "address": "UPDATE_THIS_ADDRESS"
+          },
+          "overrideParams": {
+            "environment.appId": "DO_NOT_CHANGE_THIS_RAPP_INSTANCE_ID",
+            "environment.smeDiscoveryEndpoint": "DO_NOT_CHANGE_THIS_SME_DISCOVERY_ENDPOINT"
+          }
+        }
+      }
+    },
+    "709c62b3-8918-41b9-a747-d21eb79c6c20": {
+      "id": "709c62b3-8918-41b9-a747-d21eb79c6c20",
+      "definition": {
+        "name": "onap.policy.clamp.ac.element.KserveAutomationCompositionElement",
+        "version": "1.2.3"
+      },
+      "description": "Starter Automation Composition Element for the Demo",
+      "properties": {
+        "kserveInferenceEntities": [
+          {
+            "kserveInferenceEntityId": {
+              "name": "es-aiml-model-entity",
+              "version": "1.0.1"
+            },
+            "name": "es-aiml-model",
+            "namespace": "kserve-test",
+            "payload": "{\"apiVersion\": \"serving.kserve.io/v1beta1\",\"kind\": \"InferenceService\",\"metadata\": {\"name\": \"es-aiml-model\"},\"spec\": {\"predictor\": {\"tensorflow\": {\"storageUri\": \"https://huggingface.co/saulgillEST/es-aiml-model/resolve/main/Model.zip\"}}}}"
+          }
+        ]
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Acm/instances/k8s-instance.json b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Acm/instances/k8s-instance.json
new file mode 100644 (file)
index 0000000..8c073d3
--- /dev/null
@@ -0,0 +1,35 @@
+{
+  "name": "K8ESInstance0",
+  "version": "1.0.1",
+  "compositionId": "DO_NOT_CHANGE_THIS_COMPOSITION_ID",
+  "description": "Energy Saving automation composition instance 0",
+  "elements": {
+    "d7be552e-bcc5-4478-b64d-797dbaec8f55": {
+      "id": "d7be552e-bcc5-4478-b64d-797dbaec8f55",
+      "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": "energy-saving-rapp",
+            "version": "0.1.0"
+          },
+          "namespace": "nonrtric",
+          "releaseName": "energy-saving-rapp",
+          "podName": "energy-saving-rapp",
+          "repository": {
+            "repoName": "local",
+            "address": "http://10.101.1.170:18080"
+          },
+          "overrideParams": {
+            "environment.appId": "DO_NOT_CHANGE_THIS_RAPP_INSTANCE_ID",
+            "environment.smeDiscoveryEndpoint": "DO_NOT_CHANGE_THIS_SME_DISCOVERY_ENDPOINT"
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Acm/instances/kserve-instance.json b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Acm/instances/kserve-instance.json
new file mode 100755 (executable)
index 0000000..3904412
--- /dev/null
@@ -0,0 +1,29 @@
+{
+  "name": "KserveInstance0",
+  "version": "1.0.1",
+  "compositionId": "DO_NOT_CHANGE_THIS_COMPOSITION_ID",
+  "description": "Demo automation composition instance 0",
+  "elements": {
+    "709c62b3-8918-41b9-a747-d21eb79c6c20": {
+      "id": "709c62b3-8918-41b9-a747-d21eb79c6c20",
+      "definition": {
+        "name": "onap.policy.clamp.ac.element.KserveAutomationCompositionElement",
+        "version": "1.2.3"
+      },
+      "description": "Starter Automation Composition Element for the Demo",
+      "properties": {
+        "kserveInferenceEntities": [
+          {
+            "kserveInferenceEntityId": {
+              "name": "es-aiml-model-entity",
+              "version": "1.0.1"
+            },
+            "name": "es-aiml-model",
+            "namespace": "kserve-test",
+            "payload": "{\"apiVersion\": \"serving.kserve.io/v1beta1\",\"kind\": \"InferenceService\",\"metadata\": {\"name\": \"es-aiml-model\"},\"spec\": {\"predictor\": {\"tensorflow\": {\"storageUri\": \"https://huggingface.co/saulgillEST/es-aiml-model/resolve/main/Model.zip\"}}}}"
+          }
+        ]
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/invokers/invoker-app1.json b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/invokers/invoker-app1.json
new file mode 100755 (executable)
index 0000000..0400730
--- /dev/null
@@ -0,0 +1,14 @@
+[
+  {
+    "apiInvokerInformation": "DO_NOT_CHANGE_THIS_RAPP_INSTANCE_ID",
+    "apiList": [
+      {}
+    ],
+    "notificationDestination": "http://invoker-app1:8086/callback",
+    "onboardingInformation": {
+      "apiInvokerPublicKey": "{PUBLIC_KEY_INVOKER_1}",
+      "apiInvokerCertificate": "apiInvokerCertificate"
+    },
+    "requestTestNotification": true
+  }
+]
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/invokers/invoker-influxdb.json b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/invokers/invoker-influxdb.json
new file mode 100644 (file)
index 0000000..1514bc9
--- /dev/null
@@ -0,0 +1,14 @@
+[
+  {
+    "apiInvokerInformation": "DO_NOT_CHANGE_THIS_RAPP_INSTANCE_ID",
+    "apiList": [
+      { "apiName": "influxdb2-http" }
+    ],
+    "notificationDestination": "http://NOT_USED_HERE",
+    "onboardingInformation": {
+      "apiInvokerPublicKey": "{PUBLIC_KEY_INVOKER_1}",
+      "apiInvokerCertificate": "apiInvokerCertificate"
+    },
+    "requestTestNotification": true
+  }
+]
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/invokers/invoker-kserve-predictor.json b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/invokers/invoker-kserve-predictor.json
new file mode 100644 (file)
index 0000000..60b994d
--- /dev/null
@@ -0,0 +1,14 @@
+[
+  {
+    "apiInvokerInformation": "DO_NOT_CHANGE_THIS_RAPP_INSTANCE_ID",
+    "apiList": [
+      { "apiName": "ES-Predictor-API" }
+    ],
+    "notificationDestination": "http://NOT_USED_HERE",
+    "onboardingInformation": {
+      "apiInvokerPublicKey": "{PUBLIC_KEY_INVOKER_1}",
+      "apiInvokerCertificate": "apiInvokerCertificate"
+    },
+    "requestTestNotification": true
+  }
+]
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/invokers/invoker-ncmp.json b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/invokers/invoker-ncmp.json
new file mode 100644 (file)
index 0000000..ba325b5
--- /dev/null
@@ -0,0 +1,14 @@
+[
+  {
+    "apiInvokerInformation": "DO_NOT_CHANGE_THIS_RAPP_INSTANCE_ID",
+    "apiList": [
+      { "apiName": "ncmp-dmi-plugin-http" }
+    ],
+    "notificationDestination": "http://NOT_USED_HERE",
+    "onboardingInformation": {
+      "apiInvokerPublicKey": "{PUBLIC_KEY_INVOKER_1}",
+      "apiInvokerCertificate": "apiInvokerCertificate"
+    },
+    "requestTestNotification": true
+  }
+]
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/providers/es-model-provider-function.json b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/providers/es-model-provider-function.json
new file mode 100644 (file)
index 0000000..65cd00b
--- /dev/null
@@ -0,0 +1,20 @@
+{\r
+  "apiProvDomInfo": "ES Model Provider domain",\r
+  "apiProvFuncs": [\r
+    {\r
+      "apiProvFuncInfo": "ES Prediction as APF",\r
+      "apiProvFuncRole": "APF",\r
+      "regInfo": {\r
+        "apiProvPubKey": "NOT USED here"\r
+      }\r
+    },\r
+    {\r
+      "apiProvFuncInfo": "ES Prediction as AEF",\r
+      "apiProvFuncRole": "AEF",\r
+      "regInfo": {\r
+        "apiProvPubKey": "NOT USED here"\r
+      }\r
+    }\r
+  ],\r
+  "regSec": "plain"\r
+}
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/providers/provider-function-1.json b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/providers/provider-function-1.json
new file mode 100644 (file)
index 0000000..b612ae5
--- /dev/null
@@ -0,0 +1,20 @@
+{\r
+  "apiProvDomInfo": "Provider domain",\r
+  "apiProvFuncs": [\r
+    {\r
+      "apiProvFuncInfo": "Energy Saving as APF",\r
+      "apiProvFuncRole": "APF",\r
+      "regInfo": {\r
+        "apiProvPubKey": "NOT USED here"\r
+      }\r
+    },\r
+    {\r
+      "apiProvFuncInfo": "Energy Saving as AEF",\r
+      "apiProvFuncRole": "AEF",\r
+      "regInfo": {\r
+        "apiProvPubKey": "NOT USED here"\r
+      }\r
+    }\r
+  ],\r
+  "regSec": "plain"\r
+}
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/serviceapis/api-set-1.json b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/serviceapis/api-set-1.json
new file mode 100644 (file)
index 0000000..7287685
--- /dev/null
@@ -0,0 +1,32 @@
+{\r
+  "apiName": "Energy Saving API Set 1",\r
+  "description": "Simple Energy Saving API",\r
+  "aefProfiles": [\r
+    {\r
+      "aefId": "Energy Saving as AEF",\r
+      "description": "Energy Saving API",\r
+      "versions": [\r
+        {\r
+          "apiVersion": "",\r
+          "resources": [\r
+            {\r
+              "resourceName": "energysaving",\r
+              "commType": "REQUEST_RESPONSE",\r
+              "uri": "/energysaving/v1",\r
+              "operations": [\r
+                "GET"\r
+              ]\r
+            }\r
+          ]\r
+        }\r
+      ],\r
+      "protocol": "HTTP_1_1",\r
+      "interfaceDescriptions": [\r
+        {\r
+          "ipv4Addr": "energysaving.nonrtric.svc.cluster.local",\r
+          "port": 8080\r
+        }\r
+      ]\r
+    }\r
+  ]\r
+}
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/serviceapis/api-set-2.json b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/serviceapis/api-set-2.json
new file mode 100644 (file)
index 0000000..19b1a25
--- /dev/null
@@ -0,0 +1,32 @@
+{\r
+  "apiName": "Energy Saving API Set 2",\r
+  "description": "Simple Energy Saving API for Subpath",\r
+  "aefProfiles": [\r
+    {\r
+      "aefId": "Energy Saving as AEF",\r
+      "description": "Energy Saving API for Subpath",\r
+      "versions": [\r
+        {\r
+          "apiVersion": "",\r
+          "resources": [\r
+            {\r
+              "resourceName": "energysaving",\r
+              "commType": "REQUEST_RESPONSE",\r
+              "uri": "/energysaving/v1/subpath1",\r
+              "operations": [\r
+                "GET"\r
+              ]\r
+            }\r
+          ]\r
+        }\r
+      ],\r
+      "protocol": "HTTP_1_1",\r
+      "interfaceDescriptions": [\r
+        {\r
+          "ipv4Addr": "energysaving.nonrtric.svc.cluster.local",\r
+          "port": 8080\r
+        }\r
+      ]\r
+    }\r
+  ]\r
+}
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/serviceapis/api-set-kserve-predictor.json b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Sme/serviceapis/api-set-kserve-predictor.json
new file mode 100644 (file)
index 0000000..84d8dbf
--- /dev/null
@@ -0,0 +1,36 @@
+{\r
+  "apiName": "es-predictor-http",\r
+  "description": "ES Prediction model endpoints",\r
+  "aefProfiles": [\r
+    {\r
+      "aefId": "ES Predictor as AEF",\r
+      "description": "ES predictor API",\r
+      "versions": [\r
+        {\r
+          "apiVersion": "",\r
+          "resources": [\r
+            {\r
+              "resourceName": "root",\r
+              "commType": "REQUEST_RESPONSE",\r
+              "uri": "/",\r
+              "operations": [\r
+                "POST",\r
+                "GET",\r
+                "PUT",\r
+                "DELETE",\r
+                "PATCH"\r
+              ]\r
+            }\r
+          ]\r
+        }\r
+      ],\r
+      "protocol": "HTTP_1_1",\r
+      "interfaceDescriptions": [\r
+        {\r
+          "ipv4Addr": "es-aiml-model-predictor.kserve-test.svc.cluster.local",\r
+          "port": 80\r
+        }\r
+      ]\r
+    }\r
+  ]\r
+}
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/TOSCA-Metadata/TOSCA.meta b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/TOSCA-Metadata/TOSCA.meta
new file mode 100644 (file)
index 0000000..3da5f0d
--- /dev/null
@@ -0,0 +1,5 @@
+TOSCA-Meta-File-Version: 1.0\r
+CSAR-Version: 1.0\r
+Created-By: Ericsson Software Technology (O-RAN SC NONRTRIC team)\r
+Entry-Definitions: Definitions/asd.yaml\r
+ETSI-Entry-Manifest: asd.mf
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/asd.mf b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/asd.mf
new file mode 100644 (file)
index 0000000..0dcefc3
--- /dev/null
@@ -0,0 +1,23 @@
+metadata:\r
+  application_name: rapp-energy-saving\r
+  application_provider: Ericsson Software Technology (O-RAN SC NONRTRIC team)\r
+  release_date_time: 2025-06-03T12:34:00+00:00\r
+  entry_definition_type: asd\r
+\r
+Source: asd.mf\r
+Source: Definitions/asd.yaml\r
+Source: Definitions/asd_types.yaml\r
+Source: TOSCA-Metadata/TOSCA.meta\r
+Source: Files/Acm/definition/compositions.json\r
+Source: Files/Acm/instances/es-instance.json\r
+Source: Files/Acm/instances/k8s-instance.json\r
+Source: Files/Acm/instances/kserve-instance.json\r
+Source: Files/SME/invokers/invoker-app1.json\r
+Source: Files/SME/invokers/invoker-ncmp.json\r
+Source: Files/SME/invokers/invoker-kserve-predictor.json\r
+Source: Files/SME/invokers/invoker-influxdb.json\r
+Source: Files/Sme/provider/provider-function-1.json\r
+Source: Files/Sme/provider/es-model-provider-function.json\r
+Source: Files/Sme/serviceapis/api-set-1.json\r
+Source: Files/Sme/serviceapis/api-set-2.json\r
+Source: Files/Sme/serviceapis/api-set-kserve-predictor.json\r
diff --git a/sample-rapp-generator/es-demo-rapp/src/assist.py b/sample-rapp-generator/es-demo-rapp/src/assist.py
new file mode 100644 (file)
index 0000000..27d6fe8
--- /dev/null
@@ -0,0 +1,98 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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 json
+import random
+import requests
+import logging
+from sme_client import SMEClient
+
+logger = logging.getLogger(__name__)
+
+class ASSIST(object):
+
+    def __init__(self):
+        self.kserve_url = None
+        self.invoker_id = None
+        self.api_name = None
+        self.resource_name = None
+        self.config()
+        self.get_url_from_sme()
+
+    def config(self):
+        with open('config.json', 'r') as f:
+            config = json.load(f)
+
+        assist_config = config.get("SME", {})
+        self.invoker_id = assist_config.get("kserve_invoker_id")
+        self.api_name = assist_config.get("kserve_api_name")
+        self.resource_name = assist_config.get("kserve_resource_name")
+
+    def get_url_from_sme(self):
+        sme_client = SMEClient(
+            invoker_id=self.invoker_id,
+            api_name=self.api_name,
+            resource_name=self.resource_name
+        )
+
+        self.kserve_url = sme_client.discover_service()
+
+        if self.kserve_url is None:
+            logger.error("Failed to discover KServe URL.")
+            return None
+        logger.info(f"Discovered KServe URL: {self.kserve_url}")
+
+    def send_request_to_server(self, json_data, randomize=False):
+
+        if(not randomize):
+            with open('input.json', 'w') as f:
+                json.dump(json_data, f)
+
+            # Commented out for local testing
+            # url = 'http://localhost:8080/v1/models/es-aiml-model:predict'
+            # headers = {'Host': 'es-aiml-model-predictor-default.default.svc.cluster.local'}
+            url = self.kserve_url + 'v1/models/es-aiml-model:predict'
+            host = self.kserve_url.split('/')[2].split(':')[0]
+            headers = {'Host': host }
+
+            with open('input.json', 'rb') as f:
+                response = requests.post(url, headers=headers, data=f)
+            logger.info("Prediction result")
+            logger.info(response.text)
+            return response.status_code, response.text
+        else:
+            data = json.dumps({
+                "predictions": self.random_predictions()
+            })
+
+            logger.info("Prediction result")
+            logger.info(data)
+
+            return 200, data
+
+    def random_predictions(self):
+        predictions = []
+        # Generate random decision for all rows
+        power_value = random.random()
+        for _ in range(3):  # Generate 3 rows of predictions
+            if power_value < 0.5:  # 50% chance for all values < 0.4
+                row = [random.uniform(0.0, 0.039) for _ in range(3)]
+            else:  # 50% chance for all values >= 0.4
+                row = [random.uniform(0.4, 1.0) for _ in range(3)]
+            predictions.append(row)
+
+        return predictions
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/src/config.json b/sample-rapp-generator/es-demo-rapp/src/config.json
new file mode 100644 (file)
index 0000000..c39467d
--- /dev/null
@@ -0,0 +1,35 @@
+{
+  "SME": {
+    "sme_discovery_endpoint": "http://localhost:31575/service-apis/v1/allServiceAPIs",
+    "host": "localhost",
+    "port": 31575,
+    "ncmp_invoker_id": "6a965002-ed7c-4f69-855c-ab9196f86e61",
+    "ncmp_api_name": "ncmp-dmi-plugin-http",
+    "ncmp_resource_name": "root",
+    "resource_id": "/_3gpp-common-managed-element:ManagedElement=ManagedElement-002/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction=GNBDUFunction-001/_3gpp-nr-nrm-nrcelldu:NRCellDU=NRCellDU-001/attributes",
+    "influxdb_invoker_id": "6a965002-ed7c-4f69-855c-ab9196f86e61",
+    "influxdb_api_name": "influxdb2-http",
+    "influxdb_resource_name": "root",
+    "kserve_invoker_id": "6a965002-ed7c-4f69-855c-ab9196f86e61",
+    "kserve_api_name": "es-predictor-http",
+    "kserve_resource_name": "root",
+    "teiv_invoker_id": "6a965002-ed7c-4f69-855c-ab9196f86e61",
+    "teiv_api_name": "topology-exposure-http",
+    "teiv_resource_name": "root",
+    "odufunction_id": "GNBDUFunction-001"
+  },
+  "DB": {
+    "host": "localhost",
+    "port": 8086,
+    "bucket": "pm-bucket",
+    "org": "est",
+    "token": "WcrfLfqC63uCxfDa15C1sb6WtG5fhzrS",
+    "user": "admin",
+    "password": "mySuP3rS3cr3tT0keN",
+    "example_data_file": "example_data.json",
+    "database": "pm-bucket",
+    "measurement": "CellReports",
+    "ssl": false,
+    "address": "http://localhost:8086"
+  }
+}
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/src/data.py b/sample-rapp-generator/es-demo-rapp/src/data.py
new file mode 100644 (file)
index 0000000..74662ec
--- /dev/null
@@ -0,0 +1,207 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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 time
+import logging
+from influxdb.exceptions import InfluxDBClientError, InfluxDBServerError
+from requests.exceptions import RequestException, ConnectionError
+import influxdb_client
+from datetime import datetime, timedelta
+import random
+import json
+from sme_client import SMEClient
+from influxdb_client.client.write_api import SYNCHRONOUS
+import pandas as pd
+
+logger = logging.getLogger(__name__)
+
+class DATABASE(object):
+
+    def __init__(self, dbname='Timeseries', user='user', password='password', host="influxdb_ip", port='influxdb_port', path='', ssl=False):
+        self.token = None
+        self.org = None
+        self.bucket = None
+        self.data = None
+        self.host = host
+        self.port = port
+        self.user = user
+        self.password = password
+        self.ssl = ssl
+        self.dbname = dbname
+        self.client = None
+        self.address = None
+        self.influx_invoker_id = None
+        self.influx_api_name = None
+        self.influx_resource_name = None
+        self.config()
+
+        # Set pandas options to display all rows and columns
+        pd.set_option('display.max_rows', None)  # Show all rows
+        pd.set_option('display.max_columns', None)  # Show all columns
+        pd.set_option('display.width', 1000)  # Adjust the width to avoid line breaks
+        pd.set_option('display.colheader_justify', 'left')  # Align column headers to the left
+
+    def get_url_from_sme(self):
+        sme_client = SMEClient(
+            invoker_id=self.influx_invoker_id,
+            api_name=self.influx_api_name,
+            resource_name=self.influx_resource_name
+        )
+
+        self.influx_url = sme_client.discover_service()
+
+        logger.info("InfluxDB URL: {}".format(self.influx_url))
+
+        if self.influx_url is not None:
+            self.address = self.influx_url
+            logger.debug(f"InfluxDB URL: {self.influx_url}")
+            self.host = self.influx_url.split(":")[1].replace("//", "")
+            logger.debug(f"InfluxDB Host: {self.host}")
+            self.port = self.influx_url.split(":")[2].split("/")[0]
+            logger.debug(f"InfluxDB Port: {self.port}")
+            self.address = self.influx_url.rstrip('/')
+            logger.debug(f"InfluxDB Address: {self.address}")
+        else:
+            logger.error("Failed to discover InfluxDB URL from SME.")
+
+    # Connect with influxdb
+    def connect(self):
+        if self.client is not None:
+            self.client.close()
+
+        try:
+            self.client = influxdb_client.InfluxDBClient(url=self.address, org=self.org, token=self.token)
+            version = self.client.version()
+            logger.info("Connected to Influx Database, InfluxDB version : {}".format(version))
+            return True
+
+        except (RequestException, InfluxDBClientError, InfluxDBServerError, ConnectionError):
+            logger.error("Failed to establish a new connection with InflulxDB, Please check your url/hostname")
+            time.sleep(120)
+
+    # Query information
+    def read_data(self, train=False, valid=False, limit=False):
+
+        self.data = None
+        query = 'from(bucket:"{}")'.format(self.bucket)
+        query += '|> range(start: -10m) '
+        query += ' |> filter(fn: (r) => r["_measurement"] == "o-ran-pm")'
+        query += ' |> filter(fn: (r) => r["_field"] == "CellID" or r["_field"] == "DRB.UEThpUl" or r["_field"] == "RRU.PrbUsedUl" or r["_field"] == "PEE.AvgPower") '
+        #query += ' |> filter(fn: (r) => r["_field"] == "CellID" or r["_field"] == "RRC.ConnMean" or r["_field"] == "DRB.UEThpUl" or r["_field"] == "RRU.PrbUsedUl" or r["_field"] == "PEE.AvgPower") '
+        query += ' |> pivot(rowKey: ["_time"], columnKey: ["_field"], valueColumn: "_value") '
+        result = self.query(query)
+        self.data = result
+        return result
+
+    # Query data
+    def query(self, query):
+        while True:
+            try:
+                query_api = self.client.query_api()
+                result = query_api.query_data_frame(org=self.org, query=query)
+                logger.debug(f'Cell data : {result}')
+                return result
+            except (RequestException, InfluxDBClientError, InfluxDBServerError, ConnectionError) as e:
+                logger.error(f'Failed to query influxdb: {e}, retrying in 60 seconds...')
+                time.sleep(60)
+
+    def mapping(self, data):
+        data[['S', 'B', 'C']] = data['CellID'].str.extract(r'S(\d+)/[BN](\d+)/C(\d+)')
+        data[['S', 'B', 'C']] = data[['S', 'B', 'C']].astype(int)
+        data = data.sort_values(by=['B', 'S', 'C'])
+        data['cellidnumber'] = data.groupby(['B', 'S', 'C']).ngroup().add(1)
+        data = data.drop(['S', 'B', 'C'], axis=1)
+        return data
+
+    def generate_synthetic_data(self):
+        data = []
+        fields = ["CellID", "DRB.UEThpUl", "RRU.PrbUsedUl", "PEE.AvgPower"]
+        # fields = ["CellID", "DRB.UEThpUl", "RRU.PrbUsedUl", "PEE.AvgPower", "RRC.ConnMean"]
+        other_fields = ["TestFilterField1", "TestFilterField2", "TestFilterField3", "TestFilterField4"]
+        measurements = ["o-ran-pm", "test-filter-measurement1", "test-filter-measurement2", "test-filter-measurement3", "test-filter-measurement4"]
+
+        # Generate matching records (synchronized _time for each group of 4)
+        for _ in range(50):  # 50 records, each with 4 rows sharing the same time
+            common_time = datetime.now() - timedelta(minutes=random.randint(0, 60))
+            iso_time = common_time.isoformat()
+
+            for field in fields:
+                value = (
+                    f"S{random.randint(1,9)}/B{random.randint(1,9)}/C{random.randint(1,9)}"
+                    if field == "CellID"
+                    else round(random.uniform(1, 100), 2)
+                )
+                record = {
+                    "_time": iso_time,
+                    "_measurement": "o-ran-pm",
+                    "_field": field,
+                    "_value": value
+                }
+                data.append(record)
+
+        # Generate non-matching records (randomized)
+        for _ in range(50):
+            record = {
+                "_time": (datetime.now() - timedelta(minutes=random.randint(0, 60))).isoformat(),
+                "_measurement": random.choice(measurements),
+                "_field": random.choice(other_fields),
+                "_value": str(round(random.uniform(0, 100), 2))
+            }
+            data.append(record)
+
+        # Log data to be written
+        print(pd.DataFrame(data).to_string())
+
+        self.write_synthetic_data_to_db(data)
+
+
+    def write_synthetic_data_to_db(self, data):
+
+        write_api = self.client.write_api(write_options=SYNCHRONOUS)
+        for record in data:
+            point = influxdb_client.Point(record["_measurement"]) \
+                .field(record["_field"], record["_value"]) \
+                .time(datetime.fromisoformat(record["_time"]))
+            write_api.write(bucket=self.bucket, org=self.org, record=point)
+        write_api.flush()
+        write_api.close()
+        logger.info("Synthetic data successfully written to InfluxDB.")
+
+    def config(self):
+
+        with open('config.json', 'r') as f:
+            config = json.load(f)
+
+        # Load the SME configuration from the JSON file
+        sme_config = config.get("SME", {})
+        self.influx_invoker_id = sme_config.get("influxdb_invoker_id")
+        self.influx_api_name = sme_config.get("influxdb_api_name")
+        self.influx_resource_name = sme_config.get("influxdb_resource_name")
+
+        # Initialize the InfluxDB client
+        influx_config = config.get("DB", {})
+        self.token = influx_config.get("token")
+        self.org = influx_config.get("org")
+        self.bucket = influx_config.get("bucket")
+        self.address = influx_config.get("address")
+        self.host = influx_config.get("host")
+        self.port = influx_config.get("port")
+        self.ssl = influx_config.get("ssl")
+        self.dbname = influx_config.get("database")
+        self.meas = influx_config.get("measurement")
+        self.user = influx_config.get("user")
+        self.password = influx_config.get("password")
diff --git a/sample-rapp-generator/es-demo-rapp/src/input.json b/sample-rapp-generator/es-demo-rapp/src/input.json
new file mode 100644 (file)
index 0000000..41367ce
--- /dev/null
@@ -0,0 +1 @@
+{"signature_name": "serving_default", "instances": [[[42.59, 50.3, 73.18]]]}
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/src/main.py b/sample-rapp-generator/es-demo-rapp/src/main.py
new file mode 100644 (file)
index 0000000..97dfd1c
--- /dev/null
@@ -0,0 +1,209 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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 argparse
+import time
+import pandas as pd
+import schedule
+import logging
+from data import DATABASE
+from assist import ASSIST
+from ncmp_client import NCMP_CLIENT
+from teiv_client import TEIV_CLIENT
+import json
+
+logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+logger = logging.getLogger(__name__)
+
+
+class ESrapp():
+    def __init__(self, generate_db_data=True, use_sme_db=False, random_predictions=False):
+
+        # Initialize the local storage of cell status
+        self.cell_power_status = {}
+        self.teiv_cells = {}
+
+        # Initialize the database and prediction client
+        self.db = DATABASE()
+        self.assist=ASSIST()
+
+        self.random_predictions = random_predictions
+
+        if use_sme_db:
+            # Get the InfluxDB URL from SME
+            self.db.get_url_from_sme()
+
+        self.db.connect()
+
+        if generate_db_data:
+            # Use local InfluxDB and generate synthetic data - only for local testing
+            self.db.generate_synthetic_data()
+
+
+        self.threshold = 50
+        # Initialize the NCMP client - allows us to query the cells from the RAN and power them on/off
+        self.ncmp_client = NCMP_CLIENT()
+        self.index = 1
+
+        # Get the ODU function ID from the database
+        self.teiv_client = TEIV_CLIENT()
+        #self.get_teiv_cells()
+        # Create Policy Manager instance
+        #self.policy_manager = PolicyManager(base_url="http://192.168.8.111:32080/a1mediator/A1-P/v2", policy_type_id=20008)
+
+        # Create policy type and policy instance
+        #self.policy_manager.create_policy_type()
+
+    def entry(self):
+        schedule.every(10).seconds.do(self.inference)
+
+        while True:
+            schedule.run_pending()
+
+    # Send data to ML rApp
+    def inference(self):
+        data = self.db.read_data()
+
+        if data.empty:
+            logger.info("No data to process... skipping this iteration of inference.")
+            return
+
+        data_mapping = self.mapping(data)
+        groups = data_mapping.groupby("CellID")
+        for group_name, group_data in groups:
+            json_data = self.generate_json_data(group_data)
+            logger.info(f"Send data to ML rApp {group_name}: {json_data}")
+            status_code, response_text = self.assist.send_request_to_server(json_data, randomize=self.random_predictions)
+            if not self.check_and_perform_action(response_text):
+                cell_id_number = group_data['cellidnumber'].iloc[0]
+                logger.info(f"Turn on the cell {group_name}")
+                # Create policy instance with the cell_id_number before performing action
+                #self.policy_manager.create_policy_instance(cell_id_number)
+                # Wait for 3 seconds before performing the action
+                time.sleep(3)
+
+                if cell_id_number not in self.cell_power_status:
+                    logger.debug(f"Cell {cell_id_number} not in local cache. Adding it...")
+                    self.cell_power_status[cell_id_number] = "off"
+                # Check if the cell is already powered on
+                if self.cell_power_status[cell_id_number] == "on":
+                    logger.debug(f"Cell {cell_id_number} is already powered on.")
+                    # continue
+                else:
+                    self.ncmp_client.power_on_cell(cell_id_number)
+                    self.cell_power_status[cell_id_number] = "on"
+            else:
+                cell_id_number = group_data['cellidnumber'].iloc[0]
+                logger.info(f"Turn off the cell {group_name}")
+                # Create policy instance with the cell_id_number before performing action
+                #self.policy_manager.create_policy_instance(cell_id_number)
+                # Wait for 3 seconds before performing the action
+                time.sleep(3)
+
+                if cell_id_number not in self.cell_power_status:
+                    logger.debug(f"Cell {cell_id_number} not in local cache. Adding it...")
+                    self.cell_power_status[cell_id_number] = "on"
+
+                if self.cell_power_status[cell_id_number] == "off":
+                    logger.debug(f"Cell {cell_id_number} is already powered off.")
+                    # continue
+                else:
+                    self.ncmp_client.power_off_cell(cell_id_number)
+                    self.cell_power_status[cell_id_number] = "off"
+
+    # Generate the input data for ML rApp
+    def generate_json_data(self, data):
+        # rrc_conn_mean_values = data["RRC.ConnMean"].tolist()
+        drb_ue_thp_ul_values = data["DRB.UEThpUl"].tolist()
+        rru_prb_used_ul_values = data["RRU.PrbUsedUl"].tolist()
+        pee_avg_power_values = data["PEE.AvgPower"].tolist()
+
+        instances = [
+            [
+                [drb, rru, pee]
+                for drb, rru, pee in zip(
+                drb_ue_thp_ul_values,
+                rru_prb_used_ul_values,
+                pee_avg_power_values
+            )
+            ]
+        ]
+
+        json_data = {"signature_name": "serving_default", "instances": instances}
+        logger.debug(f'Generated JSON data: {json_data}')
+        return json_data
+    # Mapping CellID and Cell name
+    def mapping(self, data):
+        data = pd.DataFrame(data)
+        # TODO: This regex is not likely to match all cell IDs. Will need to be improved.
+        data[['S', 'B', 'C']] = data['CellID'].str.extract(r'S(\d+)/[BN](\d+)/C(\d+)')
+        data[['S', 'B', 'C']] = data[['S', 'B', 'C']].astype(int)
+        data = data.sort_values(by=['B', 'S', 'C'])
+        data['cellidnumber'] = data.groupby(['B', 'S', 'C']).ngroup().add(1)
+        data = data.drop(['S', 'B', 'C'], axis=1)
+        return data
+
+
+    def check_and_perform_action(self, data):
+        response_obj = json.loads(data)
+        predictions = response_obj.get('predictions')
+        if predictions:
+            for prediction in predictions:
+                if all(pred < 0.04 for pred in prediction):
+                    return True
+                elif all(pred >= 0.04 for pred in prediction):
+                    return False
+        return False
+
+
+
+    # def get_teiv_cells(self):
+    #     # Get the TEIV cells from the teiv
+    #     odufunction_id = self.teiv_client.odufunction_id
+    #     logger.info("ODU function ID: " + str(odufunction_id))
+    #     # Get the NRCellDUs from the TEIV
+    #     nrcelldus = self.teiv_client.get_nrcelldus(odufunction_id)
+    #     if nrcelldus is None:
+    #         logger.error("Failed to retrieve NRCellDUs.")
+    #         return None
+    #     # Extract the cell IDs from the NRCellDUs
+    #     self.teiv_cells = self.teiv_client.search_entity_data_for_ids(nrcelldus)
+    #     logger.info("NRCellDUs: " + str(self.nrcelldus))
+
+
+if __name__ == "__main__":
+
+    def str2bool(v):
+        if isinstance(v, bool):
+            return v
+        if v.lower() in ('yes', 'true', 't', 'y', '1'):
+            return True
+        elif v.lower() in ('no', 'false', 'f', 'n', '0'):
+            return False
+        else:
+            raise argparse.ArgumentTypeError('Boolean value expected.')
+
+    parser = argparse.ArgumentParser(description="Run ESrapp with optional localdb data generation.")
+    parser.add_argument("--generate_db_data", type=str2bool, default=True, help="Set to True to generate data in db.")
+    parser.add_argument("--use_sme_db", type=str2bool, default=False, help="Set to True use SME url for DB.")
+    parser.add_argument("--random_predictions", type=str2bool, default=False, help="Set to True to generate random predictions.")
+    args = parser.parse_args()
+
+    rapp = ESrapp(generate_db_data=args.generate_db_data, use_sme_db=args.use_sme_db, random_predictions=args.random_predictions)
+    logger.debug("ES xApp starting")
+
+    rapp.entry()
diff --git a/sample-rapp-generator/es-demo-rapp/src/ncmp_client.py b/sample-rapp-generator/es-demo-rapp/src/ncmp_client.py
new file mode 100644 (file)
index 0000000..0093f88
--- /dev/null
@@ -0,0 +1,122 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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 json
+import logging
+from sme_client import SMEClient
+
+logger = logging.getLogger(__name__)
+
+class NCMP_CLIENT(object):
+    def __init__(self):
+        with open('config.json', 'r') as f:
+            config = json.load(f)
+
+        sme_config = config.get("SME", {})
+        self.host = sme_config.get("host")
+        self.port = sme_config.get("port")
+        self.ncmp_invoker_id = sme_config.get("ncmp_invoker_id")
+        self.ncmp_api_name = sme_config.get("ncmp_api_name")
+        self.ncmp_resource_name = sme_config.get("ncmp_resource_name")
+        self.resourse_identifier = sme_config.get("resource_id")
+        self.ncmp_uri = None
+
+        sme_client = SMEClient(
+            invoker_id=self.ncmp_invoker_id,
+            api_name=self.ncmp_api_name,
+            resource_name=self.ncmp_resource_name
+        )
+
+        self.ncmp_uri = sme_client.discover_service()
+
+        print("Discovered NCMP URI: ", self.ncmp_uri)
+
+    def power_off_cell(self, endpoint):
+
+        # This log is all it does in testing
+        logger.info("Powering-off cell " + str(endpoint) + " successful")
+
+        # It expects the SME ncmp endpoint to call power off
+        # endpoint_with_query = f"{endpoint}?resourceIdentifier={self.resourse_identifier}"
+        #
+        # headers = {
+        #     "Content-Type": "application/json"
+        # }
+        #
+        # body = {
+        #     "attributes": {
+        #         "administrativeState": "LOCKED"
+        #     }
+        # }
+        #
+        # response = requests.patch(endpoint_with_query, data=body, headers=headers)
+        #
+        # if response.status_code == 200:
+        #     logger.info("Power-off successful. " + response.text)
+        #     return response.json()
+        # else:
+        #     logger.error(f"Error in connection to NCMP for power off: {response.status_code}")
+        #     logger.error(response.text)
+        #     return None
+
+    def power_on_cell(self, endpoint):
+
+        # This log is all it does in testing
+        logger.info("Powering-on cell " + str(endpoint) + " successful")
+
+        # It expects the SME ncmp endpoint to call power on
+        # endpoint_with_query = f"{endpoint}?resourceIdentifier={self.resourse_identifier}"
+        #
+        # headers = {
+        #     "Content-Type": "application/json"
+        # }
+        #
+        # body = {
+        #     "attributes": {
+        #         "administrativeState": "UNLOCKED"
+        #     }
+        # }
+        #
+        # response = requests.patch(endpoint_with_query, data=body, headers=headers)
+        #
+        # if response.status_code == 200:
+        #     logger.info("Power-on successful. " + response.text)
+        #     return response.json()
+        # else:
+        #     logger.error(f"Error in connection to NCMP for power on: {response.status_code}")
+        #     logger.error(response.text)
+        #     return None
+
+# if __name__ == "__main__":
+#     logging.basicConfig(level=logging.INFO)  # Set up logging for better visibility
+#
+#     # Instantiate the NcmpClient
+#     ncmp_client = NCMP_CLIENT()
+
+# Test the discover_ncmp_via_sme method
+# Discover service
+
+# Test the power_off_cell method
+#if discovery_result:
+#    power_off_result = ncmp_client.power_off_cell(discovery_result)
+#    print(f"Power Off Result: {power_off_result}")
+
+# Test the power_on_cell method
+#if discovery_result:
+#    power_on_result = ncmp_client.power_on_cell(discovery_result)
+#    print(f"Power On Result: {power_on_result}")
+
diff --git a/sample-rapp-generator/es-demo-rapp/src/requirements.txt b/sample-rapp-generator/es-demo-rapp/src/requirements.txt
new file mode 100644 (file)
index 0000000..e99dedc
--- /dev/null
@@ -0,0 +1,6 @@
+influxdb_client
+pandas
+requests
+influxdb
+pandas
+schedule
diff --git a/sample-rapp-generator/es-demo-rapp/src/sme_client.py b/sample-rapp-generator/es-demo-rapp/src/sme_client.py
new file mode 100644 (file)
index 0000000..9ec3dcb
--- /dev/null
@@ -0,0 +1,79 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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 requests
+import logging
+import json
+
+logger = logging.getLogger(__name__)
+
+class SMEClient:
+    def __init__(self, invoker_id, api_name, resource_name):
+        self.host = None
+        self.port = None
+        self.invoker_id = invoker_id
+        self.api_name = api_name
+        self.resource_name = resource_name
+
+        with open('config.json', 'r') as f:
+            config = json.load(f)
+
+        sme_config = config.get("SME", {})
+        self.host = sme_config.get("host")
+        self.port = sme_config.get("port")
+        self.sme_discovery_endpoint = sme_config.get("sme_discovery_endpoint")
+
+    def discover_service(self):
+        #url = f"http://{self.host}:{self.port}/service-apis/v1/allServiceAPIs"
+        #url = f"http://{self.sme_discovery_endpoint}"
+        query = f"api-invoker-id=api_invoker_id_{self.invoker_id}&api-name={self.api_name}"
+        full_url = f"{self.sme_discovery_endpoint}?{query}"
+        logger.info(f"Full URL for service discovery: {full_url}")
+
+        try:
+            response = requests.get(full_url, headers={"Content-Type": "application/json"})
+            if response.status_code == 200:
+                logger.info("Service discovery successful.")
+                return self.parse_uri(response.json())
+            else:
+                logger.error(f"Failed to discover service. Status code: {response.status_code}")
+                logger.error(response.text)
+                return None
+        except requests.RequestException as e:
+            logger.error(f"Error during service discovery: {e}")
+            return None
+
+    def parse_uri(self, response):
+        try:
+            logger.debug("Parsing SME response to extract URI.")
+            service = response["serviceAPIDescriptions"][0]
+            profile = service["aefProfiles"][0]
+            version = profile["versions"][0]
+            resource = next(
+                (res for res in version["resources"] if res["resourceName"] == self.resource_name),
+                None
+            )
+            uri = resource["uri"] if resource else None
+
+            interface = profile["interfaceDescriptions"][0]
+            ipv4_addr = interface.get("ipv4Addr")
+            port = interface.get("port")
+
+            return f"http://{ipv4_addr}:{port}{uri}" if uri else f"http://{ipv4_addr}:{port}"
+        except (KeyError, IndexError, TypeError) as e:
+            logger.error(f"Error parsing URI: {e}")
+            return None
\ No newline at end of file
diff --git a/sample-rapp-generator/es-demo-rapp/src/teiv_client.py b/sample-rapp-generator/es-demo-rapp/src/teiv_client.py
new file mode 100644 (file)
index 0000000..3b4456b
--- /dev/null
@@ -0,0 +1,84 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  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 json
+import logging
+import requests
+import urllib.parse
+from sme_client import SMEClient
+
+logger = logging.getLogger(__name__)
+
+class TEIV_CLIENT(object):
+    def __init__(self):
+        with open('config.json', 'r') as f:
+            config = json.load(f)
+
+        sme_config = config.get("SME", {})
+        self.host = sme_config.get("host")
+        self.port = sme_config.get("port")
+        self.teiv_invoker_id = sme_config.get("teiv_invoker_id")
+        self.teiv_api_name = sme_config.get("teiv_api_name")
+        self.teiv_resource_name = sme_config.get("teiv_resource_name")
+        self.odufunction_id = sme_config.get("odufunction_id")
+        self.teiv_uri = None
+
+        sme_client = SMEClient(
+            invoker_id=self.teiv_invoker_id,
+            api_name=self.teiv_api_name,
+            resource_name=self.teiv_resource_name
+        )
+
+        self.teiv_uri = sme_client.discover_service()
+
+        print("Discovered TEIV URI: ", self.teiv_uri)
+
+    def get_nrcelldus(self, odufunction_id):
+
+        scope_filter = f"/provided-by-oduFunction[@id=\"{odufunction_id}\"]"
+        encoded_scope_filter = urllib.parse.quote(scope_filter)
+        endpoint = (
+            f"{self.teiv_uri}domains/RAN/entity-types/NRCellDU/entities?"
+            f"scopeFilter={encoded_scope_filter}&targetFilter=/attributes;/sourceIds"
+        )
+        logger.info("TEIV full endpoint: " + endpoint)
+        response = requests.get(endpoint)
+        
+        if response.status_code == 200:
+            logger.info("Retrieved NRCellDUs. " + response.text)
+            return response.json()
+        else:
+            logger.error(f"Error in connection to TEIV: {response.status_code}")
+            logger.error(response.text)
+            return None
+
+    def search_entity_data_for_ids(self, json_data):
+        items = json_data.get("items", [])
+        ids = []
+        for item in items:
+            for key in item:
+                ids.extend(entity.get('id') for entity in item[key] if 'id' in entity)
+        return ids
+
+# if __name__ == "__main__":
+#     logging.basicConfig(level=logging.INFO)  # Set up logging for better visibility
+#
+#     # Instantiate the TEIVClient
+#     teiv_client = TEIV_CLIENT()
+#
+#     nrcelldu_json = teiv_client.get_nrcelldus(teiv_client.odufunction_id)
+#     nrcelldu_ids = teiv_client.search_entity_data_for_ids(nrcelldu_json)
\ No newline at end of file
index e3d0e6e..7dcbc94 100755 (executable)
@@ -2,7 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2023 Nordix Foundation. All rights reserved.
-#  Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved.
+#  Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved.
 #  ========================================================================
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
@@ -33,8 +33,9 @@ if ! command -v helm &> /dev/null; then
   exit 1
 fi
 
+ORIGINAL_DIR=$(pwd)
 DIRECTORY=${1%/}
-PACKAGENAME="$DIRECTORY.csar"
+PACKAGENAME="$(basename "$DIRECTORY").csar"
 HELM_DIR="$DIRECTORY/Artifacts/Deployment/HELM"
 EXCLUDE_DIRS=()
 
@@ -56,9 +57,9 @@ checkHelmPackage() {
 
 if [ -d "$DIRECTORY" ]; then
   checkHelmPackage
-  rm -f $PACKAGENAME 2> /dev/null
+  rm -f $ORIGINAL_DIR/$PACKAGENAME 2> /dev/null
   pushd $DIRECTORY
-  zip -r ../$PACKAGENAME * $([ ${#EXCLUDE_DIRS[@]} -gt 0 ] && printf " -x %s" "${EXCLUDE_DIRS[@]}")
+  zip -r $ORIGINAL_DIR/$PACKAGENAME * $([ ${#EXCLUDE_DIRS[@]} -gt 0 ] && printf " -x %s" "${EXCLUDE_DIRS[@]}")
   popd
   echo -e "rApp package $PACKAGENAME generated."
 else
index 5ad1c10..a4c4ed8 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/bash
 #  ============LICENSE_START===============================================
-#  Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved.
+#  Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved.
 #  ========================================================================
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
 #
 
 echo "######### Patching Sample rApps #########"
+
+# Default values
+IP_ADDRESS=$(hostname -I | sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 | awk '{print $1}')
+PORT=8879
+
+# Parse optional arguments
+while getopts "i:p:r:" opt; do
+  case $opt in
+    i) IP_ADDRESS="$OPTARG" ;;
+    p) PORT="$OPTARG" ;;
+    r) RAPP="$OPTARG" ;;
+    *) echo "Usage: $0 [-i IP_ADDRESS] [-p PORT] [-r RAPP]" >&2; exit 1 ;;
+  esac
+done
+
+echo "IP Address : $IP_ADDRESS"
+echo "Port : $PORT"
+echo "Rapp Directory: $RAPP"
+
+
 echo "Replacing hardcoded variables inside sample-rapp-generator:"
 echo "UPDATE_THIS_MACHINE_IP"
 echo "UPDATE_THIS_CHART_MUSEUM_GET_CHARTS_URI"
 echo "UPDATE_THIS_CHART_MUSEUM_POST_CHARTS_URI"
+echo "UPDATE_THIS_ADDRESS"
+
 CWD=$(pwd)
 export WORKSPACE="$CWD/../../sample-rapp-generator"
 
-IP_ADDRESS=$(hostname -I | sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 | awk '{print $1}')
-echo "IP Address : $IP_ADDRESS"
-
-CHART_REPO_GET_URI=${CHART_REPO_GET_URI:-'http://'$IP_ADDRESS':8879/charts'}
-CHART_REPO_POST_URI=${CHART_REPO_POST_URI:-'http://'$IP_ADDRESS':8879/charts/api/charts'}
+CHARTREPO_IP_PORT=${CHART_REPO_GET_URI:-'http://'$IP_ADDRESS':'$PORT''}
+echo "CHARTREPO_IP_PORT: $CHARTREPO_IP_PORT"
+CHART_REPO_GET_URI=${CHART_REPO_GET_URI:-'http://'$IP_ADDRESS':'$PORT'/charts'}
+CHART_REPO_POST_URI=${CHART_REPO_POST_URI:-'http://'$IP_ADDRESS':'$PORT'/api/charts'}
 
 echo "Replacing charts repo post url in yaml files....."
 echo "Chart repository post URI : $CHART_REPO_POST_URI"
-for file in $(find $WORKSPACE -type f -name "*.yaml"); do
+for file in $(find $WORKSPACE/$RAPP -type f -name "*.yaml"); do
   sed -i "s|UPDATE_THIS_CHART_MUSEUM_POST_CHARTS_URI|${CHART_REPO_POST_URI}|g" "$file"
   if grep -q "$CHART_REPO_POST_URI" "$file"; then
     echo "$file is updated."
@@ -41,7 +62,7 @@ done
 
 echo "Replacing charts repo get url and machine ip in json files....."
 echo "Chart repository get URI : $CHART_REPO_GET_URI"
-for file in $(find $WORKSPACE -type f -name "*.json"); do
+for file in $(find $WORKSPACE/$RAPP -type f \( -name "*.yaml" -o -name "*.json" \)); do
   sed -i "s|UPDATE_THIS_CHART_MUSEUM_GET_CHARTS_URI|${CHART_REPO_GET_URI}|g" "$file"
   if grep -q "$CHART_REPO_GET_URI" "$file"; then
     echo "$file is updated."
@@ -51,6 +72,12 @@ for file in $(find $WORKSPACE -type f -name "*.json"); do
   if grep -q "$IP_ADDRESS" "$file"; then
     echo "UPDATE_THIS_MACHINE_IP updated in file: $file"
   fi
+
+  sed -i "s|UPDATE_THIS_ADDRESS|${CHARTREPO_IP_PORT}|g" "$file"
+  if grep -q "$CHARTREPO_IP_PORT" "$file"; then
+    echo "UPDATE_THIS_ADDRESS updated in file: $file"
+  fi
+
 done
 echo "UPDATE_THIS_MACHINE_IP=$IP_ADDRESS"
 echo "UPDATE_THIS_CHART_MUSEUM_GET_CHARTS_URI=$CHART_REPO_GET_URI"