Hard manual reset to master branch 30/13130/2
authorJohnKeeney <john.keeney@est.tech>
Fri, 28 Jun 2024 13:00:50 +0000 (14:00 +0100)
committerJohnKeeney <john.keeney@est.tech>
Fri, 28 Jun 2024 13:25:52 +0000 (14:25 +0100)
Error creating branch initially.
Reseting branch contents to 85d61ba735e5c00a377361b6d57081a4279f2dde
Ref: https://gerrit.o-ran-sc.org/r/gitweb?p=nonrtric.git;a=tree;h=85d61ba735e5c00a377361b6d57081a4279f2dde
Same as master at time of J Release (26 June 2024)

Issue-ID: NONRTRIC-972
Change-Id: I0fbd77a28ca3fa54b4bb869a3dd35aa517e34d0e
Signed-off-by: JohnKeeney <john.keeney@est.tech>
193 files changed:
.github/workflows/gerrit-merge.yaml [new file with mode: 0644]
README.md
docs/api-docs.rst
docs/conf.py
docs/overview.rst
sample-services/hello-world-sme-invoker/.gitignore [moved from test/servicestub/.gitignore with 100% similarity]
sample-services/hello-world-sme-invoker/Dockerfile [new file with mode: 0644]
sample-services/hello-world-sme-invoker/README.md [new file with mode: 0644]
sample-services/hello-world-sme-invoker/build.sh [new file with mode: 0644]
sample-services/hello-world-sme-invoker/container-tag.yaml [moved from test/servicestub/hello-world-chart/templates/tests/test-connection.yaml with 61% similarity]
sample-services/hello-world-sme-invoker/docker-compose.yml [moved from test/servicestub/hello-world-chart/values.yaml with 76% similarity]
sample-services/hello-world-sme-invoker/hello-world-sme-invoker-build-start.sh [new file with mode: 0644]
sample-services/hello-world-sme-invoker/hello-world-sme-invoker/.helmignore [moved from test/servicestub/hello-world-chart/.helmignore with 100% similarity]
sample-services/hello-world-sme-invoker/hello-world-sme-invoker/Chart.yaml [new file with mode: 0644]
sample-services/hello-world-sme-invoker/hello-world-sme-invoker/templates/deployment.yaml [new file with mode: 0644]
sample-services/hello-world-sme-invoker/hello-world-sme-invoker/templates/service.yaml [moved from test/servicestub/hello-world-chart/templates/service.yaml with 78% similarity]
sample-services/hello-world-sme-invoker/hello-world-sme-invoker/values.yaml [new file with mode: 0644]
sample-services/hello-world-sme-invoker/pom.xml [new file with mode: 0644]
sample-services/hello-world-sme-invoker/src/main/java/org/oransc/nonrtric/sample/HelloWorldSmeInvokerApplication.java [new file with mode: 0644]
sample-services/hello-world-sme-invoker/src/main/java/org/oransc/nonrtric/sample/exception/CapifAccessException.java [moved from test/servicestub/src/main/java/org/oran/helloworld/rest/HelloWorldController.java with 57% similarity]
sample-services/hello-world-sme-invoker/src/main/java/org/oransc/nonrtric/sample/exception/GlobalExceptionHandler.java [new file with mode: 0644]
sample-services/hello-world-sme-invoker/src/main/java/org/oransc/nonrtric/sample/rest/HelloWorldSmeInvokerComponent.java [new file with mode: 0644]
sample-services/hello-world-sme-invoker/src/main/java/org/oransc/nonrtric/sample/rest/response/ApiResponse.java [new file with mode: 0644]
sample-services/hello-world/.gitignore [new file with mode: 0644]
sample-services/hello-world/Dockerfile [moved from test/servicestub/Dockerfile with 100% similarity]
sample-services/hello-world/README.md [moved from test/servicestub/README.md with 70% similarity]
sample-services/hello-world/build.sh [moved from test/servicestub/build.sh with 98% similarity]
sample-services/hello-world/container-tag.yaml [moved from test/servicestub/container-tag.yaml with 100% similarity]
sample-services/hello-world/docker-compose.yml [moved from test/servicestub/docker-compose.yml with 93% similarity]
sample-services/hello-world/hello-world-build-start.sh [moved from test/servicestub/service-stub-build-start.sh with 73% similarity]
sample-services/hello-world/hello-world-chart/.helmignore [new file with mode: 0644]
sample-services/hello-world/hello-world-chart/Chart.yaml [moved from test/servicestub/hello-world-chart/Chart.yaml with 100% similarity]
sample-services/hello-world/hello-world-chart/templates/deployment.yaml [moved from test/servicestub/hello-world-chart/templates/deployment.yaml with 78% similarity]
sample-services/hello-world/hello-world-chart/templates/service.yaml [new file with mode: 0644]
sample-services/hello-world/hello-world-chart/values.yaml [new file with mode: 0644]
sample-services/hello-world/pom.xml [moved from test/servicestub/pom.xml with 98% similarity]
sample-services/hello-world/src/main/java/org/oransc/nonrtric/sample/HelloWorldApplication.java [moved from test/servicestub/src/main/java/org/oran/helloworld/HelloWorldApplication.java with 89% similarity]
sample-services/hello-world/src/main/java/org/oransc/nonrtric/sample/rest/HelloWorldController.java [new file with mode: 0644]
sample-services/hello-world/src/test/java/org/oransc/nonrtric/sample/rest/HelloWorldControllerTest.java [new file with mode: 0644]
sample-services/ics-producer-consumer/.gitignore [new file with mode: 0644]
sample-services/ics-producer-consumer/README.md [new file with mode: 0644]
sample-services/ics-producer-consumer/application.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/Dockerfile [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/Makefile [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/container-tag.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/pom.xml [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/Application.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/consumer/SimpleConsumer.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/controllers/ConsumerController.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/controllers/ThreadsController.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/dme/ConsumerJobInfo.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/dme/ConsumerStatusInfo.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/dme/JobDataSchema.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/AbstractSimpleKafka.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/ApplicationMessageHandlerImpl.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/KafkaMessageHandler.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/KafkaMessageHandlerImpl.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/MessageHelper.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/PropertiesHelper.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/repository/InfoType.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/repository/InfoTypes.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/repository/Job.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/repository/Jobs.java [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/resources/application.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/resources/config.properties [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/main/resources/logback.xml [new file with mode: 0644]
sample-services/ics-producer-consumer/consumer/src/test/java/com/demo/consumer/SimpleConsumerTest.java [new file with mode: 0644]
sample-services/ics-producer-consumer/docker-compose.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/docker-compose/.env [new file with mode: 0644]
sample-services/ics-producer-consumer/docker-compose/LICENSE.txt [new file with mode: 0644]
sample-services/ics-producer-consumer/docker-compose/README.md [new file with mode: 0644]
sample-services/ics-producer-consumer/docker-compose/control-panel/config/nginx.conf [new file with mode: 0644]
sample-services/ics-producer-consumer/docker-compose/control-panel/docker-compose.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/docker-compose/docker-compose.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/docker-compose/nonrtric-gateway/config/application-nonrtricgateway.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/docker-compose/nonrtric-gateway/docker-compose.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/docker-composeRedPanda.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/helm-chart/ics-consumer/.helmignore [new file with mode: 0644]
sample-services/ics-producer-consumer/helm-chart/ics-consumer/Chart.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/helm-chart/ics-consumer/templates/consumer-deployment.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/helm-chart/ics-consumer/templates/consumer-service.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/helm-chart/ics-consumer/values.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/helm-chart/ics-producer/.helmignore [new file with mode: 0644]
sample-services/ics-producer-consumer/helm-chart/ics-producer/Chart.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/helm-chart/ics-producer/templates/producer-deployment.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/helm-chart/ics-producer/templates/producer-service.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/helm-chart/ics-producer/values.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/Dockerfile [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/Makefile [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/container-tag.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/pom.xml [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/Application.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/controllers/ProducerController.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/controllers/ThreadsController.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/dme/ProducerInfoTypeInfo.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/dme/ProducerJobInfo.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/dme/ProducerRegistrationInfo.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/AbstractSimpleKafka.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/ApplicationMessageHandlerImpl.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/KafkaMessageHandler.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/KafkaMessageHandlerImpl.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/MessageHelper.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/PropertiesHelper.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/producer/SimpleProducer.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/repository/InfoType.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/repository/InfoTypes.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/repository/Job.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/repository/Jobs.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/resources/application.yaml [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/resources/config.properties [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/main/resources/logback.xml [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/test/java/com/demo/producer/SimpleProducerTest.java [new file with mode: 0644]
sample-services/ics-producer-consumer/producer/src/test/java/com/demo/producer/ThreadsControllerTest.java [new file with mode: 0644]
sample-services/ics-producer-consumer/red.sh [new file with mode: 0644]
sample-services/ics-producer-consumer/runconsumer.sh [new file with mode: 0644]
sample-services/ics-producer-consumer/runproducer.sh [new file with mode: 0644]
sample-services/ics-producer-consumer/start.sh [new file with mode: 0644]
sample-services/ics-producer-consumer/stop.sh [new file with mode: 0644]
sample-services/ics-producer-consumer/utils.sh [new file with mode: 0644]
test/auto-test/FTC1.sh
test/auto-test/FTC10.sh
test/auto-test/FTC100.sh
test/auto-test/FTC110.sh
test/auto-test/FTC1100.sh
test/auto-test/FTC150.sh
test/auto-test/FTC1800.sh
test/auto-test/FTC1_A1PMS_ADAPTER.sh
test/auto-test/FTC1_MEDIATOR_ADAPTER.sh [new file with mode: 0644]
test/auto-test/FTC1_RICMEDIATOR.sh
test/auto-test/FTC1_RICMEDIATORONLY.sh
test/auto-test/FTC2001.sh
test/auto-test/FTC2002.sh
test/auto-test/FTC2003.sh
test/auto-test/FTC300.sh
test/auto-test/FTC3000.sh
test/auto-test/FTC3001.sh
test/auto-test/FTC310.sh
test/auto-test/FTC350.sh
test/auto-test/FTC4000.sh
test/auto-test/FTC800.sh
test/auto-test/FTC805.sh
test/auto-test/FTC810.sh
test/auto-test/FTC850.sh
test/auto-test/FTC900.sh
test/auto-test/ONAP_UC.sh
test/auto-test/PM_DEMO.sh
test/auto-test/PM_EI_DEMO.sh
test/auto-test/README.md
test/auto-test/Suite-Verify-jobs.sh
test/auto-test/mediator-override-adapter.sh [new file with mode: 0644]
test/auto-test/override-adapter.sh
test/auto-test/startMR.sh
test/auto-test/verify-jobs-nonrtric.sh
test/common/a1pms_api_functions.sh [changed mode: 0644->0755]
test/common/api_curl.sh [changed mode: 0644->0755]
test/common/authsidecar_api_functions.sh [changed mode: 0644->0755]
test/common/chartmus_api_functions.sh [changed mode: 0644->0755]
test/common/cp_api_functions.sh [changed mode: 0644->0755]
test/common/cr_api_functions.sh [changed mode: 0644->0755]
test/common/create_policies_process.py
test/common/create_rics_json.py
test/common/delete_policies_process_v3.py [new file with mode: 0644]
test/common/dmaapadp_api_functions.sh [changed mode: 0644->0755]
test/common/dmaapmed_api_functions.sh [changed mode: 0644->0755]
test/common/dmaapmr_api_functions.sh [changed mode: 0644->0755]
test/common/get_policies_process.py [new file with mode: 0644]
test/common/get_policies_process_v3.py [new file with mode: 0644]
test/common/helmmanager_api_functions.sh [changed mode: 0644->0755]
test/common/httpproxy_api_functions.sh [changed mode: 0644->0755]
test/common/ics_api_functions.sh [changed mode: 0644->0755]
test/common/istio_api_functions.sh [changed mode: 0644->0755]
test/common/kafkapc_api_functions.sh [changed mode: 0644->0755]
test/common/keycloak_api_functions.sh [changed mode: 0644->0755]
test/common/kubeproxy_api_functions.sh [changed mode: 0644->0755]
test/common/localhelm_api_functions.sh [changed mode: 0644->0755]
test/common/ngw_api_functions.sh [changed mode: 0644->0755]
test/common/prodstub_api_functions.sh [changed mode: 0644->0755]
test/common/pvccleaner_api_functions.sh [changed mode: 0644->0755]
test/common/rc_api_functions.sh [changed mode: 0644->0755]
test/common/ricmediatorsim_api_functions.sh [changed mode: 0644->0755]
test/common/ricsim_api_functions.sh [changed mode: 0644->0755]
test/common/sdnc_api_functions.sh [changed mode: 0644->0755]
test/common/test_env-onap-kohn.sh [changed mode: 0644->0755]
test/common/test_env-onap-london.sh [changed mode: 0644->0755]
test/common/test_env-onap-montreal.sh [moved from test/common/test_env-onap-jakarta.sh with 92% similarity, mode: 0755]
test/common/test_env-oran-h-release.sh
test/common/test_env-oran-i-release.sh [moved from test/common/test_env-oran-f-release.sh with 87% similarity]
test/common/testcase_common.sh
test/common/testengine_config.sh [changed mode: 0644->0755]
test/common/testsuite_common.sh [changed mode: 0644->0755]
test/common/update_policies_process.py [new file with mode: 0644]
test/servicestub/hello-world-chart/templates/_helpers.tpl [deleted file]
test/servicestub/src/test/java/org/oran/helloworld/rest/HelloWorldControllerTest.java [deleted file]

diff --git a/.github/workflows/gerrit-merge.yaml b/.github/workflows/gerrit-merge.yaml
new file mode 100644 (file)
index 0000000..01cd32b
--- /dev/null
@@ -0,0 +1,120 @@
+---
+name: Gerrit Merge
+
+# yamllint disable-line rule:truthy
+on:
+  workflow_dispatch:
+    inputs:
+      GERRIT_BRANCH:
+        description: "Branch that change is against"
+        required: true
+        type: string
+      GERRIT_CHANGE_ID:
+        description: "The ID for the change"
+        required: true
+        type: string
+      GERRIT_CHANGE_NUMBER:
+        description: "The Gerrit number"
+        required: true
+        type: string
+      GERRIT_CHANGE_URL:
+        description: "URL to the change"
+        required: true
+        type: string
+      GERRIT_EVENT_TYPE:
+        description: "Type of Gerrit event"
+        required: true
+        type: string
+      GERRIT_PATCHSET_NUMBER:
+        description: "The patch number for the change"
+        required: true
+        type: string
+      GERRIT_PATCHSET_REVISION:
+        description: "The revision sha"
+        required: true
+        type: string
+      GERRIT_PROJECT:
+        description: "Project in Gerrit"
+        required: true
+        type: string
+      GERRIT_REFSPEC:
+        description: "Gerrit refspec of change"
+        required: true
+        type: string
+    secrets:
+      SONAR_TOKEN:
+        description: "Sonar Cloud access token"
+        required: true
+
+concurrency:
+  # yamllint disable-line rule:line-length
+  group: gerrit-merge-${{ github.workflow }}-${{ github.event.inputs.GERRIT_CHANGE_ID || github.run_id }}
+  cancel-in-progress: true
+
+jobs:
+  notify:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Notify job start
+        # yamllint disable-line rule:line-length
+        uses: lfit/gerrit-review-action@7c30179c3c9389545fccb0d458df59879372ae6a  # v0.6
+        with:
+          host: ${{ vars.GERRIT_SERVER }}
+          username: ${{ vars.GERRIT_SSH_USER }}
+          key: ${{ secrets.GERRIT_SSH_PRIVKEY }}
+          known_hosts: ${{ vars.GERRIT_KNOWN_HOSTS }}
+          gerrit-change-number: ${{ inputs.GERRIT_CHANGE_NUMBER }}
+          gerrit-patchset-number: ${{ inputs.GERRIT_PATCHSET_NUMBER }}
+          vote-type: clear
+      - name: Allow replication
+        run: sleep 10s
+
+  call-prescan-sonarcloud:
+    needs: notify
+    # yamllint disable-line rule:line-length
+    uses: lfit/releng-reusable-workflows/.github/workflows/composed-prescan-sonar-cloud.yaml@main
+    with:
+      GERRIT_BRANCH: ${{ inputs.GERRIT_BRANCH }}
+      GERRIT_CHANGE_ID: ${{ inputs.GERRIT_CHANGE_ID }}
+      GERRIT_CHANGE_NUMBER: ${{ inputs.GERRIT_CHANGE_NUMBER }}
+      GERRIT_CHANGE_URL: ${{ inputs.GERRIT_CHANGE_URL }}
+      GERRIT_EVENT_TYPE: ${{ inputs.GERRIT_EVENT_TYPE }}
+      GERRIT_PATCHSET_NUMBER: ${{ inputs.GERRIT_PATCHSET_NUMBER }}
+      GERRIT_PATCHSET_REVISION: ${{ inputs.GERRIT_PATCHSET_REVISION }}
+      GERRIT_PROJECT: ${{ inputs.GERRIT_PROJECT }}
+      GERRIT_REFSPEC: ${{ inputs.GERRIT_REFSPEC }}
+      JDK_VERSION: "17"
+      # yamllint disable-line rule:line-length
+      PRE_BUILD_SCRIPT_URL: "https://raw.githubusercontent.com/o-ran-sc/ci-management/master/jjb/nonrtric/prescan-nonrtric-auth-token-fetch-ubuntu.sh"
+      SONAR_ARGS: >
+        -Dsonar.organization=o-ran-sc
+        -Dsonar.projectKey=o-ran-sc_nonrtric
+        -Dsonar.projectName=nonrtric
+        -Dsonar.build.sourceEncoding=UTF-8
+        -Dsonar.language=go
+        -Dsonar.sources=.
+        -Dsonar.go.coverage.reportPaths=auth-token-fetch/coverage.txt
+        -Dsonar.inclusions=auth-token-fetch/**.go
+        -Dsonar.exclusions=auth-token-fetch/**_test.go
+        -Dsonar.verbose=true
+    secrets:
+      SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+
+  report-status:
+    if: ${{ always() }}
+    needs: [notify, call-prescan-sonarcloud]
+    runs-on: ubuntu-latest
+    steps:
+      - name: Get workflow conclusion
+        uses: technote-space/workflow-conclusion-action@v3
+      - name: Report workflow conclusion
+        # yamllint disable-line rule:line-length
+        uses: lfit/gerrit-review-action@7c30179c3c9389545fccb0d458df59879372ae6a  # v0.6
+        with:
+          host: ${{ vars.GERRIT_SERVER }}
+          username: ${{ vars.GERRIT_SSH_USER }}
+          key: ${{ secrets.GERRIT_SSH_PRIVKEY }}
+          known_hosts: ${{ vars.GERRIT_KNOWN_HOSTS }}
+          gerrit-change-number: ${{ inputs.GERRIT_CHANGE_NUMBER }}
+          gerrit-patchset-number: ${{ inputs.GERRIT_PATCHSET_NUMBER }}
+          vote-type: ${{ env.WORKFLOW_CONCLUSION }}
index e27ff07..81caa27 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,25 +1,24 @@
-# O-RAN-SC Non-RealTime RIC\r
-\r
-The O-RAN SC Non-RT RIC provides support for non-real-time intelligent radio resource management, higher layer procedure optimization, policy optimization in RAN, and providing guidance, parameters, policies and AI/ML models to support the operation of the Near-RT RIC to achieve higher-level non-real-time objectives.\r
-\r
-Please see the documentation in the docs/ folder\r
-\r
-For more information about the Non-RT RIC project please see the [project website](https://wiki.o-ran-sc.org/display/RICNR "O-RAN-SC Non-RT RIC project")\r
-\r
-## License\r
-\r
-Copyright (C) 2019-2023 Nordix Foundation. All Rights Reserved.\r
-Copyright (C) 2019-2023 OpenInfra Foundation Europe. All Rights Reserved.\r
-Licensed under the Apache License, Version 2.0 (the "License")\r
-you may not use this file except in compliance with the License.\r
-You may obtain a copy of the License at\r
-\r
-      http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-Unless required by applicable law or agreed to in writing, software\r
-distributed under the License is distributed on an "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-See the License for the specific language governing permissions and\r
-limitations under the License.\r
-\r
-For more information about license please see the [LICENSE](LICENSE.txt) file for details.\r
+# O-RAN-SC Non-RealTime RIC
+
+The O-RAN SC Non-RT RIC provides support for non-real-time intelligent radio resource management, higher layer procedure optimization, policy optimization in RAN, and providing guidance, parameters, policies and AI/ML models to support the operation of the Near-RT RIC to achieve higher-level non-real-time objectives.
+
+Please see the documentation in the docs/ folder
+
+For more information about the Non-RT RIC project please see the [project website](https://wiki.o-ran-sc.org/display/RICNR "O-RAN-SC Non-RT RIC project")
+
+## License
+
+Copyright (C) 2019 Nordix Foundation.
+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.
+
+For more information about license please see the [LICENSE](LICENSE.txt) file for details.
index 2b83838..47d6720 100644 (file)
@@ -1,7 +1,7 @@
 .. This work is licensed under a Creative Commons Attribution 4.0 International License.
 .. http://creativecommons.org/licenses/by/4.0
 .. Copyright (C) 2021-2023 Nordix Foundation. All rights Reserved
-.. Copyright (C) 2023-2024 OpenInfra Foundation Europe. All Rights Reserved
+.. Copyright (C) 2023 OpenInfra Foundation Europe. All Rights Reserved
 
 .. _api_docs:
 
index f437de7..642acf2 100644 (file)
@@ -19,21 +19,21 @@ from docs_conf.conf import *
 
 ## Update here to configure which branch is used. 
 #branch configurations
-controlpanelbranch = 'i-release'
-simulatorbranch = 'i-release'
-dmaapmediatorproducerbranch = 'i-release'
-dmaapadapterbranch = 'i-release'
-informationcoordinatorservicebranch = 'i-release'
-rappcataloguebranch = 'i-release'
-rappmanagerbranch = 'i-release'
-helmmanagerbranch = 'i-release'
+controlpanelbranch = 'latest'
+simulatorbranch = 'latest'
+dmaapmediatorproducerbranch = 'latest'
+dmaapadapterbranch = 'latest'
+informationcoordinatorservicebranch = 'latest'
+rappcataloguebranch = 'latest'
+rappmanagerbranch = 'latest'
+helmmanagerbranch = 'latest'
 ransliceassurancebranch = 'latest'
 orufhrecoverybranch = 'latest'
-authtokenfetchbranch = 'i-release'
-a1policymanagementservicebranch = 'i-release'
-smebranch = 'i-release'
-ranpmbranch = 'i-release'
-onapbranch = 'montreal'
+authtokenfetchbranch = 'latest'
+a1policymanagementservicebranch = 'latest'
+smebranch = 'latest'
+ranpmbranch = 'latest'
+onapbranch = 'latest'
 # Add some useful links available in every page
 rst_epilog = """
 .. _nonrtricwiki: https://wiki.o-ran-sc.org/display/RICNR/
index 4f14da5..60515a0 100644 (file)
@@ -25,7 +25,7 @@ The OSC NONRTRIC hosts rApps, and coordinates all interactions between the rApp
 
 Find detailed description of the NONRTRIC project see the `O-RAN SC NONRTRIC Project Wiki <nonrtricwiki_>`_.
 
-NONRTRIC Components
+NONRTRIC components
 -------------------
 
 These are the components that make up the Non-RT-RIC:
@@ -50,6 +50,7 @@ These are the components that make up the Non-RT-RIC:
   * "Helloworld" O-RU Fronthaul Recovery use case.  (:doc:`Documentation site <orufhrecovery:index>`).
   * "Helloworld" O-DU Slice Assurance use case.  (:doc:`Documentation site <ransliceassurance:index>`).
 
+
 Non-RT-RIC Control Panel / NONRTRIC Dashboard
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -209,10 +210,10 @@ Implementation:
 Initial Kubernetes Helm Chart LCM Manager
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Onboard, start, stop, and modify Non-RT-RIC App microservices as Helm Charts.
-*A building block for coming releases as the RAPP concept matures*.
+Onboard, start, stop, and modify Non-RT-RIC App Ã‚µServices as Helm Charts.
+*A building block for coming releases as the R-APP concept matures*.
 
-- Interfaces that accepts Non-RT-RIC App microservices Helm Charts.
+- Interfaces that accepts Non-RT-RIC App Ã‚µServices Helm Charts.
 - Support basic LCM operations.
 - Onboard, Start, Stop, Modify, Monitor.
 - Initial version co-developed with v. similar functions in ONAP.
diff --git a/sample-services/hello-world-sme-invoker/Dockerfile b/sample-services/hello-world-sme-invoker/Dockerfile
new file mode 100644 (file)
index 0000000..05b4db2
--- /dev/null
@@ -0,0 +1,45 @@
+#==================================================================================
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#
+#   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.
+#
+#==================================================================================
+
+
+# Use Maven image with OpenJDK 17 for the build stage
+FROM maven:3.8.5-openjdk-17 AS maven_build
+
+# Copy Maven project files
+COPY pom.xml /tmp/
+COPY src /tmp/src/
+
+# Set working directory
+WORKDIR /tmp/
+
+# Build the Maven project
+RUN mvn package
+
+# Use a separate image with OpenJDK 17 for the runtime stage
+FROM openjdk:17-jdk-slim
+
+# Expose port 8080
+EXPOSE 8080
+
+# Set the working directory
+WORKDIR /app
+
+# Copy the JAR file from the maven_build stage to the runtime stage
+COPY --from=maven_build /tmp/target/hello-world-sme-invoker-0.1.0.jar /app/hello-world-sme-invoker-0.1.0.jar
+
+# Command to run the application
+CMD ["java", "-jar", "hello-world-sme-invoker-0.1.0.jar"]
diff --git a/sample-services/hello-world-sme-invoker/README.md b/sample-services/hello-world-sme-invoker/README.md
new file mode 100644 (file)
index 0000000..0e8193f
--- /dev/null
@@ -0,0 +1,27 @@
+# Hello World Sme Invoker Service
+
+This repository contains a Spring Boot application serving as Hello World SME invoker application.
+The application can be built and run using the provided script - ``hello-world-sme-invoker-build-start.sh``.
+
+## Prerequisites
+
+- Docker installed on your machine.
+
+## Building and Running the Application
+Run the script:
+
+```bash
+  ./hello-world-sme-invoker-build-start.sh
+```
+
+The script will build a Docker image and run a container with the Hello World SME service. After the container starts,
+wait for a few seconds to ensure the Spring Boot application is fully initialized. Next, it will make an HTTP request to the
+Hello World SME endpoint on the interval of 5 seconds and displays the response:
+
+To stop and remove the Docker container:
+
+```bash
+  docker stop hello-world-sme-invoker
+  docker rm hello-world-sme-invoker
+```
+
diff --git a/sample-services/hello-world-sme-invoker/build.sh b/sample-services/hello-world-sme-invoker/build.sh
new file mode 100644 (file)
index 0000000..576b4b2
--- /dev/null
@@ -0,0 +1,96 @@
+#!/bin/bash
+
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2024: OpenInfra Foundation Europe.
+#  ========================================================================
+#  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=================================================
+#
+
+# Build image from Dockerfile with/without custom image tag
+# Optionally push to external image repo
+
+print_usage() {
+    echo "Usage: build.sh no-push|<docker-hub-repo-name> [<image-tag>]"
+    exit 1
+}
+
+if [ $# -ne 1 ] && [ $# -ne 2 ]; then
+    print_usage
+fi
+
+IMAGE_NAME="o-ran-sc/nonrtric-sample-helloworld-sme-invoker"
+IMAGE_TAG="latest"
+REPO=""
+if [ $1 == "no-push" ]; then
+    echo "Only local image build"
+else
+    REPO=$1
+    echo "Attempt to push built image to: "$REPO
+fi
+
+shift
+while [ $# -ne 0 ]; do
+    if [ $1 == "--tag" ]; then
+        shift
+        if [ -z "$1" ]; then
+            print_usage
+        fi
+        IMAGE_TAG=$1
+        echo "Setting image tag to: "$IMAGE_TAG
+        shift
+    else
+        echo "Unknown parameter: $1"
+        print_usage
+    fi
+done
+
+IMAGE=$IMAGE_NAME:$IMAGE_TAG
+
+export DOCKER_DEFAULT_PLATFORM=linux/amd64
+CURRENT_PLATFORM=$(docker system info --format '{{.OSType}}/{{.Architecture}}')
+if [ $CURRENT_PLATFORM != $DOCKER_DEFAULT_PLATFORM ]; then
+    echo "Image may not work on the current platform: $CURRENT_PLATFORM, only platform $DOCKER_DEFAULT_PLATFORM supported"
+fi
+
+echo "Building image $IMAGE"
+docker build -t $IMAGE_NAME:$IMAGE_TAG .
+if [ $? -ne 0 ]; then
+    echo "BUILD FAILED"
+    exit 1
+fi
+echo "BUILD OK"
+
+if [ "$REPO" != "" ]; then
+    echo "Tagging image"
+    NEW_IMAGE=$REPO/$IMAGE_NAME:$IMAGE_TAG
+    docker tag $IMAGE $NEW_IMAGE
+    if [ $? -ne 0 ]; then
+        echo "RE-TAGGING FAILED"
+        exit 1
+    fi
+    echo "RE-TAG OK"
+
+    echo "Pushing image $NEW_IMAGE"
+    docker push $NEW_IMAGE
+    if [ $? -ne 0 ]; then
+        echo "PUSHED FAILED"
+        echo " Perhaps not logged into docker-hub repo $REPO?"
+        exit 1
+    fi
+    IMAGE=$NEW_IMAGE
+    echo "PUSH OK"
+fi
+
+echo "IMAGE OK: $IMAGE"
+echo "DONE"
@@ -2,7 +2,7 @@
 #   ========================LICENSE_START=================================
 #   O-RAN-SC
 #   %%
-#   Copyright (C) 2023: OpenInfra Foundation Europe
+#   Copyright (C) 2024: OpenInfra Foundation Europe.
 #   %%
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
 #   ========================LICENSE_END===================================
 #
 
-apiVersion: v1
-kind: Pod
-metadata:
-  name: "{{ include "hello-world-chart.fullname" . }}-test-connection"
-  labels:
-    {{- include "hello-world-chart.labels" . | nindent 4 }}
-  annotations:
-    "helm.sh/hook": test
-spec:
-  containers:
-    - name: wget
-      image: busybox
-      command: ['wget']
-      args: ['{{ include "hello-world-chart.fullname" . }}:{{ .Values.service.port }}']
-  restartPolicy: Never
+# The Jenkins job requires a tag to build the Docker image.
+# By default this file is in the docker build directory,
+# but the location can configured in the JJB template.
+---
+tag: 0.1.0
@@ -2,7 +2,7 @@
 #   ========================LICENSE_START=================================
 #   O-RAN-SC
 #   %%
-#   Copyright (C) 2023: OpenInfra Foundation Europe
+#   Copyright (C) 2024: OpenInfra Foundation Europe
 #   %%
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
 #   ========================LICENSE_END===================================
 #
 
-image:
-  repository: nonrtric-hello-world
-  tag: latest
-
-service:
-  name: hello-world
-  type: NodePort
-  port: 8080
+version: "3.0"
 
+services:
+  hello-world-sme-invoker:
+    build:
+      context: ../../sample-services/hello-world-sme-invoker
+      dockerfile: Dockerfile
+    ports:
+      - 8080:8080
\ No newline at end of file
diff --git a/sample-services/hello-world-sme-invoker/hello-world-sme-invoker-build-start.sh b/sample-services/hello-world-sme-invoker/hello-world-sme-invoker-build-start.sh
new file mode 100644 (file)
index 0000000..1baf2c0
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe.
+#   %%
+#   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===================================
+#
+
+NAME="hello-world-sme-invoker"
+IMAGE_NAME="o-ran-sc/nonrtric-sample-helloworld-sme-invoker"
+
+docker build -t $IMAGE_NAME:latest .
+
+docker run --rm -d -p 8080:8080 --name $NAME $IMAGE_NAME
diff --git a/sample-services/hello-world-sme-invoker/hello-world-sme-invoker/Chart.yaml b/sample-services/hello-world-sme-invoker/hello-world-sme-invoker/Chart.yaml
new file mode 100644 (file)
index 0000000..1c00950
--- /dev/null
@@ -0,0 +1,44 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   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: hello-world-sme-invoker
+description: A Helm chart for NONRTRIC Hello World SME Invoker
+
+# 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: "0.1.0"
diff --git a/sample-services/hello-world-sme-invoker/hello-world-sme-invoker/templates/deployment.yaml b/sample-services/hello-world-sme-invoker/hello-world-sme-invoker/templates/deployment.yaml
new file mode 100644 (file)
index 0000000..f32bb9a
--- /dev/null
@@ -0,0 +1,46 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   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: hello-world-sme-invoker-deployment
+spec:
+  replicas: {{ .Values.replicaCount }}
+  selector:
+    matchLabels:
+      app: hello-world-sme-invoker-container
+  template:
+    metadata:
+      labels:
+        app: hello-world-sme-invoker-container
+    spec:
+      containers:
+        - name: {{ .Chart.Name }}
+          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
+          env:
+            - name: APP_ID
+              value: "{{ .Values.environment.appId }}"
+            - name: SME_DISCOVERY_ENDPOINT
+              value: "{{ .Values.environment.smeDiscoveryEndpoint }}"
+          ports:
+            - name: http
+              containerPort: {{ .Values.service.port }}
+
@@ -2,7 +2,7 @@
 #   ========================LICENSE_START=================================
 #   O-RAN-SC
 #   %%
-#   Copyright (C) 2023: OpenInfra Foundation Europe
+#   Copyright (C) 2024: OpenInfra Foundation Europe
 #   %%
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -21,9 +21,7 @@
 apiVersion: v1
 kind: Service
 metadata:
-  name: {{ include "hello-world-chart.fullname" . }}
-  labels:
-    {{- include "hello-world-chart.labels" . | nindent 4 }}
+  name: hello-world-sme-invoker-service
 spec:
   type: {{ .Values.service.type }}
   ports:
@@ -31,7 +29,6 @@ spec:
       targetPort: http
       protocol: TCP
       name: http
-      nodePort: 30951
   selector:
-    {{- include "hello-world-chart.selectorLabels" . | nindent 4 }}
+    app: hello-world-sme-invoker-container
 
diff --git a/sample-services/hello-world-sme-invoker/hello-world-sme-invoker/values.yaml b/sample-services/hello-world-sme-invoker/hello-world-sme-invoker/values.yaml
new file mode 100644 (file)
index 0000000..69c367e
--- /dev/null
@@ -0,0 +1,35 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   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===================================
+#
+
+image:
+  # use a released image (and port number) if one is available, or use a local/staging image in a development environment
+  repository: nexus3.o-ran-sc.org:10004/o-ran-sc/nonrtric-sample-helloworld-sme-invoker
+  tag: 0.1.0
+
+service:
+  name: hello-world-sme-invoker
+  type: ClusterIP
+  port: 8080
+
+environment:
+  appId:
+  smeDiscoveryEndpoint:
+
+
diff --git a/sample-services/hello-world-sme-invoker/pom.xml b/sample-services/hello-world-sme-invoker/pom.xml
new file mode 100644 (file)
index 0000000..50e2097
--- /dev/null
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+* ========================LICENSE_START=================================
+* O-RAN-SC
+* %%
+* Copyright (C) 2024 OpenInfra Foundation Europe.
+* %%
+* 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===================================
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>3.2.3</version>
+    </parent>
+
+    <groupId>org.o-ran-sc.nonrtric.plt</groupId>
+    <artifactId>hello-world-sme-invoker</artifactId>
+    <version>0.1.0</version>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/sample-services/hello-world-sme-invoker/src/main/java/org/oransc/nonrtric/sample/HelloWorldSmeInvokerApplication.java b/sample-services/hello-world-sme-invoker/src/main/java/org/oransc/nonrtric/sample/HelloWorldSmeInvokerApplication.java
new file mode 100644 (file)
index 0000000..b683611
--- /dev/null
@@ -0,0 +1,41 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2024 OpenInfra Foundation Europe.
+ * %%
+ * 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===================================
+ */
+
+package org.oransc.nonrtric.sample;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.web.client.RestTemplate;
+
+@SpringBootApplication(scanBasePackages = "org.oransc.nonrtric.sample")
+@EnableScheduling
+public class HelloWorldSmeInvokerApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(HelloWorldSmeInvokerApplication.class, args);
+    }
+
+    @Bean
+    public RestTemplate restTemplate(RestTemplateBuilder builder) {
+        return builder.build();
+    }
+}
@@ -1,38 +1,28 @@
-/*-\r
- * ========================LICENSE_START=================================\r
- * O-RAN-SC\r
- * %%\r
- * Copyright (C) 2023 OpenInfra Foundation Europe.\r
- * %%\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * ========================LICENSE_END===================================\r
- */\r
-\r
-package org.oran.helloworld.rest;\r
-\r
-import org.springframework.web.bind.annotation.RequestMapping;\r
-import org.springframework.web.bind.annotation.RestController;\r
-\r
-@RestController\r
-@RequestMapping("/helloworld")\r
-public class HelloWorldController {\r
-\r
-    @RequestMapping("")\r
-    public String helloWorld() {\r
-        return "Hello World from service stub\n";\r
-    }\r
-    @RequestMapping("/sme")\r
-    public String helloWorldSme() {\r
-        return "Hello World from SME\n";\r
-    }\r
-}\r
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2024 OpenInfra Foundation Europe.
+ * %%
+ * 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===================================
+ */
+
+package org.oransc.nonrtric.sample.exception;
+
+public class CapifAccessException extends RuntimeException {
+    public CapifAccessException(String message) {
+        super(message);
+    }
+}
+
diff --git a/sample-services/hello-world-sme-invoker/src/main/java/org/oransc/nonrtric/sample/exception/GlobalExceptionHandler.java b/sample-services/hello-world-sme-invoker/src/main/java/org/oransc/nonrtric/sample/exception/GlobalExceptionHandler.java
new file mode 100644 (file)
index 0000000..26b9b99
--- /dev/null
@@ -0,0 +1,39 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2024 OpenInfra Foundation Europe.
+ * %%
+ * 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===================================
+ */
+
+package org.oransc.nonrtric.sample.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+@ControllerAdvice
+public class GlobalExceptionHandler {
+
+    @ExceptionHandler(CapifAccessException.class)
+    public ResponseEntity<String> handleCapifAccessException(CapifAccessException ex) {
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+            .contentType(MediaType.TEXT_PLAIN)
+            .body(ex.getMessage());
+    }
+}
+
diff --git a/sample-services/hello-world-sme-invoker/src/main/java/org/oransc/nonrtric/sample/rest/HelloWorldSmeInvokerComponent.java b/sample-services/hello-world-sme-invoker/src/main/java/org/oransc/nonrtric/sample/rest/HelloWorldSmeInvokerComponent.java
new file mode 100644 (file)
index 0000000..0f70216
--- /dev/null
@@ -0,0 +1,159 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2024 OpenInfra Foundation Europe.
+ * %%
+ * 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===================================
+ */
+
+package org.oransc.nonrtric.sample.rest;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.ArrayList;
+import java.util.List;
+import org.oransc.nonrtric.sample.exception.CapifAccessException;
+import org.oransc.nonrtric.sample.rest.response.ApiResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+@Component
+public class HelloWorldSmeInvokerComponent {
+
+    private final RestTemplate restTemplate;
+    private final ObjectMapper objectMapper;
+    private static final Logger logger = LoggerFactory.getLogger(HelloWorldSmeInvokerComponent.class);
+
+    public HelloWorldSmeInvokerComponent(RestTemplate restTemplate, ObjectMapper objectMapper) {
+        this.restTemplate = restTemplate;
+        this.objectMapper = objectMapper;
+    }
+
+    @Scheduled(fixedRate = 5000)
+    public void accessHelloWorldByInvoker() {
+        String capifUrl = createCapifUrl();
+        if (capifUrl != null && !capifUrl.isEmpty()) {
+            String baseUrl = "";
+            ApiResponse apiResponse;
+            try {
+                apiResponse = restTemplate.getForObject(capifUrl, ApiResponse.class);
+                logger.info("Discovery endpoint response is {}",
+                        objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(apiResponse));
+                baseUrl = getBaseUrl(apiResponse);
+            } catch (IllegalArgumentException e) {
+                throw new CapifAccessException("Error accessing the URL :- " + capifUrl);
+            } catch (Exception e) {
+                throw new CapifAccessException("Unexpected error");
+            }
+
+            String helloWorldEndpoint = "";
+            List<String> apiSetEndpoints = getApiSetEndpoints(apiResponse, baseUrl);
+            if (apiSetEndpoints != null && !apiSetEndpoints.isEmpty()) {
+                helloWorldEndpoint = apiSetEndpoints.get(0);
+            }
+
+            if (helloWorldEndpoint != null && !helloWorldEndpoint.isEmpty()) {
+                try {
+                    String responseHelloWorld = restTemplate.getForObject(helloWorldEndpoint, String.class);
+                    logger.info("rApp SME Provider Response : {}", responseHelloWorld);
+                } catch (IllegalArgumentException e) {
+                    throw new CapifAccessException("Error accessing the URL :- " + helloWorldEndpoint);
+                } catch (Exception e) {
+                    throw new CapifAccessException("Unexpected error");
+                }
+            }
+        }
+    }
+
+    private String createCapifUrl() {
+        String appId = System.getenv("APP_ID");
+        String invokerId = "";
+        String capifUrl = "";
+        if (appId != null) {
+            logger.info("APP_ID: " + appId);
+            invokerId = "api_invoker_id_" + appId;
+            logger.info("invokerId: " + invokerId);
+        } else {
+            logger.info("APP_ID environment variable is not set. ");
+        }
+
+        String smeDiscoveryEndpoint = System.getenv("SME_DISCOVERY_ENDPOINT");
+        if (smeDiscoveryEndpoint != null) {
+            logger.info("SME_DISCOVERY_ENDPOINT: " + smeDiscoveryEndpoint);
+            capifUrl = smeDiscoveryEndpoint + "?api-invoker-id=" + invokerId;
+            logger.info("capifUrl: " + capifUrl);
+        } else {
+            logger.info("SME_DISCOVERY_ENDPOINT environment variable is not set.");
+        }
+        return capifUrl;
+    }
+
+    private static String getBaseUrl(ApiResponse apiResponse) {
+        if (apiResponse != null && apiResponse.getServiceAPIDescriptions() != null && !apiResponse.getServiceAPIDescriptions()
+                .isEmpty()) {
+
+            ApiResponse.ServiceAPIDescription serviceAPIDescription = apiResponse.getServiceAPIDescriptions().get(0);
+
+            if (serviceAPIDescription.getAefProfiles() != null && !serviceAPIDescription.getAefProfiles().isEmpty()) {
+
+                ApiResponse.AefProfile aefProfile = serviceAPIDescription.getAefProfiles().get(0);
+
+                if (aefProfile.getInterfaceDescriptions() != null && !aefProfile.getInterfaceDescriptions().isEmpty()) {
+                    ApiResponse.InterfaceDescription interfaceDescription = aefProfile.getInterfaceDescriptions().get(0);
+                    return "http://" + interfaceDescription.getIpv4Addr() + ":" + interfaceDescription.getPort();
+                }
+            }
+        }
+        return "";
+    }
+
+    private static List<String> getApiSetEndpoints(ApiResponse apiResponse, String baseUrl) {
+
+        String helloWorldEndpoint = "";
+        List<String> apiSetEndpoints = new ArrayList<>(5);
+
+        if (apiResponse != null && apiResponse.getServiceAPIDescriptions() != null && !apiResponse.getServiceAPIDescriptions()
+                .isEmpty()) {
+
+            ApiResponse.ServiceAPIDescription serviceAPIDescription = apiResponse.getServiceAPIDescriptions().get(0);
+
+            if (serviceAPIDescription.getAefProfiles() != null && !serviceAPIDescription.getAefProfiles().isEmpty()) {
+
+                ApiResponse.AefProfile aefProfile = serviceAPIDescription.getAefProfiles().get(0);
+
+                if (aefProfile.getInterfaceDescriptions() != null && !aefProfile.getInterfaceDescriptions().isEmpty()) {
+
+                    if (aefProfile.getVersions() != null && !aefProfile.getVersions().isEmpty()) {
+
+                        ApiResponse.ApiVersion apiVersion = aefProfile.getVersions().get(0);
+
+                        if (apiVersion.getResources() != null && !apiVersion.getResources().isEmpty()) {
+
+                            for (ApiResponse.Resource resource : apiVersion.getResources()) {
+                                helloWorldEndpoint = baseUrl + resource.getUri();
+                                logger.info("Complete URL for resource " + helloWorldEndpoint);
+                                apiSetEndpoints.add(helloWorldEndpoint);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return apiSetEndpoints;
+    }
+
+}
diff --git a/sample-services/hello-world-sme-invoker/src/main/java/org/oransc/nonrtric/sample/rest/response/ApiResponse.java b/sample-services/hello-world-sme-invoker/src/main/java/org/oransc/nonrtric/sample/rest/response/ApiResponse.java
new file mode 100644 (file)
index 0000000..e26e7a9
--- /dev/null
@@ -0,0 +1,215 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2024 OpenInfra Foundation Europe.
+ * %%
+ * 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===================================
+ */
+
+package org.oransc.nonrtric.sample.rest.response;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+
+public class ApiResponse {
+
+    @JsonProperty("serviceAPIDescriptions")
+    private List<ServiceAPIDescription> serviceAPIDescriptions;
+
+    public List<ServiceAPIDescription> getServiceAPIDescriptions() {
+        return serviceAPIDescriptions;
+    }
+
+    public void setServiceAPIDescriptions(List<ServiceAPIDescription> serviceAPIDescriptions) {
+        this.serviceAPIDescriptions = serviceAPIDescriptions;
+    }
+
+    public static class ServiceAPIDescription {
+        @JsonProperty("apiName")
+        private String apiName;
+
+        @JsonProperty("apiId")
+        private String apiId;
+
+        @JsonProperty("description")
+        private String description;
+
+        @JsonProperty("aefProfiles")
+        private List<AefProfile> aefProfiles;
+
+        public String getApiName() {
+            return apiName;
+        }
+
+        public void setApiName(String apiName) {
+            this.apiName = apiName;
+        }
+
+        public String getApiId() {
+            return apiId;
+        }
+
+        public void setApiId(String apiId) {
+            this.apiId = apiId;
+        }
+
+        public String getDescription() {
+            return description;
+        }
+
+        public void setDescription(String description) {
+            this.description = description;
+        }
+
+        public List<AefProfile> getAefProfiles() {
+            return aefProfiles;
+        }
+
+        public void setAefProfiles(List<AefProfile> aefProfiles) {
+            this.aefProfiles = aefProfiles;
+        }
+    }
+
+    public static class AefProfile {
+        private String aefId;
+        private String domainName;
+        private List<ApiVersion> versions;
+        private String protocol;
+        private List<InterfaceDescription> interfaceDescriptions;
+
+        public String getAefId() {
+            return aefId;
+        }
+
+        public String getDomainName() {
+            return domainName;
+        }
+
+        public void setDomainName(String domainName) {
+            this.domainName = domainName;
+        }
+
+        public void setAefId(String aefId) {
+            this.aefId = aefId;
+        }
+
+        public List<ApiVersion> getVersions() {
+            return versions;
+        }
+
+        public void setVersions(List<ApiVersion> versions) {
+            this.versions = versions;
+        }
+
+        public String getProtocol() {
+            return protocol;
+        }
+
+        public void setProtocol(String protocol) {
+            this.protocol = protocol;
+        }
+
+        public List<InterfaceDescription> getInterfaceDescriptions() {
+            return interfaceDescriptions;
+        }
+
+        public void setInterfaceDescriptions(
+            List<InterfaceDescription> interfaceDescriptions) {
+            this.interfaceDescriptions = interfaceDescriptions;
+        }
+    }
+
+    public static class ApiVersion {
+        private String apiVersion;
+        private List<Resource> resources;
+
+        public String getApiVersion() {
+            return apiVersion;
+        }
+
+        public void setApiVersion(String apiVersion) {
+            this.apiVersion = apiVersion;
+        }
+
+        public List<Resource> getResources() {
+            return resources;
+        }
+
+        public void setResources(List<Resource> resources) {
+            this.resources = resources;
+        }
+    }
+
+    public static class Resource {
+        private String resourceName;
+        private String commType;
+        private String uri;
+        private List<String> operations;
+
+        public String getResourceName() {
+            return resourceName;
+        }
+
+        public void setResourceName(String resourceName) {
+            this.resourceName = resourceName;
+        }
+
+        public String getCommType() {
+            return commType;
+        }
+
+        public void setCommType(String commType) {
+            this.commType = commType;
+        }
+
+        public String getUri() {
+            return uri;
+        }
+
+        public void setUri(String uri) {
+            this.uri = uri;
+        }
+
+        public List<String> getOperations() {
+            return operations;
+        }
+
+        public void setOperations(List<String> operations) {
+            this.operations = operations;
+        }
+    }
+
+    public static class InterfaceDescription {
+        private String ipv4Addr;
+        private int port;
+
+        public String getIpv4Addr() {
+            return ipv4Addr;
+        }
+
+        public void setIpv4Addr(String ipv4Addr) {
+            this.ipv4Addr = ipv4Addr;
+        }
+
+        public int getPort() {
+            return port;
+        }
+
+        public void setPort(int port) {
+            this.port = port;
+        }
+    }
+}
+
diff --git a/sample-services/hello-world/.gitignore b/sample-services/hello-world/.gitignore
new file mode 100644 (file)
index 0000000..5ff6309
--- /dev/null
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
similarity index 70%
rename from test/servicestub/README.md
rename to sample-services/hello-world/README.md
index 601e52a..f8650f8 100644 (file)
@@ -1,37 +1,37 @@
-# Hello World Service Stub\r
-\r
-This repository contains a Spring Boot application serving a Hello World endpoint. The application can be built and \r
-run using the provided script - ``service-stub-build-start.sh``.\r
-\r
-## Prerequisites\r
-\r
-- Docker installed on your machine.\r
-\r
-## Building and Running the Application\r
-Run the script:\r
-\r
-```bash\r
-  ./service-stub-build-start.sh\r
-```\r
-\r
-The script will build a Docker image and run a container with the Hello World service. After the container starts, \r
-wait for a few seconds to ensure the Spring Boot application is fully initialized. Next, it will make an HTTP request to the \r
-Hello World endpoint and display the response:\r
-\r
-```bash\r
-  response=$(curl -s http://localhost:8080/helloworld/sme)\r
-  echo "Response from the Hello World endpoint:"\r
-  echo "$response"\r
-```\r
-\r
-To stop and remove the Docker container:\r
-\r
-```bash\r
-  docker stop service-stub-hello-world-test\r
-  docker rm service-stub-hello-world-test\r
-```\r
-\r
-## Additional Information\r
-\r
-- The Hello World endpoint is available at http://localhost:8080/helloworld/sme.\r
-\r
+# Hello World Service
+
+This repository contains a Spring Boot application serving a Hello World endpoint. The application can be built and 
+run using the provided script - ``hello-world-build-start.sh``.
+
+## Prerequisites
+
+- Docker installed on your machine.
+
+## Building and Running the Application
+Run the script:
+
+```bash
+  ./hello-world-build-start.sh
+```
+
+The script will build a Docker image and run a container with the Hello World service. After the container starts, 
+wait for a few seconds to ensure the Spring Boot application is fully initialized. Next, it will make an HTTP request to the 
+Hello World endpoint and display the response:
+
+```bash
+  response=$(curl -s http://localhost:8080/helloworld/v1)
+  echo "Response from the Hello World endpoint:"
+  echo "$response"
+```
+
+To stop and remove the Docker container:
+
+```bash
+  docker stop hello-world
+  docker rm hello-world
+```
+
+## Additional Information
+
+- The Hello World endpoint is available at http://localhost:8080/helloworld/v1.
+
similarity index 98%
rename from test/servicestub/build.sh
rename to sample-services/hello-world/build.sh
index bb0ff80..a124724 100644 (file)
@@ -29,7 +29,7 @@ if [ $# -ne 1 ] && [ $# -ne 2 ]; then
     print_usage
 fi
 
-IMAGE_NAME="nonrtric-hello-world"
+IMAGE_NAME="o-ran-sc/nonrtric-sample-helloworld"
 IMAGE_TAG="latest"
 REPO=""
 if [ $1 == "no-push" ]; then
similarity index 93%
rename from test/servicestub/docker-compose.yml
rename to sample-services/hello-world/docker-compose.yml
index b137ec1..4c2ac67 100644 (file)
@@ -23,7 +23,7 @@ version: "3.0"
 services:
   hello-world:
     build: 
-      context: ./
+      context: ../../sample-services/hello-world
       dockerfile: Dockerfile
     ports:
       - 8080:8080
\ No newline at end of file
@@ -4,7 +4,7 @@
 #   ========================LICENSE_START=================================
 #   O-RAN-SC
 #   %%
-#   Copyright (C) 2023: OpenInfra Foundation Europe.
+#   Copyright (C) 2023-2024: OpenInfra Foundation Europe.
 #   %%
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -20,8 +20,8 @@
 #   ========================LICENSE_END===================================
 #
 
-NAME="service-stub-hello-world-test"
-IMAGE_NAME="nonrtric-hello-world"
+NAME="hello-world"
+IMAGE_NAME="o-ran-sc/nonrtric-sample-helloworld"
 
 docker build -t $IMAGE_NAME:latest .
 
@@ -30,11 +30,6 @@ docker run --rm -d -p 8080:8080 --name $NAME $IMAGE_NAME
 sleep 10
 
 echo "Make an HTTP request to the Hello World endpoint and display the response"
-response=$(curl -s http://localhost:8080/helloworld/sme)
-
-echo "Response from the /helloworld/sme endpoint: "
+response=$(curl -s http://localhost:8080/helloworld/v1)
+echo "Response from the /helloworld/v1 endpoint: "
 echo "$response"
-
-response2=$(curl -s http://localhost:8080/helloworld)
-echo "Response from the /helloworld endpoint: "
-echo "$response2"
diff --git a/sample-services/hello-world/hello-world-chart/.helmignore b/sample-services/hello-world/hello-world-chart/.helmignore
new file mode 100644 (file)
index 0000000..0e8a0eb
--- /dev/null
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
@@ -2,7 +2,7 @@
 #   ========================LICENSE_START=================================
 #   O-RAN-SC
 #   %%
-#   Copyright (C) 2023: OpenInfra Foundation Europe
+#   Copyright (C) 2023-2024: OpenInfra Foundation Europe
 #   %%
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
 apiVersion: apps/v1
 kind: Deployment
 metadata:
-  name: {{ include "hello-world-chart.fullname" . }}
-  labels:
-    {{- include "hello-world-chart.labels" . | nindent 4 }}
+  name: hello-world-chart-deployment
 spec:
   replicas: {{ .Values.replicaCount }}
   selector:
     matchLabels:
-      {{- include "hello-world-chart.selectorLabels" . | nindent 8 }}
+      app: hello-world-chart-container
   template:
     metadata:
       labels:
-        {{- include "hello-world-chart.selectorLabels" . | nindent 12 }}
+        app: hello-world-chart-container
     spec:
       containers:
         - name: {{ .Chart.Name }}
diff --git a/sample-services/hello-world/hello-world-chart/templates/service.yaml b/sample-services/hello-world/hello-world-chart/templates/service.yaml
new file mode 100644 (file)
index 0000000..9fa5e7a
--- /dev/null
@@ -0,0 +1,34 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2023-2024: OpenInfra Foundation Europe
+#   %%
+#   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: hello-world-chart-service
+spec:
+  type: {{ .Values.service.type }}
+  ports:
+    - port: {{ .Values.service.port }}
+      targetPort: http
+      protocol: TCP
+      name: http
+  selector:
+    app: hello-world-chart-container
+
diff --git a/sample-services/hello-world/hello-world-chart/values.yaml b/sample-services/hello-world/hello-world-chart/values.yaml
new file mode 100644 (file)
index 0000000..3feff4c
--- /dev/null
@@ -0,0 +1,30 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2023-2024: OpenInfra Foundation Europe
+#   %%
+#   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===================================
+#
+
+image:
+  # use a released image (and port number) if one is available, or use a local/staging image in a development environment.
+  repository: nexus3.o-ran-sc.org:10004/o-ran-sc/nonrtric-sample-helloworld
+  tag: 0.1.0
+
+service:
+  name: hello-world
+  type: ClusterIP
+  port: 8080
+
similarity index 98%
rename from test/servicestub/pom.xml
rename to sample-services/hello-world/pom.xml
index be7a791..c37384e 100644 (file)
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>3.2.3</version>
+    </parent>
+
     <groupId>org.o-ran-sc.nonrtric.plt</groupId>
     <artifactId>hello-world</artifactId>
     <version>0.1.0</version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     </properties>
 
-    <parent>
-        <groupId>org.springframework.boot</groupId>
-        <artifactId>spring-boot-starter-parent</artifactId>
-        <version>3.1.0</version>
-    </parent>
-
     <dependencies>
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -1,31 +1,31 @@
-/*-\r
- * ========================LICENSE_START=================================\r
- * O-RAN-SC\r
- * %%\r
- * Copyright (C) 2023 OpenInfra Foundation Europe.\r
- * %%\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * ========================LICENSE_END===================================\r
- */\r
-\r
-package org.oran.helloworld;\r
-\r
-import org.springframework.boot.SpringApplication;\r
-import org.springframework.boot.autoconfigure.SpringBootApplication;\r
-\r
-@SpringBootApplication(scanBasePackages = "org.oran.helloworld")\r
-public class HelloWorldApplication {\r
-    public static void main(String[] args) {\r
-        SpringApplication.run(HelloWorldApplication.class, args);\r
-    }\r
-}\r
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2023 OpenInfra Foundation Europe.
+ * %%
+ * 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===================================
+ */
+
+package org.oransc.nonrtric.sample;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication(scanBasePackages = "org.oransc.nonrtric.sample")
+public class HelloWorldApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(HelloWorldApplication.class, args);
+    }
+}
diff --git a/sample-services/hello-world/src/main/java/org/oransc/nonrtric/sample/rest/HelloWorldController.java b/sample-services/hello-world/src/main/java/org/oransc/nonrtric/sample/rest/HelloWorldController.java
new file mode 100644 (file)
index 0000000..cd11d71
--- /dev/null
@@ -0,0 +1,69 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2023-2024 OpenInfra Foundation Europe.
+ * %%
+ * 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===================================
+ */
+
+package org.oransc.nonrtric.sample.rest;
+
+import jakarta.servlet.http.HttpServletRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class HelloWorldController {
+
+    private static final Logger logger = LoggerFactory.getLogger(HelloWorldController.class);
+
+    @RequestMapping("/helloworld/v1")
+    public String helloWorld(HttpServletRequest request) {
+        String path = logRequestPath(request);
+        return "Hello from "+path;
+    }
+
+    @RequestMapping("/helloworld/v1/subpath1")
+    public String helloWorldSubpath1(HttpServletRequest request) {
+        String path = logRequestPath(request);
+        return "Hello from "+path;
+    }
+
+    @RequestMapping("/helloworld2/v1")
+    public String helloWorld2(HttpServletRequest request) {
+        String path = logRequestPath(request);
+        return "Hello from "+path;
+    }
+
+    @RequestMapping("/helloworld/v2")
+    public String helloWorldV2(HttpServletRequest request) {
+        String path = logRequestPath(request);
+        return "Hello from "+path;
+    }
+
+    @RequestMapping("/helloworld/v2/subpath1")
+    public String helloWorldSubpath1V2(HttpServletRequest request) {
+        String path = logRequestPath(request);
+        return "Hello from "+path;
+    }
+
+    private String logRequestPath(HttpServletRequest request) {
+        String path = request.getRequestURI();
+        logger.info("Received request for path: {}", path);
+        return path;
+    }
+}
diff --git a/sample-services/hello-world/src/test/java/org/oransc/nonrtric/sample/rest/HelloWorldControllerTest.java b/sample-services/hello-world/src/test/java/org/oransc/nonrtric/sample/rest/HelloWorldControllerTest.java
new file mode 100644 (file)
index 0000000..6d57588
--- /dev/null
@@ -0,0 +1,85 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2023-2024 OpenInfra Foundation Europe.
+ * %%
+ * 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===================================
+ */
+
+package org.oransc.nonrtric.sample.rest;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.mock.web.MockHttpServletRequest;
+
+@WebMvcTest(HelloWorldController.class)
+public class HelloWorldControllerTest {
+
+    @InjectMocks
+    private HelloWorldController helloWorldController;
+
+    @Test
+    public void testHelloWorldEndpoint() {
+        MockHttpServletRequest request = new MockHttpServletRequest();
+        request.setRequestURI("/helloworld/v1");
+
+        String result = helloWorldController.helloWorld(request);
+
+        assertEquals("Hello from /helloworld/v1", result);
+    }
+
+    @Test
+    public void testHelloWorldSubpathEndpoint() {
+        MockHttpServletRequest request = new MockHttpServletRequest();
+        request.setRequestURI("/helloworld/v1/subpath1");
+
+        String result = helloWorldController.helloWorldSubpath1(request);
+
+        assertEquals("Hello from /helloworld/v1/subpath1", result);
+    }
+
+    @Test
+    public void testHelloWorld2Endpoint() {
+        MockHttpServletRequest request = new MockHttpServletRequest();
+        request.setRequestURI("/helloworld2/v1");
+
+        String result = helloWorldController.helloWorld2(request);
+
+        assertEquals("Hello from /helloworld2/v1", result);
+    }
+
+    @Test
+    public void testHelloWorldEndpointV2() {
+        MockHttpServletRequest request = new MockHttpServletRequest();
+        request.setRequestURI("/helloworld/v2");
+
+        String result = helloWorldController.helloWorldV2(request);
+
+        assertEquals("Hello from /helloworld/v2", result);
+    }
+
+    @Test
+    public void testHelloWorldSubpathEndpointV2() {
+        MockHttpServletRequest request = new MockHttpServletRequest();
+        request.setRequestURI("/helloworld/v2/subpath1");
+
+        String result = helloWorldController.helloWorldSubpath1V2(request);
+
+        assertEquals("Hello from /helloworld/v2/subpath1", result);
+    }
+}
diff --git a/sample-services/ics-producer-consumer/.gitignore b/sample-services/ics-producer-consumer/.gitignore
new file mode 100644 (file)
index 0000000..48d83d4
--- /dev/null
@@ -0,0 +1,27 @@
+.idea
+.DS_Store
+target
+logging.log
+
+*.class
+logs/
+.vscode
+*.log
+
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+*.tgz
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
diff --git a/sample-services/ics-producer-consumer/README.md b/sample-services/ics-producer-consumer/README.md
new file mode 100644 (file)
index 0000000..1731c17
--- /dev/null
@@ -0,0 +1,102 @@
+<!--
+* ========================LICENSE_START=================================
+* O-RAN-SC
+*
+* Copyright (C) 2024 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===================================
+-->
+# Automatic
+### Using Kafka with a Java Producer and Consumer
+
+Run the demo script
+It will check prerequisites, build a consumer and producer, and run them with kafka and ICS.
+
+```shell
+./start.sh
+```
+Or run the other script to bring up RedPanda on port 8888 and NONRTRIC control panel UI on port 8181
+
+```shell
+./red.sh
+```
+
+For a faster execution you can add:
+
+--skip-build to skip creating the app jar and building the docker images
+
+--no-console to skip running RedPanda and NONRTRIC control panel
+
+```shell
+./red.sh --skip-build --no-console
+```
+# Manual
+### Run Kafka in a container
+
+```shell
+docker-compose up -d kafka-zkless
+```
+
+### Starting the REST application individually
+
+In a new terminal window:
+
+```shell
+mvn spring-boot:run
+```
+
+### Starting a producer
+
+```shell
+sh ./runproducer.sh
+```
+
+### Starting a Consumer
+
+```shell
+sh ./runproducer.sh
+```
+
+## Reading the logs
+
+A sample of the output is as follows:
+
+```
+Demo Producer Docker logs
+
+2024-04-02 12:48:05 INFO  c.d.p.p.SimpleProducer:141 - {"bootstrapServers":"kafka-zkless:9092","topic":"mytopic","source":"com.demo.producer.producer.SimpleProducer","message":"ygHwxXSIxW","key":"f8f1a7a7-a78e-4c7d-9b8d-108bb0cc9e2c"}
+2024-04-02 12:48:06 INFO  c.d.p.p.SimpleProducer:141 - {"bootstrapServers":"kafka-zkless:9092","topic":"mytopic","source":"com.demo.producer.producer.SimpleProducer","message":"KNIbP10zfN","key":"b058d00f-bbcd-4d2c-936b-6327847d4c2a"}
+2024-04-02 12:48:07 INFO  c.d.p.p.SimpleProducer:141 - {"bootstrapServers":"kafka-zkless:9092","topic":"mytopic","source":"com.demo.producer.producer.SimpleProducer","message":"V6fH1NkdeH","key":"ae1a83a3-d8a7-40c8-9d98-529230f8b585"}
+2024-04-02 12:48:08 INFO  c.d.p.p.SimpleProducer:141 - {"bootstrapServers":"kafka-zkless:9092","topic":"mytopic","source":"com.demo.producer.producer.SimpleProducer","message":"m76qvRFh6f","key":"abccde52-fa72-4fd4-99ab-5bc21514d825"}
+2024-04-02 12:48:09 INFO  c.d.p.p.SimpleProducer:141 - {"bootstrapServers":"kafka-zkless:9092","topic":"mytopic","source":"com.demo.producer.producer.SimpleProducer","message":"t7FJYnFr43","key":"0602239e-34e9-45a6-a04a-3c67b4c7d9e4"}
+
+++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Demo Consumer Docker logs
+
+2024-04-02 12:48:05 INFO  c.d.c.c.SimpleConsumer:158 - {"message":"Topic: mytopicMessage: ygHwxXSIxW"}
+2024-04-02 12:48:06 INFO  c.d.c.c.SimpleConsumer:158 - {"message":"Topic: mytopicMessage: KNIbP10zfN"}
+2024-04-02 12:48:07 INFO  c.d.c.c.SimpleConsumer:158 - {"message":"Topic: mytopicMessage: V6fH1NkdeH"}
+2024-04-02 12:48:08 INFO  c.d.c.c.SimpleConsumer:158 - {"message":"Topic: mytopicMessage: m76qvRFh6f"}
+2024-04-02 12:48:09 INFO  c.d.c.c.SimpleConsumer:158 - {"message":"Topic: mytopicMessage: t7FJYnFr43"}
+
+++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ICS logs
+
+2024-04-02T12:48:05.615Z DEBUG 1 --- [or-http-epoll-2] o.o.i.c.r1producer.ProducerCallbacks     : Job subscription 1 started OK 1
+2024-04-02T12:48:05.820Z DEBUG 1 --- [io-8083-exec-10] o.o.i.repository.InfoTypeSubscriptions   : Added type status subscription 1
+```
+
+The script will fail (exit 1) if there are anny ERRORS logged in the kafka-producer and kafka-consumer.
\ No newline at end of file
diff --git a/sample-services/ics-producer-consumer/application.yaml b/sample-services/ics-producer-consumer/application.yaml
new file mode 100644 (file)
index 0000000..cfb4f78
--- /dev/null
@@ -0,0 +1,83 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2019-2022 Nordix Foundation. 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=================================================
+#
+
+spring:
+  profiles:
+    active: prod
+  main:
+    allow-bean-definition-overriding: true
+  aop:
+    auto: false
+springdoc:
+  show-actuator: true
+management:
+  endpoints:
+    web:
+      exposure:
+        # Enabling of springboot actuator features. See springboot documentation.
+        include: "loggers,logfile,health,info,metrics,threaddump,heapdump,shutdown"
+  endpoint:
+    shutdown:
+      enabled: true
+lifecycle:
+  timeout-per-shutdown-phase: "20s"
+logging:
+  # Configuration of logging
+  level:
+    ROOT: INFO
+    org.springframework: INFO
+    org.springframework.data: INFO
+    org.springframework.web.reactive.function.client.ExchangeFunctions: INFO
+    org.oransc.ics: DEBUG
+  file:
+    name: /var/log/information-coordinator-service/application.log
+server:
+   # Configuration of the HTTP/REST server. The parameters are defined and handeled by the springboot framework.
+   # See springboot documentation.
+   port : 8434
+   http-port: 8083
+   ssl:
+      key-store-type: JKS
+      key-store-password: policy_agent
+      key-store: /opt/app/information-coordinator-service/etc/cert/keystore.jks
+      key-password: policy_agent
+      key-alias: policy_agent
+   shutdown: "graceful"
+app:
+  webclient:
+    # Configuration of the trust store used for the HTTP client (outgoing requests)
+    # The file location and the password for the truststore is only relevant if trust-store-used == true
+    # Note that the same keystore as for the server is used.
+    trust-store-used: false
+    trust-store-password: policy_agent
+    trust-store: /opt/app/information-coordinator-service/etc/cert/truststore.jks
+    # Configuration of usage of HTTP Proxy for the southbound accesses.
+    # The HTTP proxy (if configured) will only be used for accessing NearRT RIC:s
+    http.proxy-host:
+    http.proxy-port: 0
+  vardata-directory: /var/information-coordinator-service
+  # If the file name is empty, no authorization token is used
+  auth-token-file:
+  # A URL to authorization provider such as OPA. Each time a information job is accessed, a call to this
+  # authorization provider is done for access control. If this is empty, no fine grained access control is done.
+  info-job-authorization-agent:
+  # S3 object store usage is enabled by defining the bucket to use. This will override the vardata-directory parameter.
+  s3:
+    endpointOverride: http://localhost:9000
+    accessKeyId: minio
+    secretAccessKey: miniostorage
+    bucket:
\ No newline at end of file
diff --git a/sample-services/ics-producer-consumer/consumer/Dockerfile b/sample-services/ics-producer-consumer/consumer/Dockerfile
new file mode 100644 (file)
index 0000000..d5d6f2a
--- /dev/null
@@ -0,0 +1,49 @@
+#==================================================================================
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#
+#   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.
+#
+#   This source code is part of the near-RT RIC (RAN Intelligent Controller)
+#   platform project (RICP).
+#==================================================================================
+
+# Use Maven image with OpenJDK 17 for the build stage
+FROM maven:3.8.5-openjdk-17 AS maven_build
+
+# Copy Maven project files
+COPY pom.xml /tmp/
+COPY src /tmp/src/
+
+# Set working directory
+WORKDIR /tmp/
+
+# Build the Maven project
+RUN mvn package
+
+# Use a separate image with OpenJDK 17 for the runtime stage
+FROM openjdk:17-jdk-slim
+
+# Expose port 8081
+EXPOSE 8081
+
+ARG KAFKA_SERVERS
+ENV KAFKA_SERVERS=${KAFKA_SERVERS}
+
+# Set the working directory
+WORKDIR /app
+
+# Copy the JAR file from the maven_build stage to the runtime stage
+COPY --from=maven_build /tmp/target/consumer-0.0.1.jar /app/consumer-0.0.1.jar
+
+# Command to run the application
+CMD ["java", "-jar", "consumer-0.0.1.jar"]
diff --git a/sample-services/ics-producer-consumer/consumer/Makefile b/sample-services/ics-producer-consumer/consumer/Makefile
new file mode 100644 (file)
index 0000000..4e87cd3
--- /dev/null
@@ -0,0 +1,51 @@
+#  ========================LICENSE_START=================================
+#  O-RAN-SC
+#
+#  Copyright (C) 2024: OpenInfra Foundation Europe
+#  ========================================================================
+#  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=================================================
+
+# Define variables
+IMAGE_NAME = "o-ran-sc/nonrtric-sample-icsconsumer"
+DOCKERFILE = Dockerfile
+
+# Default target
+.PHONY: all
+all: build run
+
+# Target to build the Maven JAR
+.PHONY: jar
+jar:
+       mvn clean package
+
+# Target to build the Docker image
+.PHONY: build
+build:
+       docker build -t $(IMAGE_NAME) -f $(DOCKERFILE) .
+
+# Target to run the Docker container
+.PHONY: run
+run:
+       docker run -p 8081:8081 $(IMAGE_NAME)
+
+# Target to stop and remove the Docker container
+.PHONY: stop
+stop:
+       docker stop $(IMAGE_NAME) || true
+       docker rm $(IMAGE_NAME) || true
+
+# Target to clean up
+.PHONY: clean
+clean: stop
+       docker rmi $(IMAGE_NAME) || true
diff --git a/sample-services/ics-producer-consumer/consumer/container-tag.yaml b/sample-services/ics-producer-consumer/consumer/container-tag.yaml
new file mode 100644 (file)
index 0000000..6423243
--- /dev/null
@@ -0,0 +1,23 @@
+#  ========================LICENSE_START=================================
+#  O-RAN-SC
+#
+#  Copyright (C) 2024: OpenInfra Foundation Europe
+#  ========================================================================
+#  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=================================================
+
+# The Jenkins job requires a tag to build the Docker image.
+# By default this file is in the docker build directory,
+# but the location can configured in the JJB template.
+---
+tag: 0.0.1
\ No newline at end of file
diff --git a/sample-services/ics-producer-consumer/consumer/pom.xml b/sample-services/ics-producer-consumer/consumer/pom.xml
new file mode 100644 (file)
index 0000000..84a6ae8
--- /dev/null
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+* ========================LICENSE_START=================================
+* O-RAN-SC
+*
+* Copyright (C) 2024 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===================================
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>3.2.3</version>
+        <relativePath/>
+    </parent>
+
+    <groupId>com.demo.consumer</groupId>
+    <artifactId>consumer</artifactId>
+    <version>0.0.1</version>
+    <packaging>jar</packaging>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients -->
+        <dependency>
+            <groupId>org.apache.kafka</groupId>
+            <artifactId>kafka-clients</artifactId>
+            <version>3.7.0</version>
+            <!--<scope>provided</scope> -->
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+           <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.18.24</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.10.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.googlecode.json-simple</groupId>
+            <artifactId>json-simple</artifactId>
+            <version>1.1.1</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <mainClass>com.demo.consumer.Application</mainClass>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/Application.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/Application.java
new file mode 100644 (file)
index 0000000..0ba278b
--- /dev/null
@@ -0,0 +1,57 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+import com.demo.consumer.consumer.SimpleConsumer;
+import com.demo.consumer.messages.KafkaMessageHandlerImpl;
+
+@SpringBootApplication
+@EnableAsync
+public class Application {
+
+    @Autowired
+    private SimpleConsumer simpleConsumer;
+
+    @Value("${vars.autostart:false}")
+    private boolean autostart;
+
+    @Value("${vars.topic}")
+    private String topic;
+
+    public static void main(String[] args) throws Exception {
+        SpringApplication.run(Application.class, args);
+    }
+
+    @EventListener(ApplicationReadyEvent.class)
+    public void checkAutoRun() throws Exception{
+        if (autostart) {
+            simpleConsumer.runAlways(topic, new KafkaMessageHandlerImpl());
+        }
+    }
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/consumer/SimpleConsumer.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/consumer/SimpleConsumer.java
new file mode 100644 (file)
index 0000000..1d91afb
--- /dev/null
@@ -0,0 +1,143 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.consumer;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.apache.kafka.clients.consumer.ConsumerRecords;
+import org.apache.kafka.clients.consumer.KafkaConsumer;
+import org.apache.kafka.common.TopicPartition;
+import org.apache.kafka.common.errors.WakeupException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import com.demo.consumer.messages.AbstractSimpleKafka;
+import com.demo.consumer.messages.KafkaMessageHandler;
+import com.demo.consumer.messages.MessageHelper;
+import com.demo.consumer.messages.PropertiesHelper;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Properties;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.time.Duration;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+@Component
+@Setter
+@Getter
+public class SimpleConsumer extends AbstractSimpleKafka {
+    private static final Logger log = LoggerFactory.getLogger(SimpleConsumer.class);
+
+    private KafkaConsumer<String, String> kafkaConsumer = null;
+    private final AtomicBoolean closed = new AtomicBoolean(false);
+
+    @Value("${vars.time:2000}")
+    private int TIME_OUT_MS;
+
+    public void run(String topicName, int numberOfRecords, KafkaMessageHandler callback) throws Exception {
+        Properties props = PropertiesHelper.getProperties();
+        // See if the number of records is provided
+        Optional<Integer> recs = Optional.ofNullable(numberOfRecords);
+
+        // adjust the number of records to get accordingly
+        Integer numOfRecs = recs.orElseGet(() -> Integer.parseInt(props.getProperty("max.poll.records")));
+        props.setProperty("max.poll.records", String.valueOf(numOfRecs));
+
+        // create the consumer
+        KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
+
+        // make the consumer available for graceful shutdown
+        setKafkaConsumer(consumer);
+        consumer.assign(Collections.singleton(new TopicPartition(topicName, 0)));
+        int recNum = numOfRecs;
+        while (recNum > 0) {
+            ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(TIME_OUT_MS));
+            recNum = records.count();
+            if (recNum == 0) {
+                log.info(MessageHelper.getSimpleJSONObject("No records retrieved").toJSONString());
+                break;
+            }
+
+            for (ConsumerRecord<String, String> record : records) {
+                callback.processMessage(topicName, record);
+                recNum--;
+            }
+        }
+        consumer.close();
+    }
+
+    private void close() throws Exception {
+        if (this.getKafkaConsumer() == null) {
+            log.info(MessageHelper.getSimpleJSONObject("The internal consumer is NULL").toJSONString());
+            return;
+        }
+        log.info(MessageHelper.getSimpleJSONObject("Closing consumer").toJSONString());
+        this.getKafkaConsumer().close();
+    }
+
+    public void runAlways(String topicName, KafkaMessageHandler callback) throws Exception {
+        Properties props = PropertiesHelper.getProperties();
+        // make the consumer available for graceful shutdown
+        setKafkaConsumer(new KafkaConsumer<>(props));
+
+        // keep running forever or until shutdown() is called from another thread.
+        try {
+            getKafkaConsumer().subscribe(List.of(topicName));
+            while (!closed.get()) {
+                ConsumerRecords<String, String> records = getKafkaConsumer().poll(Duration.ofMillis(TIME_OUT_MS));
+                if (records.count() == 0) {
+                    log.info(MessageHelper.getSimpleJSONObject("No records retrieved").toJSONString());
+                }
+
+                for (ConsumerRecord<String, String> record : records) {
+                    callback.processMessage(topicName, record);
+                    log.info(MessageHelper.getSimpleJSONObject("Topic: " + topicName + "Message: " + record.value()).toJSONString());
+                }
+            }
+        } catch (WakeupException e) {
+            // Ignore exception if closing
+            if (!closed.get())
+                throw e;
+        }
+    }
+
+    public void shutdown() {
+        closed.set(true);
+        try {
+            log.info(MessageHelper.getSimpleJSONObject("Shutting down consumer").toJSONString());
+        } catch (Exception e) {
+        }
+        getKafkaConsumer().wakeup();
+    }
+
+    public KafkaConsumer<String, String> getKafkaConsumer() {
+        return kafkaConsumer;
+    }
+
+    public void setKafkaConsumer(KafkaConsumer<String, String> kafkaConsumer) {
+        this.kafkaConsumer = kafkaConsumer;
+    }
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/controllers/ConsumerController.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/controllers/ConsumerController.java
new file mode 100644 (file)
index 0000000..30225c7
--- /dev/null
@@ -0,0 +1,94 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.controllers;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.demo.consumer.repository.InfoType;
+import com.demo.consumer.repository.InfoTypes;
+import com.demo.consumer.repository.Job.Parameters;
+import com.demo.consumer.repository.Job.Parameters.KafkaDeliveryInfo;
+import com.demo.consumer.dme.ConsumerJobInfo;
+import com.demo.consumer.dme.JobDataSchema;
+import com.demo.consumer.repository.Jobs;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+@RestController
+@RequestMapping(path = "/consumer", produces = "application/json")
+public class ConsumerController {
+    private static final Logger log = LoggerFactory.getLogger(ConsumerController.class);
+
+    private static Gson gson = new GsonBuilder().create();
+
+    private final Jobs jobs;
+    private final InfoTypes types;
+
+    public ConsumerController(@Autowired Jobs jobs, @Autowired InfoTypes types) {
+        this.jobs = jobs;
+        this.types = types;
+        InfoType type1 = InfoType.builder().build();
+        Parameters p = Parameters.builder().build();
+        type1.setId("type1");
+        type1.setKafkaInputTopic("mytopic");
+        type1.setInputJobType("type1");
+        type1.setInputJobDefinition(p);
+        types.put(type1);
+    }
+
+    @PostMapping("/job/{infoJobId}")
+    public void startinfojob(@RequestBody String requestBody, @PathVariable String infoJobId) {
+        ConsumerJobInfo request = gson.fromJson(requestBody, ConsumerJobInfo.class);
+        log.info("Add Job Info" + infoJobId, request);
+        try {
+            this.jobs.addJob(request.infoTypeId, types.getType(request.infoTypeId), request.owner,
+                    toJobParameters(request.jobDefinition));
+        } catch (Exception e) {
+            log.error("Error adding the job " + infoJobId + "{}", e.getMessage());
+        }
+    }
+
+    @PostMapping("/info-type-status")
+    public void statusChange(@RequestBody String requestBody) {
+        JobDataSchema request = gson.fromJson(requestBody, JobDataSchema.class);
+        log.debug("Body Received: {}" , requestBody);
+        try {
+            this.jobs.addJob(request.getInfo_type_id(), types.getType(request.getInfo_type_id()), "",
+                new Parameters(new KafkaDeliveryInfo(
+                        request.getJob_data_schema().getTopic(),
+                        request.getJob_data_schema().getBootStrapServers(), 0)));
+        } catch (Exception e) {
+            log.error("Error adding the info type " + request.getInfo_type_id() + "{}", e.getMessage());
+        }
+    }
+
+    private Parameters toJobParameters(Object jobData) {
+        String json = gson.toJson(jobData);
+        return gson.fromJson(json, Parameters.class);
+    }
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/controllers/ThreadsController.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/controllers/ThreadsController.java
new file mode 100644 (file)
index 0000000..f668e3a
--- /dev/null
@@ -0,0 +1,93 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.controllers;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.demo.consumer.consumer.SimpleConsumer;
+import com.demo.consumer.messages.ApplicationMessageHandlerImpl;
+
+@RestController
+public class ThreadsController {
+    private static final Logger log = LoggerFactory.getLogger(ThreadsController.class);
+
+    @Autowired
+    private SimpleConsumer simpleConsumer;
+
+    private Thread consumerThread;
+
+    @Async
+    @GetMapping("/startConsumer/{topicName}")
+    public CompletableFuture<String> startConsumer(@PathVariable("topicName") String topicName) {
+        try {
+            Thread consumerThread = new Thread(() -> {
+                try {
+                    simpleConsumer.runAlways(topicName, new ApplicationMessageHandlerImpl());
+                } catch (Exception e) {
+                    log.error("Error starting consuming on: " + topicName, e.getMessage());
+                }
+            });
+            consumerThread.start();
+            return CompletableFuture.completedFuture("Consumer started for topic: " + topicName);
+        } catch (Exception e) {
+            return CompletableFuture.failedFuture(e);
+        }
+    }
+
+    @GetMapping("/stopConsumer")
+    public String stopConsumer() {
+        if (consumerThread != null && consumerThread.isAlive()) {
+            try {
+                simpleConsumer.shutdown();
+            } catch (Exception e) {
+                log.error("Error stopping consumer Thread", e.getMessage());
+            }
+            return "Consumer stopped successfully";
+        } else {
+            return "No active consumer to stop";
+        }
+    }
+
+    @GetMapping("/listen/{numberOfMessages}/on/{topicName}")
+    public CompletableFuture<String> listenMessage(@PathVariable int numberOfMessages, @PathVariable String topicName) {
+        try {
+            Thread consumerThread = new Thread(() -> {
+                try {
+                    simpleConsumer.run(topicName, numberOfMessages, new ApplicationMessageHandlerImpl());
+                } catch (Exception e) {
+                    log.error("Error starting consuming on: " + topicName, e.getMessage());
+                }
+            });
+            consumerThread.start();
+            return CompletableFuture.completedFuture("Consumer started for topic: " + topicName);
+        } catch (Exception e) {
+            return CompletableFuture.failedFuture(e);
+        }
+    }
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/dme/ConsumerJobInfo.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/dme/ConsumerJobInfo.java
new file mode 100644 (file)
index 0000000..b3cd416
--- /dev/null
@@ -0,0 +1,52 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.dme;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@AllArgsConstructor
+public class ConsumerJobInfo {
+
+    @SerializedName("info_type_id")
+    @JsonProperty(value = "info_type_id", required = true)
+    public String infoTypeId = "";
+
+    @SerializedName("job_owner")
+    @JsonProperty(value = "job_owner", required = true)
+    public String owner = "";
+
+    @SerializedName("job_definition")
+    @JsonProperty(value = "job_definition", required = true)
+    public Object jobDefinition;
+
+    @SerializedName("job_result_uri")
+    @JsonProperty(value = "job_result_uri", required = true)
+    public String jobResultUri = "";
+
+    @SerializedName("status_notification_uri")
+    @JsonProperty(value = "status_notification_uri", required = false)
+    public String statusNotificationUri = "";
+
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/dme/ConsumerStatusInfo.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/dme/ConsumerStatusInfo.java
new file mode 100644 (file)
index 0000000..46f1a3f
--- /dev/null
@@ -0,0 +1,47 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.dme;
+
+import java.util.Collection;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@AllArgsConstructor
+public class ConsumerStatusInfo {
+
+    public enum InfoJobStatusValues {
+        REGISTERED, UNREGISTERED
+    }
+
+    @SerializedName("info_job_status")
+    @JsonProperty(value = "info_job_status", required = true)
+    public InfoJobStatusValues state;
+
+    @SerializedName("producers")
+    @JsonProperty(value = "producers", required = true)
+    public Collection<String> producers;
+
+}
+
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/dme/JobDataSchema.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/dme/JobDataSchema.java
new file mode 100644 (file)
index 0000000..678f536
--- /dev/null
@@ -0,0 +1,59 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.dme;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+
+import com.demo.consumer.repository.Job.Parameters.KafkaDeliveryInfo;
+import com.google.gson.Gson;
+
+@Data
+public class JobDataSchema {
+
+    public enum InfoJobStatusValues {
+        REGISTERED, UNREGISTERED
+    }
+    @SerializedName("info_type_id")
+    private String info_type_id;
+    @SerializedName("job_data_schema")
+    private DataSchema job_data_schema;
+    @SerializedName("status")
+    private InfoJobStatusValues status;
+
+    @Override
+    public String toString() {
+        return new Gson().toJson(this);
+    }
+
+    @Getter
+    @Setter
+    public class DataSchema {
+        private String title;
+        private String description;
+        @SerializedName("topic")
+        private String topic;
+        @SerializedName("bootStrapServers")
+        private String bootStrapServers;
+    }
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/AbstractSimpleKafka.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/AbstractSimpleKafka.java
new file mode 100644 (file)
index 0000000..4f817a9
--- /dev/null
@@ -0,0 +1,42 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.messages;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractSimpleKafka {
+    private static final Logger log = LoggerFactory.getLogger(AbstractSimpleKafka.class);
+
+    public AbstractSimpleKafka(){
+        Runtime.getRuntime().addShutdownHook(new Thread() {
+            @Override
+            public void run() {
+                    shutdown();
+            }
+        });
+        log.info(MessageHelper.getSimpleJSONObject("Created the Shutdown Hook").toJSONString());
+    }
+
+    public abstract void shutdown();
+    public abstract void runAlways(String topicName, KafkaMessageHandler callback) throws Exception;
+    public abstract void run(String topicName, int numberOfMessages, KafkaMessageHandler callback) throws Exception;
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/ApplicationMessageHandlerImpl.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/ApplicationMessageHandlerImpl.java
new file mode 100644 (file)
index 0000000..ed4a930
--- /dev/null
@@ -0,0 +1,39 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.messages;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.json.simple.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ApplicationMessageHandlerImpl implements KafkaMessageHandler {
+
+    private static final Logger log = LoggerFactory.getLogger(ApplicationMessageHandlerImpl.class);
+
+    @Override
+    public void processMessage(String topicName, ConsumerRecord<String, String> message) throws Exception {
+        String source = KafkaMessageHandlerImpl.class.getName();
+        JSONObject obj = MessageHelper.getMessageLogEntryJSON(source, topicName, message.key(), message.value());
+        System.out.println(obj.toJSONString());
+        log.info(obj.toJSONString());
+    }
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/KafkaMessageHandler.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/KafkaMessageHandler.java
new file mode 100644 (file)
index 0000000..9c16f9e
--- /dev/null
@@ -0,0 +1,28 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.messages;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+
+@FunctionalInterface
+public interface KafkaMessageHandler {
+    void processMessage(String topicName, ConsumerRecord<String, String> message) throws Exception;
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/KafkaMessageHandlerImpl.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/KafkaMessageHandlerImpl.java
new file mode 100644 (file)
index 0000000..8ff36fe
--- /dev/null
@@ -0,0 +1,37 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.messages;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.json.simple.JSONObject;
+
+public class KafkaMessageHandlerImpl implements KafkaMessageHandler {
+    private static final Logger log = LoggerFactory.getLogger(KafkaMessageHandlerImpl.class);
+
+    @Override
+    public void processMessage(String topicName, ConsumerRecord<String, String> message) throws Exception {
+        String source = KafkaMessageHandlerImpl.class.getName();
+        JSONObject obj = MessageHelper.getMessageLogEntryJSON(source, topicName, message.key(), message.value());
+        log.info(obj.toJSONString());
+    }
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/MessageHelper.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/MessageHelper.java
new file mode 100644 (file)
index 0000000..21063cc
--- /dev/null
@@ -0,0 +1,73 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.messages;
+
+import java.util.Properties;
+import java.util.Random;
+import org.json.simple.JSONObject;
+
+/**
+ * The type Message helper.
+ */
+public class MessageHelper {
+
+    private static Properties props;
+
+    public static String getRandomString() {
+        int leftLimit = 48; // numeral '0'
+        int rightLimit = 122; // letter 'z'
+        int targetStringLength = 10;
+        Random random = new Random();
+
+        return random.ints(leftLimit, rightLimit + 1).filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97))
+                .limit(targetStringLength)
+                .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
+    }
+
+    @SuppressWarnings("unchecked") // Using only strings
+    public static JSONObject getMessageLogEntryJSON(String source, String topic, String key, String message)
+            throws Exception {
+        JSONObject obj = new JSONObject();
+        String bootstrapServers = getProperties().getProperty("bootstrap.servers");
+        obj.put("bootstrapServers", bootstrapServers);
+        obj.put("source", source);
+        obj.put("topic", topic);
+        obj.put("key", key);
+        obj.put("message", message);
+
+        return obj;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static JSONObject getSimpleJSONObject(String message) {
+        JSONObject obj = new JSONObject();
+        obj.put("message", message);
+        return obj;
+    }
+
+    protected static Properties getProperties() throws Exception {
+        if (props == null) {
+            props = PropertiesHelper.getProperties();
+        }
+        return props;
+    }
+
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/PropertiesHelper.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/messages/PropertiesHelper.java
new file mode 100644 (file)
index 0000000..c4bd436
--- /dev/null
@@ -0,0 +1,73 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.messages;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import com.demo.consumer.consumer.SimpleConsumer;
+
+@Component
+public class PropertiesHelper {
+    private static final Logger log = LoggerFactory.getLogger(PropertiesHelper.class);
+    private static String kafkaServers = null;
+
+    public static Properties getProperties() throws Exception {
+        Properties props = new Properties();
+        try (InputStream input = SimpleConsumer.class.getClassLoader().getResourceAsStream("config.properties")) {
+            if (input == null) {
+                log.error("Failed to load configuration file 'config.properties'");
+                throw new IOException("Configuration file 'config.properties' not found");
+            }
+            props.load(input);
+            setBootstrapServers(props);
+        } catch (IOException e) {
+            log.error("Error reading configuration file: ", e);
+            throw e;
+        }
+        return props;
+    }
+
+    private static void setBootstrapServers(Properties props) {
+        if (kafkaServers != null && !kafkaServers.isEmpty()) {
+            props.setProperty("bootstrap.servers", kafkaServers);
+            log.info("Using actively bootstrap servers: {}", kafkaServers);
+        } else {
+            String kafkaServersEnv = System.getenv("KAFKA_SERVERS");
+            if (kafkaServersEnv != null && !kafkaServersEnv.isEmpty()) {
+                kafkaServers = kafkaServersEnv;
+                props.setProperty("bootstrap.servers", kafkaServers);
+                log.info("Using environment variable KAFKA_SERVERS: {}", kafkaServers);
+            } else {
+                log.info("Environment variable KAFKA_SERVERS not found, defaulting to config file");
+            }
+        }
+    }
+
+    public static void setKafkaServers(String servers) {
+        kafkaServers = servers;
+    }
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/repository/InfoType.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/repository/InfoType.java
new file mode 100644 (file)
index 0000000..45b4c7c
--- /dev/null
@@ -0,0 +1,49 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.repository;
+
+import lombok.AccessLevel;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+@ToString
+@Builder(access = AccessLevel.PUBLIC)
+public class InfoType {
+
+    @Getter
+    @Setter
+    private String id;
+
+    @Getter
+    @Setter
+    private String kafkaInputTopic;
+
+    @Getter
+    @Setter
+    private String inputJobType;
+
+    @Getter
+    @Setter
+    private Object inputJobDefinition;
+
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/repository/InfoTypes.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/repository/InfoTypes.java
new file mode 100644 (file)
index 0000000..f1e83be
--- /dev/null
@@ -0,0 +1,81 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.repository;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+
+@Component
+public class InfoTypes {
+    private static final Logger logger = LoggerFactory.getLogger(InfoTypes.class);
+
+    private Map<String, InfoType> allTypes = new HashMap<>();
+
+    public InfoTypes(Collection<InfoType> types) {
+        for (InfoType type : types) {
+            put(type);
+        }
+    }
+
+    public synchronized InfoType get(String id) {
+        return allTypes.get(id);
+    }
+
+    public synchronized InfoType getType(String id) throws Exception {
+        InfoType type = allTypes.get(id);
+        if (type == null) {
+            throw new Exception("Could not find type: " + id + HttpStatus.NOT_FOUND.toString());
+        }
+        return type;
+    }
+
+    public static class ConfigFile {
+        Collection<InfoType> types;
+    }
+
+    public synchronized void put(InfoType type) {
+        logger.debug("Put type: {}", type.getId());
+        allTypes.put(type.getId(), type);
+    }
+
+    public synchronized Iterable<InfoType> getAll() {
+        return new Vector<>(allTypes.values());
+    }
+
+    public synchronized Collection<String> typeIds() {
+        return allTypes.keySet();
+    }
+
+    public synchronized int size() {
+        return allTypes.size();
+    }
+
+    public synchronized void clear() {
+        allTypes.clear();
+    }
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/repository/Job.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/repository/Job.java
new file mode 100644 (file)
index 0000000..e681714
--- /dev/null
@@ -0,0 +1,74 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.repository;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.ToString;
+
+@ToString
+public class Job {
+    @AllArgsConstructor
+    @Builder
+    public static class Parameters {
+
+        @AllArgsConstructor
+        @Builder
+        @EqualsAndHashCode
+        public static class KafkaDeliveryInfo {
+            @Getter
+            private String topic;
+
+            @Getter
+            private String bootStrapServers;
+
+            @JsonProperty(value = "numberOfMessages")
+            @Getter
+            private int numberOfMessages;
+        }
+
+        @Getter
+        private KafkaDeliveryInfo deliveryInfo;
+    }
+
+    @Getter
+    private final String id;
+
+    @Getter
+    private final InfoType type;
+
+    @Getter
+    private final String owner;
+
+    @Getter
+    private final Parameters parameters;
+
+    public Job(String id, InfoType type, String owner, Parameters parameters) {
+        this.id = id;
+        this.type = type;
+        this.owner = owner;
+        this.parameters = parameters;
+    }
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/repository/Jobs.java b/sample-services/ics-producer-consumer/consumer/src/main/java/com/demo/consumer/repository/Jobs.java
new file mode 100644 (file)
index 0000000..eab8035
--- /dev/null
@@ -0,0 +1,95 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer.repository;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import com.demo.consumer.messages.PropertiesHelper;
+import com.demo.consumer.repository.Job.Parameters;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+@Component
+public class Jobs {
+    private static final Logger logger = LoggerFactory.getLogger(Jobs.class);
+
+    private Map<String, Job> allJobs = new HashMap<>();
+
+    public Jobs() {
+    }
+
+    public synchronized Job getJob(String id) throws Exception {
+        Job job = allJobs.get(id);
+        if (job == null) {
+            throw new Exception("Could not find job: " + id);
+        }
+        return job;
+    }
+
+    public synchronized Job get(String id) {
+        return allJobs.get(id);
+    }
+
+    public void addJob(String id, InfoType type, String owner, Parameters parameters) {
+        Job job = new Job(id, type, owner, parameters);
+        setKafkaServersEnvironment(job);
+        this.put(job);
+    }
+
+    private void setKafkaServersEnvironment(Job job) {
+        String kafkaServers = job.getParameters().getDeliveryInfo().getBootStrapServers();
+        if (kafkaServers != null && !kafkaServers.isEmpty()) {
+            PropertiesHelper.setKafkaServers(kafkaServers);
+            logger.info("Setting variable bootStrapServers: {}", kafkaServers);
+        } else {
+            logger.warn("bootStrapServers is not set for job: {}", job.getId());
+        }
+    }
+
+    private synchronized void put(Job job) {
+        logger.debug("Put job: {}", job.getId());
+        allJobs.put(job.getId(), job);
+    }
+
+    public synchronized Iterable<Job> getAll() {
+        return new Vector<>(allJobs.values());
+    }
+
+    public synchronized int size() {
+        return allJobs.size();
+    }
+
+    public synchronized Job delete(String id) {
+        return allJobs.remove(id);
+    }
+
+    @Override
+    public String toString() {
+        Gson gson = new GsonBuilder().create();
+        return gson.toJson(allJobs);
+    }
+}
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/resources/application.yaml b/sample-services/ics-producer-consumer/consumer/src/main/resources/application.yaml
new file mode 100644 (file)
index 0000000..1925f5c
--- /dev/null
@@ -0,0 +1,31 @@
+#  ========================LICENSE_START=================================
+#  Copyright (C) 2024: OpenInfra Foundation Europe
+#  ========================================================================
+#  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=================================================
+
+server:
+  port : 8081
+
+vars:
+  time: 1000
+  autostart: false
+  topic: mytopic #This topic is used only in autostart
+
+spring:
+  application:
+    name: demoConsumer
+
+logging:
+  level:
+    root: INFO
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/resources/config.properties b/sample-services/ics-producer-consumer/consumer/src/main/resources/config.properties
new file mode 100644 (file)
index 0000000..48763d6
--- /dev/null
@@ -0,0 +1,42 @@
+#  ========================LICENSE_START=================================
+#  O-RAN-SC
+#
+#  Copyright (C) 2024: OpenInfra Foundation Europe
+#  ========================================================================
+#  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=================================================
+
+# The location of the Kafka server
+bootstrap.servers=${KAFKA_SERVERS:localhost:9092}
+
+# the default group ID
+group.id=test-group
+
+# the default topic to use if one is not provided
+default.topic=magic-topic
+
+# The number of records to pull of the stream every time
+# the client takes a trip out to Kafka
+max.poll.records=10
+
+# Make Kafka keep track of record reads by the consumer
+enable.auto.commit=true
+
+# The time in milliseconds to Kafka write the offset of the last message read
+auto.commit.interval.ms=500
+
+# classes for serializing and deserializing messages
+key.deserializer=org.apache.kafka.common.serialization.StringDeserializer
+value.deserializer=org.apache.kafka.common.serialization.StringDeserializer
+
+enable.idempotence=false
diff --git a/sample-services/ics-producer-consumer/consumer/src/main/resources/logback.xml b/sample-services/ics-producer-consumer/consumer/src/main/resources/logback.xml
new file mode 100644 (file)
index 0000000..dd90b77
--- /dev/null
@@ -0,0 +1,45 @@
+<!--
+* ========================LICENSE_START=================================
+* O-RAN-SC
+*
+* Copyright (C) 2024 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===================================
+-->
+
+<configuration>
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>logging.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+            <fileNamePattern>logging.%i.log.zip</fileNamePattern>
+            <minIndex>1</minIndex>
+            <maxIndex>10</maxIndex>
+        </rollingPolicy>
+        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+            <maxFileSize>10MB</maxFileSize>
+        </triggeringPolicy>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n</pattern>
+        </encoder>
+    </appender>
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n</pattern>
+        </encoder>
+    </appender>
+    <root level="INFO">
+        <appender-ref ref="FILE"/>
+        <appender-ref ref="STDOUT"/>
+    </root>
+</configuration>
diff --git a/sample-services/ics-producer-consumer/consumer/src/test/java/com/demo/consumer/SimpleConsumerTest.java b/sample-services/ics-producer-consumer/consumer/src/test/java/com/demo/consumer/SimpleConsumerTest.java
new file mode 100644 (file)
index 0000000..7a7c279
--- /dev/null
@@ -0,0 +1,86 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.consumer;
+
+import com.demo.consumer.consumer.SimpleConsumer;
+import com.demo.consumer.messages.KafkaMessageHandler;
+import com.demo.consumer.messages.PropertiesHelper;
+
+import org.apache.kafka.clients.consumer.KafkaConsumer;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.time.Duration;
+
+import java.util.Properties;
+
+import static org.mockito.Mockito.*;
+
+class SimpleConsumerTest {
+
+    private static final long TIME_OUT_MS = 1000;
+
+    @Mock
+    private KafkaConsumer<String, String> kafkaConsumer;
+
+    @InjectMocks
+    private SimpleConsumer simpleConsumer;
+
+    private AutoCloseable closable;
+
+    @BeforeEach
+    void setUp() throws Exception {
+        closable = MockitoAnnotations.openMocks(this);
+    }
+
+    @AfterEach
+    void tearDown() throws Exception {
+        closable.close();
+    }
+
+    @Test
+    void testRun() throws Exception {
+        // Mocking the properties object returned by PropertiesHelper.getProperties()
+        Properties properties = new Properties();
+        properties.setProperty("bootstrap.servers", "localhost:9092");
+        properties.setProperty("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
+        properties.setProperty("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
+
+        // Mocking PropertiesHelper.getProperties() to return the mocked Properties object
+        try (MockedStatic<PropertiesHelper> propertiesHelperMockedStatic = Mockito.mockStatic(PropertiesHelper.class)) {
+            propertiesHelperMockedStatic.when(PropertiesHelper::getProperties).thenReturn(properties);
+
+            String topicName = "testTopic";
+            int numberOfMessages = 10;
+            KafkaMessageHandler callback = mock(KafkaMessageHandler.class);
+
+            simpleConsumer.run(topicName, numberOfMessages, callback);
+            verify(kafkaConsumer, times(0)).poll(Duration.ofMillis(TIME_OUT_MS));
+        }
+    }
+
+}
diff --git a/sample-services/ics-producer-consumer/docker-compose.yaml b/sample-services/ics-producer-consumer/docker-compose.yaml
new file mode 100644 (file)
index 0000000..5743a1a
--- /dev/null
@@ -0,0 +1,83 @@
+#  ========================LICENSE_START=================================
+#  O-RAN-SC
+#
+#  Copyright (C) 2024: OpenInfra Foundation Europe
+#  ========================================================================
+#  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=================================================
+
+version: '2'
+
+networks:
+  my-network:
+    name: kafka
+    driver: bridge
+
+services:
+  kafka-zkless:
+    container_name: kafka-zkless
+    image: quay.io/strimzi/kafka:latest-kafka-2.8.1-amd64
+    command:
+      [
+        "sh",
+        "-c",
+        "export CLUSTER_ID=$$(bin/kafka-storage.sh random-uuid) && bin/kafka-storage.sh format -t $$CLUSTER_ID -c config/kraft/server.properties && bin/kafka-server-start.sh config/kraft/server.properties --override advertised.listeners=$${KAFKA_ADVERTISED_LISTENERS} --override listener.security.protocol.map=$${KAFKA_LISTENER_SECURITY_PROTOCOL_MAP} --override listeners=$${KAFKA_LISTENERS}",
+      ]
+    ports:
+      - "9092:9092"
+    environment:
+      LOG_DIR: "/tmp/logs"
+      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
+      KAFKA_LISTENERS: PLAINTEXT://:29092,PLAINTEXT_HOST://:9092,CONTROLLER://:9093
+      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka-zkless:29092,PLAINTEXT_HOST://kafka-zkless:9092
+    tty: true
+    stdin_open: true
+    networks:
+      - my-network
+
+  informationcoordinator:
+    image: nexus3.o-ran-sc.org:10001/o-ran-sc/nonrtric-plt-informationcoordinatorservice:1.6.0
+    container_name: informationcoordinatorservice
+    ports:
+      - "8083:8083"
+    volumes:
+      - ./application.yaml:/opt/app/information-coordinator-service/config/application.yaml
+    networks:
+      - my-network
+
+  kafka-producer:
+    image: o-ran-sc/nonrtric-sample-icsproducer:latest
+    container_name: kafka-producer
+    environment:
+      - KAFKA_SERVERS=kafka-zkless:9092
+    ports:
+      - "8080:8080"
+    networks:
+      - my-network
+
+  kafka-consumer:
+    image: o-ran-sc/nonrtric-sample-icsconsumer:latest
+    container_name: kafka-consumer
+    environment:
+      - KAFKA_SERVERS=kafka-zkless:9092
+    ports:
+      - "8081:8081"
+    networks:
+      - my-network
+
+  curl-client:
+    image: curlimages/curl:latest
+    container_name: curl-client
+    command: ["tail", "-f", "/dev/null"]
+    networks:
+      - my-network
diff --git a/sample-services/ics-producer-consumer/docker-compose/.env b/sample-services/ics-producer-consumer/docker-compose/.env
new file mode 100644 (file)
index 0000000..257ac73
--- /dev/null
@@ -0,0 +1,24 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2021 Nordix Foundation. 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=================================================
+#
+
+#CONTROL_PANEL
+CONTROL_PANEL_IMAGE_BASE="nexus3.o-ran-sc.org:10002/o-ran-sc/nonrtric-controlpanel"
+CONTROL_PANEL_IMAGE_TAG="2.5.0"
+
+#NONRTRIC_GATEWAY
+NONRTRIC_GATEWAY_IMAGE_BASE="nexus3.o-ran-sc.org:10002/o-ran-sc/nonrtric-gateway"
+NONRTRIC_GATEWAY_IMAGE_TAG="1.2.0"
\ No newline at end of file
diff --git a/sample-services/ics-producer-consumer/docker-compose/LICENSE.txt b/sample-services/ics-producer-consumer/docker-compose/LICENSE.txt
new file mode 100644 (file)
index 0000000..2496663
--- /dev/null
@@ -0,0 +1,14 @@
+LICENSE.txt
+
+Unless otherwise specified, all software contained herein is licensed
+under the Apache License, Version 2.0 (the "Software License");
+you may not use this software except in compliance with the Software
+License. You may obtain a copy of the Software License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the Software License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the Software License for the specific language governing permissions
+and limitations under the Software License.
diff --git a/sample-services/ics-producer-consumer/docker-compose/README.md b/sample-services/ics-producer-consumer/docker-compose/README.md
new file mode 100644 (file)
index 0000000..d7542a8
--- /dev/null
@@ -0,0 +1,35 @@
+# License
+
+Copyright (C) 2020 Nordix Foundation.
+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.
+
+For more information about license please see the [LICENSE](LICENSE.txt) file for details.
+
+## O-RAN-SC docker-compose files
+
+The docker compose file helps the user to deploy the components of nonrtric control panel with one command.
+
+NOTE:
+docker image urls & tags are in file ```.env```
+
+To install the Control Panel and gateway, run the following command:
+
+```shell
+docker-compose --env-file .env -f docker-compose.yaml -f control-panel/docker-compose.yaml -f nonrtric-gateway/docker-compose.yaml up -d
+```
+
+To remove the containers, use the command:
+
+```shell
+docker-compose --env-file .env -f docker-compose.yaml -f control-panel/docker-compose.yaml -f nonrtric-gateway/docker-compose.yaml down
+```
diff --git a/sample-services/ics-producer-consumer/docker-compose/control-panel/config/nginx.conf b/sample-services/ics-producer-consumer/docker-compose/control-panel/config/nginx.conf
new file mode 100644 (file)
index 0000000..66e8ac4
--- /dev/null
@@ -0,0 +1,45 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2019-2022 Nordix Foundation. 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=================================================
+#
+
+
+events{}
+
+http {
+    include /etc/nginx/mime.types;
+    resolver 127.0.0.11;
+    server {
+        listen 8080;
+        server_name localhost;
+        root /usr/share/nginx/html;
+        index index.html;
+        location /a1-policy/ {
+            set $upstream nonrtric-gateway;
+            proxy_pass http://$upstream:9090;
+        }
+        location /data-producer/{
+            set $upstream nonrtric-gateway;
+            proxy_pass http://$upstream:9090;
+        }
+        location /data-consumer/{
+            set $upstream nonrtric-gateway;
+            proxy_pass http://$upstream:9090;
+        }
+        location / {
+            try_files $uri $uri/ /index.html;
+        }
+    }
+}
diff --git a/sample-services/ics-producer-consumer/docker-compose/control-panel/docker-compose.yaml b/sample-services/ics-producer-consumer/docker-compose/control-panel/docker-compose.yaml
new file mode 100644 (file)
index 0000000..a42b7a8
--- /dev/null
@@ -0,0 +1,32 @@
+#  Copyright (C) 2020 Nordix Foundation. 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=================================================
+#
+version: '3.5'
+
+networks:
+  kafka:
+    external: true
+
+services:
+  policy-control-panel:
+    image: "${CONTROL_PANEL_IMAGE_BASE}:${CONTROL_PANEL_IMAGE_TAG}"
+    container_name: policy-control-panel
+    networks:
+      - kafka
+    ports:
+      - 8181:8080
+      - 8282:8082
+    volumes:
+      - ./control-panel/config/nginx.conf:/etc/nginx/nginx.conf:ro
diff --git a/sample-services/ics-producer-consumer/docker-compose/docker-compose.yaml b/sample-services/ics-producer-consumer/docker-compose/docker-compose.yaml
new file mode 100644 (file)
index 0000000..c30aa2c
--- /dev/null
@@ -0,0 +1,20 @@
+#  Copyright (C) 2021 Nordix Foundation. 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=================================================
+#
+version: '3.5'
+
+networks:
+  kafka:
+    external: true
diff --git a/sample-services/ics-producer-consumer/docker-compose/nonrtric-gateway/config/application-nonrtricgateway.yaml b/sample-services/ics-producer-consumer/docker-compose/nonrtric-gateway/config/application-nonrtricgateway.yaml
new file mode 100644 (file)
index 0000000..c620b03
--- /dev/null
@@ -0,0 +1,48 @@
+################################################################################
+#   Copyright (c) 2021 Nordix Foundation.                                      #
+#                                                                              #
+#   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.                                             #
+################################################################################
+
+server:
+  port: 9090
+spring:
+  cloud:
+    gateway:
+      httpclient:
+        ssl:
+          useInsecureTrustManager: true
+        wiretap: true
+      httpserver:
+        wiretap: true
+      routes:
+      - id: A1-EI
+        uri: http://informationcoordinatorservice:8083
+        predicates:
+        - Path=/data-producer/**,/data-consumer/**
+management:
+  endpoint:
+    gateway:
+      enabled: true
+  endpoints:
+    web:
+      exposure:
+        include: "gateway,loggers,logfile,health,info,metrics,threaddump,heapdump"
+logging:
+  level:
+    ROOT: ERROR
+    org.springframework: ERROR
+    org.springframework.cloud.gateway: INFO
+    reactor.netty: INFO
+  file:
+    name: /var/log/nonrtric-gateway/application.log
diff --git a/sample-services/ics-producer-consumer/docker-compose/nonrtric-gateway/docker-compose.yaml b/sample-services/ics-producer-consumer/docker-compose/nonrtric-gateway/docker-compose.yaml
new file mode 100644 (file)
index 0000000..138229d
--- /dev/null
@@ -0,0 +1,33 @@
+#  Copyright (C) 2021 Nordix Foundation. 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=================================================
+#
+version: '3.5'
+
+networks:
+  kafka:
+    external: true
+
+services:
+  nonrtric-gateway:
+    image: "${NONRTRIC_GATEWAY_IMAGE_BASE}:${NONRTRIC_GATEWAY_IMAGE_TAG}"
+    container_name: nonrtric-gateway
+    networks:
+      kafka:
+        aliases:
+          - nonrtric-gateway-container
+    ports:
+      - 9090:9090
+    volumes:
+      - ./nonrtric-gateway/config/application-nonrtricgateway.yaml:/opt/app/nonrtric-gateway/config/application.yaml:ro
diff --git a/sample-services/ics-producer-consumer/docker-composeRedPanda.yaml b/sample-services/ics-producer-consumer/docker-composeRedPanda.yaml
new file mode 100644 (file)
index 0000000..0184de4
--- /dev/null
@@ -0,0 +1,38 @@
+#  ========================LICENSE_START=================================
+#  O-RAN-SC
+#
+#  Copyright (C) 2024: OpenInfra Foundation Europe
+#  ========================================================================
+#  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=================================================
+
+version: '2'
+networks:
+  kafka:
+    external: true
+
+services:
+  redpanda-console:
+    container_name: redpanda-console
+    image: docker.redpanda.com/redpandadata/console:v2.4.5
+    entrypoint: /bin/sh
+    command: -c 'echo "$$CONSOLE_CONFIG_FILE" > /tmp/config.yml; /app/console'
+    environment:
+      CONFIG_FILEPATH: /tmp/config.yml
+      CONSOLE_CONFIG_FILE: |
+        kafka:
+          brokers: ["kafka-zkless:9092"]
+    ports:
+      - 8888:8080
+    networks:
+      - kafka
diff --git a/sample-services/ics-producer-consumer/helm-chart/ics-consumer/.helmignore b/sample-services/ics-producer-consumer/helm-chart/ics-consumer/.helmignore
new file mode 100644 (file)
index 0000000..0e8a0eb
--- /dev/null
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/sample-services/ics-producer-consumer/helm-chart/ics-consumer/Chart.yaml b/sample-services/ics-producer-consumer/helm-chart/ics-consumer/Chart.yaml
new file mode 100644 (file)
index 0000000..8b972e8
--- /dev/null
@@ -0,0 +1,6 @@
+apiVersion: v2
+name: ics-consumer
+description: A Helm chart for Kubernetes
+type: application
+version: 0.1.0
+appVersion: "1.16.0"
diff --git a/sample-services/ics-producer-consumer/helm-chart/ics-consumer/templates/consumer-deployment.yaml b/sample-services/ics-producer-consumer/helm-chart/ics-consumer/templates/consumer-deployment.yaml
new file mode 100644 (file)
index 0000000..9c107fe
--- /dev/null
@@ -0,0 +1,41 @@
+#
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#
+#   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: {{ .Values.consumer.name }}
+spec:
+  replicas: {{ .Values.consumer.replicaCount }}
+  selector:
+    matchLabels:
+      app: {{ .Values.consumer.name }}
+  template:
+    metadata:
+      labels:
+        app: {{ .Values.consumer.name }}
+    spec:
+      containers:
+      - name: {{ .Values.consumer.name }}
+        image: "{{ .Values.consumer.image.repository }}:{{ .Values.consumer.image.tag }}"
+        ports:
+        - containerPort: {{ .Values.consumer.service.port }}
+        env:
+        - name: KAFKA_SERVERS
+          value: "{{ .Values.kafka.host }}:{{ .Values.kafka.port }}"
diff --git a/sample-services/ics-producer-consumer/helm-chart/ics-consumer/templates/consumer-service.yaml b/sample-services/ics-producer-consumer/helm-chart/ics-consumer/templates/consumer-service.yaml
new file mode 100644 (file)
index 0000000..6b33838
--- /dev/null
@@ -0,0 +1,31 @@
+#
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#
+#   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: {{ .Values.consumer.name }}
+spec:
+  type: NodePort
+  ports:
+    - port: {{ .Values.consumer.service.port }}
+      targetPort: {{ .Values.consumer.service.port }}
+      nodePort: {{ .Values.consumer.service.nodePort }}
+  selector:
+    app: {{ .Values.consumer.name }}
diff --git a/sample-services/ics-producer-consumer/helm-chart/ics-consumer/values.yaml b/sample-services/ics-producer-consumer/helm-chart/ics-consumer/values.yaml
new file mode 100644 (file)
index 0000000..5e6c5b0
--- /dev/null
@@ -0,0 +1,32 @@
+#
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#
+#   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===================================
+#
+consumer:
+  name: kafka-consumer
+  replicaCount: 1
+  image:
+    repository: nexus3.o-ran-sc.org:10004/o-ran-sc/nonrtric-sample-icsconsumer
+    tag: 0.0.1
+  service:
+    port: 8081
+    nodePort: 30081
+
+kafka:
+  host: kafka-service
+  port: 9092
diff --git a/sample-services/ics-producer-consumer/helm-chart/ics-producer/.helmignore b/sample-services/ics-producer-consumer/helm-chart/ics-producer/.helmignore
new file mode 100644 (file)
index 0000000..0e8a0eb
--- /dev/null
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/sample-services/ics-producer-consumer/helm-chart/ics-producer/Chart.yaml b/sample-services/ics-producer-consumer/helm-chart/ics-producer/Chart.yaml
new file mode 100644 (file)
index 0000000..e26165b
--- /dev/null
@@ -0,0 +1,6 @@
+apiVersion: v2
+name: ics-producer
+description: A Helm chart for Kubernetes
+type: application
+version: 0.1.0
+appVersion: "1.16.0"
diff --git a/sample-services/ics-producer-consumer/helm-chart/ics-producer/templates/producer-deployment.yaml b/sample-services/ics-producer-consumer/helm-chart/ics-producer/templates/producer-deployment.yaml
new file mode 100644 (file)
index 0000000..b7433fc
--- /dev/null
@@ -0,0 +1,41 @@
+#
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#
+#   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: {{ .Values.producer.name }}
+spec:
+  replicas: {{ .Values.producer.replicaCount }}
+  selector:
+    matchLabels:
+      app: {{ .Values.producer.name }}
+  template:
+    metadata:
+      labels:
+        app: {{ .Values.producer.name }}
+    spec:
+      containers:
+      - name: {{ .Values.producer.name }}
+        image: "{{ .Values.producer.image.repository }}:{{ .Values.producer.image.tag }}"
+        ports:
+        - containerPort: {{ .Values.producer.service.port }}
+        env:
+        - name: KAFKA_SERVERS
+          value: "{{ .Values.kafka.host }}:{{ .Values.kafka.port }}"
diff --git a/sample-services/ics-producer-consumer/helm-chart/ics-producer/templates/producer-service.yaml b/sample-services/ics-producer-consumer/helm-chart/ics-producer/templates/producer-service.yaml
new file mode 100644 (file)
index 0000000..8e17906
--- /dev/null
@@ -0,0 +1,31 @@
+#
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#
+#   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: {{ .Values.producer.name }}
+spec:
+  type: NodePort
+  ports:
+    - port: {{ .Values.producer.service.port }}
+      targetPort: {{ .Values.producer.service.port }}
+      nodePort: {{ .Values.producer.service.nodePort }}
+  selector:
+    app: {{ .Values.producer.name }}
diff --git a/sample-services/ics-producer-consumer/helm-chart/ics-producer/values.yaml b/sample-services/ics-producer-consumer/helm-chart/ics-producer/values.yaml
new file mode 100644 (file)
index 0000000..9a71198
--- /dev/null
@@ -0,0 +1,32 @@
+#
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#
+#   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===================================
+#
+producer:
+  name: kafka-producer
+  replicaCount: 1
+  image:
+    repository: nexus3.o-ran-sc.org:10004/o-ran-sc/nonrtric-sample-icsproducer
+    tag: 0.0.1
+  service:
+    port: 8080
+    nodePort: 30080
+
+kafka:
+  host: kafka-service
+  port: 9092
diff --git a/sample-services/ics-producer-consumer/producer/Dockerfile b/sample-services/ics-producer-consumer/producer/Dockerfile
new file mode 100644 (file)
index 0000000..148872a
--- /dev/null
@@ -0,0 +1,49 @@
+#==================================================================================
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#
+#   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.
+#
+#   This source code is part of the near-RT RIC (RAN Intelligent Controller)
+#   platform project (RICP).
+#==================================================================================
+
+# Use Maven image with OpenJDK 17 for the build stage
+FROM maven:3.8.5-openjdk-17 AS maven_build
+
+# Copy Maven project files
+COPY pom.xml /tmp/
+COPY src /tmp/src/
+
+# Set working directory
+WORKDIR /tmp/
+
+# Build the Maven project
+RUN mvn package
+
+# Use a separate image with OpenJDK 17 for the runtime stage
+FROM openjdk:17-jdk-slim
+
+# Expose port 8080
+EXPOSE 8080
+
+ARG KAFKA_SERVERS
+ENV KAFKA_SERVERS=${KAFKA_SERVERS}
+
+# Set the working directory
+WORKDIR /app
+
+# Copy the JAR file from the maven_build stage to the runtime stage
+COPY --from=maven_build /tmp/target/producer-0.0.1.jar /app/producer-0.0.1.jar
+
+# Command to run the application
+CMD ["java", "-jar", "producer-0.0.1.jar"]
diff --git a/sample-services/ics-producer-consumer/producer/Makefile b/sample-services/ics-producer-consumer/producer/Makefile
new file mode 100644 (file)
index 0000000..301526a
--- /dev/null
@@ -0,0 +1,51 @@
+#  ========================LICENSE_START=================================
+#  O-RAN-SC
+#
+#  Copyright (C) 2024: OpenInfra Foundation Europe
+#  ========================================================================
+#  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=================================================
+
+# Define variables
+IMAGE_NAME = "o-ran-sc/nonrtric-sample-icsproducer"
+DOCKERFILE = Dockerfile
+
+# Default target
+.PHONY: all
+all: build run
+
+# Target to build the Maven JAR
+.PHONY: jar
+jar:
+       mvn clean package
+
+# Target to build the Docker image
+.PHONY: build
+build:
+       docker build -t $(IMAGE_NAME) -f $(DOCKERFILE) .
+
+# Target to run the Docker container
+.PHONY: run
+run:
+       docker run -p 8080:8080 $(IMAGE_NAME)
+
+# Target to stop and remove the Docker container
+.PHONY: stop
+stop:
+       docker stop $(IMAGE_NAME) || true
+       docker rm $(IMAGE_NAME) || true
+
+# Target to clean up
+.PHONY: clean
+clean: stop
+       docker rmi $(IMAGE_NAME) || true
diff --git a/sample-services/ics-producer-consumer/producer/container-tag.yaml b/sample-services/ics-producer-consumer/producer/container-tag.yaml
new file mode 100644 (file)
index 0000000..6423243
--- /dev/null
@@ -0,0 +1,23 @@
+#  ========================LICENSE_START=================================
+#  O-RAN-SC
+#
+#  Copyright (C) 2024: OpenInfra Foundation Europe
+#  ========================================================================
+#  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=================================================
+
+# The Jenkins job requires a tag to build the Docker image.
+# By default this file is in the docker build directory,
+# but the location can configured in the JJB template.
+---
+tag: 0.0.1
\ No newline at end of file
diff --git a/sample-services/ics-producer-consumer/producer/pom.xml b/sample-services/ics-producer-consumer/producer/pom.xml
new file mode 100644 (file)
index 0000000..d78f370
--- /dev/null
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+* ========================LICENSE_START=================================
+* O-RAN-SC
+*
+* Copyright (C) 2024 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===================================
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>3.2.3</version>
+        <relativePath/>
+    </parent>
+
+    <groupId>com.demo.producer</groupId>
+    <artifactId>producer</artifactId>
+    <version>0.0.1</version>
+    <packaging>jar</packaging>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients -->
+        <dependency>
+            <groupId>org.apache.kafka</groupId>
+            <artifactId>kafka-clients</artifactId>
+            <version>3.7.0</version>
+            <!--<scope>provided</scope> -->
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+           <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.18.24</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.10.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.googlecode.json-simple</groupId>
+            <artifactId>json-simple</artifactId>
+            <version>1.1.1</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <mainClass>com.demo.producer.Application</mainClass>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/Application.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/Application.java
new file mode 100644 (file)
index 0000000..fc389f4
--- /dev/null
@@ -0,0 +1,56 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+import com.demo.producer.messages.KafkaMessageHandlerImpl;
+import com.demo.producer.producer.SimpleProducer;
+
+@SpringBootApplication
+@EnableAsync
+public class Application {
+
+    @Autowired
+    private SimpleProducer simpleProducer;
+
+    @Value("${vars.autostart:false}")
+    private boolean autostart;
+
+    @Value("${vars.topic}")
+    private String topic;
+    public static void main(String[] args) throws Exception {
+        SpringApplication.run(Application.class, args);
+    }
+
+    @EventListener(ApplicationReadyEvent.class)
+    public void checkAutoRun() throws Exception{
+        if (autostart) {
+            simpleProducer.runAlways(topic, new KafkaMessageHandlerImpl());
+        }
+    }
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/controllers/ProducerController.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/controllers/ProducerController.java
new file mode 100644 (file)
index 0000000..bbf91b9
--- /dev/null
@@ -0,0 +1,134 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.controllers;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.demo.producer.repository.InfoType;
+import com.demo.producer.repository.InfoTypes;
+import com.demo.producer.repository.Job.Parameters;
+import com.demo.producer.repository.Jobs;
+import com.demo.producer.dme.ProducerJobInfo;
+import com.demo.producer.messages.KafkaMessageHandlerImpl;
+import com.demo.producer.producer.SimpleProducer;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+@RestController
+@RequestMapping(path = "/producer", produces = "application/json")
+public class ProducerController {
+    private static final Logger log = LoggerFactory.getLogger(ProducerController.class);
+    private static Gson gson = new GsonBuilder().create();
+    private final Jobs jobs;
+    private final InfoTypes types;
+    private String topicName = "mytopic";
+
+    public ProducerController(@Autowired Jobs jobs, @Autowired InfoTypes types) {
+        this.jobs = jobs;
+        this.types = types;
+        InfoType type1 = InfoType.builder().build();
+        type1.setId("type1");
+        type1.setKafkaInputTopic(topicName);
+        type1.setInputJobType("type1");
+        type1.setInputJobDefinition(null);
+        types.put(type1);
+    }
+
+    @GetMapping("/publish/{numberOfMessages}")
+    public ResponseEntity<?> publishMessage(@PathVariable int numberOfMessages) {
+        try {
+            new SimpleProducer().run(topicName, numberOfMessages, new KafkaMessageHandlerImpl());
+            return ResponseEntity.ok("message published successfully ..");
+        } catch (Exception ex) {
+            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+                    .build();
+        }
+    }
+
+    @PostMapping("/job/{infoJobId}")
+    public void jobCallback(@RequestBody String requestBody, @PathVariable String infoJobId) {
+        ProducerJobInfo request = gson.fromJson(requestBody, ProducerJobInfo.class);
+        try {
+            log.info("Adding producer job info " + request.toString());
+            this.jobs.addJob(request.id, types.getType(request.typeId), request.owner,
+                    toJobParameters(request.jobData));
+        } catch (Exception e) {
+            log.error("Error adding producer job info: " + request.toString(), e.getMessage());
+        }
+    }
+
+    @PostMapping("/job")
+    public void jobCallbackNoId(@RequestBody String requestBody) {
+        ProducerJobInfo request = gson.fromJson(requestBody, ProducerJobInfo.class);
+        try {
+            log.info("Adding producer job info "+request.toString());
+            this.jobs.addJob(request.id, types.getType(request.typeId), request.owner,
+                    toJobParameters(request.jobData));
+        } catch (Exception e) {
+            log.error("Error adding producer job info: " + request.toString(), e.getMessage());
+        }
+    }
+
+    private Parameters toJobParameters(Object jobData) {
+        String json = gson.toJson(jobData);
+        return gson.fromJson(json, Parameters.class);
+    }
+
+    @GetMapping("/job")
+    public ResponseEntity<String> getJobs() {
+        try {
+            log.info("Get all jobs");
+            return new ResponseEntity<>(this.jobs.getAll().toString(), HttpStatus.OK);
+        } catch (Exception e) {
+            log.error("Error finding jobs", e.getMessage());
+            return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    @DeleteMapping("/job/{infoJobId}")
+    public ResponseEntity<String> deleteJob(@PathVariable String infoJobId) {
+        try {
+            log.info("Delete Job" + infoJobId);
+            this.jobs.delete(infoJobId);
+            return new ResponseEntity<>("Deleted job:" + infoJobId, HttpStatus.OK);
+        } catch (Exception e) {
+            log.error("Error finding job " + infoJobId, e.getMessage());
+            return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    @GetMapping("/supervision")
+    public ResponseEntity<String> getSupervision() {
+        log.info("Get Supervision");
+        return new ResponseEntity<>("Ok", HttpStatus.OK);
+    }
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/controllers/ThreadsController.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/controllers/ThreadsController.java
new file mode 100644 (file)
index 0000000..e503b84
--- /dev/null
@@ -0,0 +1,93 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.controllers;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+import com.demo.producer.messages.KafkaMessageHandlerImpl;
+import com.demo.producer.messages.ApplicationMessageHandlerImpl;
+import com.demo.producer.producer.SimpleProducer;
+
+@RestController
+public class ThreadsController {
+    private static final Logger log = LoggerFactory.getLogger(ThreadsController.class);
+
+    @Autowired
+    private SimpleProducer simpleProducer;
+
+    private Thread producerThread;
+
+    @Async
+    @GetMapping("/startProducer/{topicName}")
+    public CompletableFuture<String> startProducer(@PathVariable("topicName") String topicName) {
+        try {
+            producerThread = new Thread(() -> {
+                try {
+                    simpleProducer.runAlways(topicName, new ApplicationMessageHandlerImpl());
+                } catch (Exception e) {
+                    log.error("Error starting producer on: " + topicName, e.getMessage());
+                }
+            });
+            producerThread.start();
+            return CompletableFuture.completedFuture("Producer started for topic: " + topicName);
+        } catch (Exception e) {
+            return CompletableFuture.failedFuture(e);
+        }
+    }
+
+    @GetMapping("/stopProducer")
+    public String stopProducer() {
+        if (producerThread != null && producerThread.isAlive()) {
+            try {
+                simpleProducer.shutdown();
+            } catch (Exception e) {
+                log.error("Error stopping producer Thread", e.getMessage());
+            }
+            return "Producer stopped successfully";
+        } else {
+            return "No active producer to stop";
+        }
+    }
+
+    @GetMapping("/publish/{numberOfMessages}/on/{topicName}")
+    public CompletableFuture<String> publishNMessage(@PathVariable int numberOfMessages, @PathVariable String topicName) {
+        try {
+            producerThread = new Thread(() -> {
+                try {
+                    simpleProducer.run(topicName, numberOfMessages, new KafkaMessageHandlerImpl());
+                } catch (Exception e) {
+                    log.error("Error producing " + numberOfMessages + "on " + topicName, e.getMessage());
+                }
+            });
+            producerThread.start();
+            return CompletableFuture.completedFuture("Producer started for topic: " + topicName);
+        } catch (Exception e) {
+            return CompletableFuture.failedFuture(e);
+        }
+    }
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/dme/ProducerInfoTypeInfo.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/dme/ProducerInfoTypeInfo.java
new file mode 100644 (file)
index 0000000..5f87f4d
--- /dev/null
@@ -0,0 +1,41 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.dme;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@AllArgsConstructor
+public class ProducerInfoTypeInfo {
+
+    @SerializedName("info_job_data_schema")
+    @JsonProperty(value = "info_job_data_schema", required = true)
+    public Object jobDataSchema;
+
+    @SerializedName("info_type_information")
+    @JsonProperty(value = "info_type_information", required = true)
+    public Object typeSpecificInformation;
+
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/dme/ProducerJobInfo.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/dme/ProducerJobInfo.java
new file mode 100644 (file)
index 0000000..c55d4c5
--- /dev/null
@@ -0,0 +1,53 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.dme;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@AllArgsConstructor
+public class ProducerJobInfo {
+
+    @SerializedName("info_job_identity")
+    @JsonProperty("info_job_identity")
+    public String id = "";
+
+    @SerializedName("info_type_identity")
+    @JsonProperty("info_type_identity")
+    public String typeId = "";
+
+    @SerializedName("info_job_data")
+    @JsonProperty("info_job_data")
+    public Object jobData;
+
+    @SerializedName("owner")
+    @JsonProperty("owner")
+    public String owner = "";
+
+    @SerializedName("last_updated")
+    @JsonProperty("last_updated")
+    public String lastUpdated = "";
+
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/dme/ProducerRegistrationInfo.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/dme/ProducerRegistrationInfo.java
new file mode 100644 (file)
index 0000000..5f279d2
--- /dev/null
@@ -0,0 +1,47 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.dme;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+
+import java.util.Collection;
+
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@AllArgsConstructor
+public class ProducerRegistrationInfo {
+
+    @SerializedName("supported_info_types")
+    @JsonProperty(value = "supported_info_types", required = true)
+    public Collection<String> supportedTypeIds;
+
+    @SerializedName("info_job_callback_url")
+    @JsonProperty(value = "info_job_callback_url", required = true)
+    public String jobCallbackUrl;
+
+    @SerializedName("info_producer_supervision_callback_url")
+    @JsonProperty(value = "info_producer_supervision_callback_url", required = true)
+    public String producerSupervisionCallbackUrl;
+
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/AbstractSimpleKafka.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/AbstractSimpleKafka.java
new file mode 100644 (file)
index 0000000..d00d074
--- /dev/null
@@ -0,0 +1,43 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.messages;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public abstract class AbstractSimpleKafka {
+    private static final Logger log = LoggerFactory.getLogger(AbstractSimpleKafka.class);
+
+    public AbstractSimpleKafka(){
+        Runtime.getRuntime().addShutdownHook(new Thread() {
+            @Override
+            public void run() {
+                    shutdown();
+            }
+        });
+        log.info(MessageHelper.getSimpleJSONObject("Created the Shutdown Hook").toJSONString());
+    }
+
+    public abstract void shutdown();
+    public abstract void runAlways(String topicName, KafkaMessageHandler callback) throws Exception;
+    public abstract void run(String topicName, int numberOfMessages, KafkaMessageHandler callback) throws Exception;
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/ApplicationMessageHandlerImpl.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/ApplicationMessageHandlerImpl.java
new file mode 100644 (file)
index 0000000..beae794
--- /dev/null
@@ -0,0 +1,39 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.messages;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.json.simple.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ApplicationMessageHandlerImpl implements KafkaMessageHandler {
+
+    private static final Logger log = LoggerFactory.getLogger(ApplicationMessageHandlerImpl.class);
+
+    @Override
+    public void processMessage(String topicName, ConsumerRecord<String, String> message) throws Exception {
+        String source = KafkaMessageHandlerImpl.class.getName();
+        JSONObject obj = MessageHelper.getMessageLogEntryJSON(source, topicName, message.key(), message.value());
+        System.out.println(obj.toJSONString());
+        log.info(obj.toJSONString());
+    }
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/KafkaMessageHandler.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/KafkaMessageHandler.java
new file mode 100644 (file)
index 0000000..814c88c
--- /dev/null
@@ -0,0 +1,28 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.messages;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+
+@FunctionalInterface
+public interface KafkaMessageHandler {
+    void processMessage(String topicName, ConsumerRecord<String, String> message) throws Exception;
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/KafkaMessageHandlerImpl.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/KafkaMessageHandlerImpl.java
new file mode 100644 (file)
index 0000000..06f7026
--- /dev/null
@@ -0,0 +1,37 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.messages;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.json.simple.JSONObject;
+
+public class KafkaMessageHandlerImpl implements KafkaMessageHandler {
+    private static final Logger log = LoggerFactory.getLogger(KafkaMessageHandlerImpl.class);
+
+    @Override
+    public void processMessage(String topicName, ConsumerRecord<String, String> message) throws Exception {
+        String source = KafkaMessageHandlerImpl.class.getName();
+        JSONObject obj = MessageHelper.getMessageLogEntryJSON(source, topicName, message.key(), message.value());
+        log.info(obj.toJSONString());
+    }
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/MessageHelper.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/MessageHelper.java
new file mode 100644 (file)
index 0000000..7a5e45b
--- /dev/null
@@ -0,0 +1,71 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.messages;
+
+import java.util.Properties;
+import java.util.Random;
+import org.json.simple.JSONObject;
+
+public class MessageHelper {
+
+    private static Properties props;
+
+    public static String getRandomString() {
+        int leftLimit = 48; // numeral '0'
+        int rightLimit = 122; // letter 'z'
+        int targetStringLength = 10;
+        Random random = new Random();
+
+        return random.ints(leftLimit, rightLimit + 1).filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97))
+                .limit(targetStringLength)
+                .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
+    }
+
+    @SuppressWarnings("unchecked") // Using only strings
+    public static JSONObject getMessageLogEntryJSON(String source, String topic, String key, String message)
+            throws Exception {
+        JSONObject obj = new JSONObject();
+        String bootstrapServers = getProperties().getProperty("bootstrap.servers");
+        obj.put("bootstrapServers", bootstrapServers);
+        obj.put("source", source);
+        obj.put("topic", topic);
+        obj.put("key", key);
+        obj.put("message", message);
+
+        return obj;
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public static JSONObject getSimpleJSONObject(String message){
+        JSONObject obj = new JSONObject();
+        obj.put("message", message);
+        return obj;
+    }
+
+    protected static Properties getProperties() throws Exception {
+        if (props == null) {
+            props = PropertiesHelper.getProperties();
+        }
+        return props;
+    }
+
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/PropertiesHelper.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/messages/PropertiesHelper.java
new file mode 100644 (file)
index 0000000..d7d9f98
--- /dev/null
@@ -0,0 +1,73 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.messages;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import com.demo.producer.producer.SimpleProducer;
+
+@Component
+public class PropertiesHelper {
+    private static final Logger log = LoggerFactory.getLogger(PropertiesHelper.class);
+    private static String kafkaServers = null;
+
+    public static Properties getProperties() throws Exception {
+        Properties props = new Properties();
+        try (InputStream input = SimpleProducer.class.getClassLoader().getResourceAsStream("config.properties")) {
+            if (input == null) {
+                log.error("Failed to load configuration file 'config.properties'");
+                throw new IOException("Configuration file 'config.properties' not found");
+            }
+            props.load(input);
+            setBootstrapServers(props);
+        } catch (IOException e) {
+            log.error("Error reading configuration file: ", e);
+            throw e;
+        }
+        return props;
+    }
+
+    private static void setBootstrapServers(Properties props) {
+        if (kafkaServers != null && !kafkaServers.isEmpty()) {
+            props.setProperty("bootstrap.servers", kafkaServers);
+            log.info("Using actively bootstrap servers: {}", kafkaServers);
+        } else {
+            String kafkaServersEnv = System.getenv("KAFKA_SERVERS");
+            if (kafkaServersEnv != null && !kafkaServersEnv.isEmpty()) {
+                kafkaServers = kafkaServersEnv;
+                props.setProperty("bootstrap.servers", kafkaServers);
+                log.info("Using environment variable KAFKA_SERVERS: {}", kafkaServers);
+            } else {
+                log.info("Environment variable KAFKA_SERVERS not found, defaulting to config file");
+            }
+        }
+    }
+
+    public static void setKafkaServers(String servers) {
+        kafkaServers = servers;
+    }
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/producer/SimpleProducer.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/producer/SimpleProducer.java
new file mode 100644 (file)
index 0000000..6c9858b
--- /dev/null
@@ -0,0 +1,112 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+package com.demo.producer.producer;
+
+import java.util.UUID;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.json.simple.JSONObject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import com.demo.producer.messages.AbstractSimpleKafka;
+import com.demo.producer.messages.KafkaMessageHandler;
+import com.demo.producer.messages.MessageHelper;
+import com.demo.producer.messages.PropertiesHelper;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Component
+@Getter
+@Setter
+public class SimpleProducer extends AbstractSimpleKafka {
+    private static final Logger log = LoggerFactory.getLogger(SimpleProducer.class);
+
+    @Value("${vars.time:1000}")
+    private int TIME;
+
+    private KafkaProducer<String, String> kafkaProducer;
+    private final AtomicBoolean closed = new AtomicBoolean(false);
+
+    public void run(String topicName, int numberOfMessages, KafkaMessageHandler callback) throws Exception {
+        for (int i = 0; i < numberOfMessages; i++) {
+            String key = UUID.randomUUID().toString();
+            String message = MessageHelper.getRandomString();
+            if (this.getTopicName() == null) {
+                this.setTopicName(topicName);
+            }
+            this.send(topicName, key, message);
+            Thread.sleep(TIME);
+        }
+        this.shutdown();
+    }
+
+    public void runAlways(String topicName, KafkaMessageHandler callback) throws Exception {
+        while (true) {
+            String key = UUID.randomUUID().toString();
+            String message = MessageHelper.getRandomString();
+            this.send(topicName, key, message);
+            Thread.sleep(TIME);
+        }
+    }
+
+    private String topicName = null;
+
+    private void setTopicName(String topicName) {
+        this.topicName = topicName;
+    }
+
+    private String getTopicName() {
+        return this.topicName;
+    }
+
+    protected void send(String topicName, String key, String message) throws Exception {
+        String source = SimpleProducer.class.getName();
+        ProducerRecord<String, String> producerRecord = new ProducerRecord<>(topicName, key, message);
+        JSONObject obj = MessageHelper.getMessageLogEntryJSON(source, topicName, key, message);
+        log.info(obj.toJSONString());
+        getKafkaProducer().send(producerRecord);
+    }
+
+    private KafkaProducer<String, String> getKafkaProducer() throws Exception {
+        if (this.kafkaProducer == null) {
+            Properties props = PropertiesHelper.getProperties();
+            this.kafkaProducer = new KafkaProducer<>(props);
+        }
+        return this.kafkaProducer;
+    }
+
+    public void shutdown(){
+        closed.set(true);
+        try {
+            log.info(MessageHelper.getSimpleJSONObject("Shutting down producer").toJSONString());
+            getKafkaProducer().close();
+        } catch (Exception e) {
+            log.error("Error shutting down the Producer ", e.getMessage());
+        }
+
+    }
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/repository/InfoType.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/repository/InfoType.java
new file mode 100644 (file)
index 0000000..75030d8
--- /dev/null
@@ -0,0 +1,48 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.repository;
+
+import lombok.AccessLevel;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+@ToString
+@Builder(access = AccessLevel.PUBLIC)
+public class InfoType {
+
+    @Getter
+    @Setter
+    private String id;
+
+    @Getter
+    @Setter
+    private String kafkaInputTopic;
+
+    @Getter
+    @Setter
+    private String inputJobType;
+
+    @Getter
+    @Setter
+    private Object inputJobDefinition;
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/repository/InfoTypes.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/repository/InfoTypes.java
new file mode 100644 (file)
index 0000000..b7a9914
--- /dev/null
@@ -0,0 +1,81 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.repository;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+
+@Component
+public class InfoTypes {
+    private static final Logger logger = LoggerFactory.getLogger(InfoTypes.class);
+
+    private Map<String, InfoType> allTypes = new HashMap<>();
+
+    public InfoTypes(Collection<InfoType> types) {
+        for (InfoType type : types) {
+            put(type);
+        }
+    }
+
+    public synchronized InfoType get(String id) {
+        return allTypes.get(id);
+    }
+
+    public synchronized InfoType getType(String id) throws Exception {
+        InfoType type = allTypes.get(id);
+        if (type == null) {
+            throw new Exception("Could not find type: " + id + HttpStatus.NOT_FOUND.toString());
+        }
+        return type;
+    }
+
+    public static class ConfigFile {
+        Collection<InfoType> types;
+    }
+
+    public synchronized void put(InfoType type) {
+        logger.debug("Put type: {}", type.getId());
+        allTypes.put(type.getId(), type);
+    }
+
+    public synchronized Iterable<InfoType> getAll() {
+        return new Vector<>(allTypes.values());
+    }
+
+    public synchronized Collection<String> typeIds() {
+        return allTypes.keySet();
+    }
+
+    public synchronized int size() {
+        return allTypes.size();
+    }
+
+    public synchronized void clear() {
+        allTypes.clear();
+    }
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/repository/Job.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/repository/Job.java
new file mode 100644 (file)
index 0000000..cafddde
--- /dev/null
@@ -0,0 +1,71 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.repository;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.ToString;
+
+@ToString
+public class Job {
+    @Builder
+    public static class Parameters {
+
+        @Builder
+        @EqualsAndHashCode
+        public static class KafkaDeliveryInfo {
+            @Getter
+            private String topic;
+
+            @Getter
+            private String bootStrapServers;
+
+            @JsonProperty(value = "numberOfMessages")
+            @Getter
+            private int numberOfMessages;
+        }
+
+        @Getter
+        private KafkaDeliveryInfo deliveryInfo;
+    }
+
+    @Getter
+    private final String id;
+
+    @Getter
+    private final InfoType type;
+
+    @Getter
+    private final String owner;
+
+    @Getter
+    private final Parameters parameters;
+
+    public Job(String id, InfoType type, String owner, Parameters parameters) {
+        this.id = id;
+        this.type = type;
+        this.owner = owner;
+        this.parameters = parameters;
+    }
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/repository/Jobs.java b/sample-services/ics-producer-consumer/producer/src/main/java/com/demo/producer/repository/Jobs.java
new file mode 100644 (file)
index 0000000..e929e44
--- /dev/null
@@ -0,0 +1,95 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer.repository;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import com.demo.producer.messages.PropertiesHelper;
+import com.demo.producer.repository.Job.Parameters;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+@Component
+public class Jobs {
+    private static final Logger logger = LoggerFactory.getLogger(Jobs.class);
+
+    private Map<String, Job> allJobs = new HashMap<>();
+
+    public Jobs() {
+    }
+
+    public synchronized Job getJob(String id) throws Exception {
+        Job job = allJobs.get(id);
+        if (job == null) {
+            throw new Exception("Could not find job: " + id);
+        }
+        return job;
+    }
+
+    public synchronized Job get(String id) {
+        return allJobs.get(id);
+    }
+
+    public void addJob(String id, InfoType type, String owner, Parameters parameters) {
+        Job job = new Job(id, type, owner, parameters);
+        setKafkaServersEnvironment(job);
+        this.put(job);
+    }
+
+    private void setKafkaServersEnvironment(Job job) {
+        String kafkaServers = job.getParameters().getDeliveryInfo().getBootStrapServers();
+        if (kafkaServers != null && !kafkaServers.isEmpty()) {
+            PropertiesHelper.setKafkaServers(kafkaServers);
+            logger.info("Setting variable bootStrapServers: {}", kafkaServers);
+        } else {
+            logger.warn("bootStrapServers is not set for job: {}", job.getId());
+        }
+    }
+
+    private synchronized void put(Job job) {
+        logger.debug("Put job: {}", job.getId());
+        allJobs.put(job.getId(), job);
+    }
+
+    public synchronized Iterable<Job> getAll() {
+        return new Vector<>(allJobs.values());
+    }
+
+    public synchronized int size() {
+        return allJobs.size();
+    }
+
+    public synchronized Job delete(String id) {
+        return allJobs.remove(id);
+    }
+
+    @Override
+    public String toString() {
+        Gson gson = new GsonBuilder().create();
+        return gson.toJson(allJobs);
+    }
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/main/resources/application.yaml b/sample-services/ics-producer-consumer/producer/src/main/resources/application.yaml
new file mode 100644 (file)
index 0000000..28ae26c
--- /dev/null
@@ -0,0 +1,28 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2024: OpenInfra Foundation Europe
+#  ========================================================================
+#  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=================================================
+#
+vars:
+  time: 1000
+  autostart: false
+  topic: mytopic #This topic is used only in autostart
+
+spring:
+  application:
+    name: demoProducer
+
+logging:
+  level:
+    root: INFO
\ No newline at end of file
diff --git a/sample-services/ics-producer-consumer/producer/src/main/resources/config.properties b/sample-services/ics-producer-consumer/producer/src/main/resources/config.properties
new file mode 100644 (file)
index 0000000..83e5539
--- /dev/null
@@ -0,0 +1,44 @@
+#  ========================LICENSE_START=================================
+#  O-RAN-SC
+#
+#  Copyright (C) 2024: OpenInfra Foundation Europe
+#  ========================================================================
+#  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=================================================
+
+# The location of the Kafka server
+bootstrap.servers=${KAFKA_SERVERS:localhost:9092}
+
+# the default group ID
+group.id=test-group
+
+# the default topic to use if one is not provided
+default.topic=magic-topic
+
+# The number of records to pull of the stream every time
+# the client takes a trip out to Kafka
+max.poll.records=10
+
+# Make Kafka keep track of record reads by the consumer
+enable.auto.commit=true
+
+# The time in milliseconds to Kafka write the offset of the last message read
+auto.commit.interval.ms=500
+
+# classes for serializing and deserializing messages
+key.serializer=org.apache.kafka.common.serialization.StringSerializer
+value.serializer=org.apache.kafka.common.serialization.StringSerializer
+key.deserializer=org.apache.kafka.common.serialization.StringDeserializer
+value.deserializer=org.apache.kafka.common.serialization.StringDeserializer
+
+enable.idempotence=false
diff --git a/sample-services/ics-producer-consumer/producer/src/main/resources/logback.xml b/sample-services/ics-producer-consumer/producer/src/main/resources/logback.xml
new file mode 100644 (file)
index 0000000..3dbfe39
--- /dev/null
@@ -0,0 +1,44 @@
+<!--
+* ========================LICENSE_START=================================
+* O-RAN-SC
+*
+* Copyright (C) 2024 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===================================
+-->
+<configuration>
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>logging.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+            <fileNamePattern>logging.%i.log.zip</fileNamePattern>
+            <minIndex>1</minIndex>
+            <maxIndex>10</maxIndex>
+        </rollingPolicy>
+        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+            <maxFileSize>10MB</maxFileSize>
+        </triggeringPolicy>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n</pattern>
+        </encoder>
+    </appender>
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n</pattern>
+        </encoder>
+    </appender>
+    <root level="INFO">
+        <appender-ref ref="FILE"/>
+        <appender-ref ref="STDOUT"/>
+    </root>
+</configuration>
diff --git a/sample-services/ics-producer-consumer/producer/src/test/java/com/demo/producer/SimpleProducerTest.java b/sample-services/ics-producer-consumer/producer/src/test/java/com/demo/producer/SimpleProducerTest.java
new file mode 100644 (file)
index 0000000..da77873
--- /dev/null
@@ -0,0 +1,105 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer;
+
+import com.demo.producer.producer.SimpleProducer;
+import org.apache.kafka.clients.producer.KafkaProducer;
+
+import com.demo.producer.messages.KafkaMessageHandler;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+class SimpleProducerTest {
+
+    private final int wait = 1000;
+    private final String topicName = "testTopic";
+
+    @Mock
+    private KafkaProducer<String, String> kafkaProducer;
+
+    @InjectMocks
+    @Autowired
+    private SimpleProducer simpleProducer;
+
+    private AutoCloseable closable;
+
+    @BeforeEach
+    void setUp() {
+        closable = MockitoAnnotations.openMocks(this);
+    }
+
+    @AfterEach
+    public void close() throws Exception {
+        closable.close();
+    }
+
+    @Test
+    @SuppressWarnings("unchecked") //sending only Strings
+    void testRun() throws Exception {
+        int numberOfMessages = 10;
+        KafkaMessageHandler callback = mock(KafkaMessageHandler.class);
+
+        simpleProducer.run(topicName, numberOfMessages, callback);
+
+        verify(kafkaProducer, times(numberOfMessages)).send(any(ProducerRecord.class));
+        verify(kafkaProducer, times(1)).close();
+    }
+
+    @Test
+    @SuppressWarnings("unchecked") //sending only Strings
+    void testRunAlways() throws Exception {
+        KafkaMessageHandler callback = mock(KafkaMessageHandler.class);
+        simpleProducer.setTIME(wait);
+        // Mocking behavior to break out of the loop after a few iterations
+        doAnswer(invocation -> {
+            simpleProducer.shutdown();
+            return null;
+        }).when(kafkaProducer).send(any(ProducerRecord.class));
+
+        // Invoking runAlways() in a separate thread to avoid an infinite loop
+        Thread thread = new Thread(() -> {
+            try {
+                simpleProducer.runAlways(topicName, callback);
+            } catch (Exception e) {
+            }
+        });
+        thread.start();
+
+        // Let the thread execute for some time (e.g., 1 second)
+        Thread.sleep(wait);
+
+        // Interrupting the thread to stop the infinite loop
+        thread.interrupt();
+
+        verify(kafkaProducer, atLeastOnce()).send(any(ProducerRecord.class));
+        verify(kafkaProducer, times(1)).close();
+    }
+
+}
diff --git a/sample-services/ics-producer-consumer/producer/src/test/java/com/demo/producer/ThreadsControllerTest.java b/sample-services/ics-producer-consumer/producer/src/test/java/com/demo/producer/ThreadsControllerTest.java
new file mode 100644 (file)
index 0000000..d3587f1
--- /dev/null
@@ -0,0 +1,89 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ *
+ * Copyright (C) 2024: OpenInfra Foundation Europe
+ *
+ * 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===================================
+ */
+
+package com.demo.producer;
+
+import com.demo.producer.controllers.ThreadsController;
+import com.demo.producer.producer.SimpleProducer;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import java.util.concurrent.CompletableFuture;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.*;
+
+@SpringBootTest
+@ContextConfiguration(classes = SimpleProducer.class)
+public class ThreadsControllerTest {
+
+    @Mock
+    @Autowired
+    private SimpleProducer simpleProducer;
+
+    @InjectMocks
+    private ThreadsController threadsController;
+
+    private MockHttpServletRequest request;
+    private MockHttpServletResponse response;
+
+    private AutoCloseable closable;
+
+    @BeforeEach
+    public void setUp() {
+        closable = MockitoAnnotations.openMocks(this);
+        request = new MockHttpServletRequest();
+        response = new MockHttpServletResponse();
+        RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request, response));
+    }
+
+    @AfterEach
+    public void close() throws Exception {
+        closable.close();
+    }
+
+    @Test
+    public void testStopProducerWhenNoActiveProducer() throws Exception {
+        String result = threadsController.stopProducer();
+        assertEquals("No active producer to stop", result);
+        verify(simpleProducer, never()).shutdown();
+    }
+
+    @Test
+    public void testPublishNMessage() throws Exception {
+        String topicName = "testTopic";
+        int numberOfMessages = 10;
+        CompletableFuture<String> future = CompletableFuture.completedFuture("Producer started for topic: " + topicName);
+        CompletableFuture<String> result = threadsController.publishNMessage(numberOfMessages, topicName);
+        assertEquals(future.getClass(), result.getClass());
+    }
+
+}
diff --git a/sample-services/ics-producer-consumer/red.sh b/sample-services/ics-producer-consumer/red.sh
new file mode 100644 (file)
index 0000000..12085fe
--- /dev/null
@@ -0,0 +1,189 @@
+#  ========================LICENSE_START=================================
+#  O-RAN-SC
+#
+#  Copyright (C) 2024: OpenInfra Foundation Europe
+#  ========================================================================
+#  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=================================================
+
+#!/bin/bash
+skip_build=false
+no_console=false
+
+# Parse command line arguments
+while [[ $# -gt 0 ]]; do
+    case $1 in
+        --skip-build)
+            skip_build=true
+            shift
+            ;;
+        --no-console)
+            no_console=true
+            shift
+            ;;
+        *)
+            echo "Unknown option: $1"
+            exit 1
+            ;;
+    esac
+done
+# Source the utils script
+source utils.sh
+
+# Check Prerequisites
+checkJava
+checkDocker
+checkDockerCompose
+
+if ! $skip_build; then
+    # Make build the demo docker image
+    cd ./producer/
+    make build
+    cd ../consumer/
+    make build
+    cd ..
+fi
+
+# Start the Docker containers in detached mode
+docker-compose up -d
+
+# Wait for the Kafka container to be running
+wait_for_container "kafka-zkless" "Kafka Server started"
+space
+
+if ! $no_console; then
+    echo "Start RedPanda Console"
+    docker-compose -f docker-composeRedPanda.yaml up -d
+    space
+
+    echo "Start NONRTRIC control panel"
+    docker-compose -f ./docker-compose/docker-compose.yaml -f ./docker-compose/control-panel/docker-compose.yaml -f ./docker-compose/nonrtric-gateway/docker-compose.yaml up -d
+    space
+fi
+
+# Once Kafka container is running, start the producers and consumers
+echo "Kafka container is up and running. Starting producer and consumer..."
+space
+
+echo "Start 1 Producer on mytopic"
+curl -X GET http://localhost:8080/startProducer/mytopic
+space
+
+echo "Start 1 Consumer on mytopic"
+curl -X GET http://localhost:8081/startConsumer/mytopic
+space
+
+sleep 10
+
+echo "Sending type1 to ICS"
+curl -X 'PUT' \
+  'http://localhost:8083/data-producer/v1/info-types/type1' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "info_job_data_schema": {
+    "$schema":"http://json-schema.org/draft-07/schema#",
+    "title":"STD_Type1_1.0.0",
+    "description":"Type 1",
+    "type":"object"
+  }
+}'
+
+echo "Getting types from ICS"
+curl -X 'GET' 'http://localhost:8083/data-producer/v1/info-types/type1'
+space
+
+echo "Sending Producer infos to ICS"
+curl -X 'PUT' \
+  'http://localhost:8083/data-producer/v1/info-producers/1' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "info_producer_supervision_callback_url": "http://kafka-producer:8080/producer/supervision",
+  "supported_info_types": [
+    "type1"
+  ],
+  "info_job_callback_url": "http://kafka-producer:8080/producer/job"
+}'
+
+echo "Getting Producers Infos from ICS"
+curl -H 'Content-Type: application/json' 'http://localhost:8083/data-producer/v1/info-producers/1'
+space
+
+echo "Sending Consumer Job infos to ICS"
+curl -X 'PUT' \
+  'http://localhost:8083/data-consumer/v1/info-jobs/1' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "info_type_id": "type1",
+  "job_owner": "demo",
+  "job_definition": {
+    "deliveryInfo": {
+      "topic": "mytopic",
+      "bootStrapServers": "http://kafka-zkless:9092",
+      "numberOfMessages": 0
+    }
+  },
+  "job_result_uri": "http://kafka-producer:8080/producer/job",
+  "status_notification_uri": "http://kafka-producer:8080/producer/supervision"
+}'
+
+echo "Getting Consumer Job Infos from ICS"
+curl -H 'Content-Type: application/json' 'http://localhost:8083/data-consumer/v1/info-jobs/1'
+space
+
+echo "Sending Consumer Subscription Job infos to ICS"
+curl -X 'PUT' \
+  'http://localhost:8083/data-consumer/v1/info-type-subscription/1' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "status_result_uri": "http://kafka-consumer:8081/info-type-status",
+  "owner": "owner"
+}'
+echo "Getting Consumer Subscription Job infos from ICS"
+curl -X 'GET' 'http://localhost:8083/data-consumer/v1/info-type-subscription/1' -H 'accept: application/json'
+space
+
+sleep 5
+echo "ICS Producer Docker logs "
+docker logs informationcoordinatorservice | grep -E 'o.o.i.c.r1producer.ProducerCallbacks|o.o.i.repository.InfoTypeSubscriptions'
+space
+echo "Demo Producer Docker logs "
+docker logs kafka-producer | grep c.d.p.p.SimpleProducer
+space
+echo "Demo Consumer Docker logs "
+docker logs kafka-consumer | grep c.d.c.c.SimpleConsumer
+space
+
+if ! $no_console; then
+    echo "Red Panda Console: http://localhost:8888"
+    echo "Control Panel Console: http://localhost:8181"
+fi
+
+echo "Done."
+
+containers=("kafka-producer" "kafka-consumer")
+
+for container in "${containers[@]}"; do
+  if docker logs "$container" | grep -q ERROR; then
+    echo "Errors found in logs of $container"
+    echo "FAIL"
+    exit 1
+  else
+    echo "No errors found in logs of $container"
+  fi
+done
+echo "SUCCESS"
+exit 0
diff --git a/sample-services/ics-producer-consumer/runconsumer.sh b/sample-services/ics-producer-consumer/runconsumer.sh
new file mode 100644 (file)
index 0000000..9ef776a
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/bash
+curl -X GET http://localhost:8081/startConsumer/mytopic
\ No newline at end of file
diff --git a/sample-services/ics-producer-consumer/runproducer.sh b/sample-services/ics-producer-consumer/runproducer.sh
new file mode 100644 (file)
index 0000000..f9f5a7e
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/bash
+curl -X GET http://localhost:8080/startProducer/mytopic
\ No newline at end of file
diff --git a/sample-services/ics-producer-consumer/start.sh b/sample-services/ics-producer-consumer/start.sh
new file mode 100644 (file)
index 0000000..7ddc908
--- /dev/null
@@ -0,0 +1,198 @@
+#  ========================LICENSE_START=================================
+#  O-RAN-SC
+#
+#  Copyright (C) 2024: OpenInfra Foundation Europe
+#  ========================================================================
+#  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=================================================
+#!/bin/bash
+source utils.sh
+
+PREFIX="nexus3.o-ran-sc.org:10004"
+VERSION="0.0.1"
+
+# Create a network for Kafka Containers
+docker network create kafka-net
+
+# Start Kafka
+docker run -d \
+  --network kafka-net \
+  --name kafka-zkless \
+  -p 9092:9092 \
+  -e LOG_DIR="/tmp/logs" \
+  -e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP="CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT" \
+  -e KAFKA_LISTENERS="PLAINTEXT://:29092,PLAINTEXT_HOST://:9092,CONTROLLER://:9093" \
+  -e KAFKA_ADVERTISED_LISTENERS="PLAINTEXT://kafka-zkless:29092,PLAINTEXT_HOST://kafka-zkless:9092" \
+  quay.io/strimzi/kafka:latest-kafka-2.8.1-amd64 \
+  /bin/sh -c 'export CLUSTER_ID=$(bin/kafka-storage.sh random-uuid) && \
+  bin/kafka-storage.sh format -t $CLUSTER_ID -c config/kraft/server.properties && \
+  bin/kafka-server-start.sh config/kraft/server.properties --override advertised.listeners=$KAFKA_ADVERTISED_LISTENERS --override listener.security.protocol.map=$KAFKA_LISTENER_SECURITY_PROTOCOL_MAP --override listeners=$KAFKA_LISTENERS'
+
+# Start ICS
+docker run -d \
+  --network kafka-net \
+  --name informationcoordinatorservice \
+  -p 8083:8083 \
+  -v ./application.yaml:/opt/app/information-coordinator-service/config/application.yaml \
+  nexus3.o-ran-sc.org:10001/o-ran-sc/nonrtric-plt-informationcoordinatorservice:1.6.0
+
+# Start Producer
+docker run -d \
+  --network kafka-net \
+  --name kafka-producer \
+  -p 8080:8080 \
+  -e KAFKA_SERVERS=kafka-zkless:9092 \
+  $PREFIX/o-ran-sc/nonrtric-sample-icsproducer:$VERSION
+
+#Start Consumer
+docker run -d \
+  --network kafka-net \
+  --name kafka-consumer \
+  -p 8081:8081 \
+  -e KAFKA_SERVERS=kafka-zkless:9092 \
+  $PREFIX/o-ran-sc/nonrtric-sample-icsconsumer:$VERSION
+
+# Wait for the Kafka container to be running
+wait_for_container "kafka-zkless" "Kafka Server started"
+wait_for_container "kafka-producer" "Started Application"
+wait_for_container "kafka-consumer" "Started Application"
+
+# Once Kafka container is running, start the producers and consumers
+echo "Kafka container is up and running. Starting producer and consumer..."
+space
+
+echo "Sending type1 to ICS"
+curl -X 'PUT' \
+  'http://localhost:8083/data-producer/v1/info-types/type1' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "info_job_data_schema": {
+    "$schema":"http://json-schema.org/draft-07/schema#",
+    "title":"STD_Type1_1.0.0",
+    "description":"Type 1",
+    "topic": "mytopic",
+    "bootStrapServers": "kafka-zkless:9092"
+    }
+}'
+
+echo "Getting types from ICS"
+curl -X 'GET' 'http://localhost:8083/data-producer/v1/info-types/type1'
+space
+
+echo "Sending Producer infos to ICS"
+curl -X 'PUT' \
+  'http://localhost:8083/data-producer/v1/info-producers/1' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "info_producer_supervision_callback_url": "http://kafka-producer:8080/producer/supervision",
+  "supported_info_types": [
+    "type1"
+  ],
+  "info_job_callback_url": "http://kafka-producer:8080/producer/job"
+}'
+
+echo "Getting Producers Infos from ICS"
+curl -H 'Content-Type: application/json' 'http://localhost:8083/data-producer/v1/info-producers/1'
+space
+
+echo "Sending Consumer Job infos to ICS"
+curl -X 'PUT' \
+  'http://localhost:8083/data-consumer/v1/info-jobs/1' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "info_type_id": "type1",
+  "job_owner": "demo",
+  "job_definition": {
+    "deliveryInfo": {
+      "topic": "mytopic",
+      "bootStrapServers": "kafka-zkless:9092",
+      "numberOfMessages": 100
+    }
+  },
+  "job_result_uri": "http://kafka-producer:8080/producer/job",
+  "status_notification_uri": "http://kafka-producer:8080/producer/supervision"
+}'
+
+echo "Getting Consumer Job Infos from ICS"
+curl -H 'Content-Type: application/json' 'http://localhost:8083/data-consumer/v1/info-jobs/1'
+space
+
+echo "Sending Consumer Subscription Job infos to ICS"
+curl -X 'PUT' \
+  'http://localhost:8083/data-consumer/v1/info-type-subscription/1' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "status_result_uri": "http://kafka-consumer:8081/consumer/info-type-status",
+  "owner": "demo"
+}'
+echo "Getting Consumer Subscription Job infos from ICS"
+curl -X 'GET' 'http://localhost:8083/data-consumer/v1/info-type-subscription/1' -H 'accept: application/json'
+space
+
+#To Set Kafka Broker in Consumer
+echo "Sending type1 to ICS to use the callback"
+curl -X 'PUT' \
+  'http://localhost:8083/data-producer/v1/info-types/type1' \
+  -H 'accept: application/json' \
+  -H 'Content-Type: application/json' \
+  -d '{
+  "info_job_data_schema": {
+    "$schema":"http://json-schema.org/draft-07/schema#",
+    "title":"STD_Type1_1.0.0",
+    "description":"Type 1",
+    "topic": "mytopic",
+    "bootStrapServers": "kafka-zkless:9092"
+    }
+}'
+
+#Using the autostart flag in the application.yaml
+echo "Start 1 Producer on mytopic"
+curl -X GET http://localhost:8080/startProducer/mytopic
+space
+
+echo "Start 1 Consumer on mytopic"
+curl -X GET http://localhost:8081/startConsumer/mytopic
+space
+
+sleep 10
+
+echo "ICS Producer Docker logs "
+docker logs informationcoordinatorservice | grep -E 'o.o.i.c.r1producer.ProducerCallbacks|o.o.i.repository.InfoTypeSubscriptions'
+space
+echo "Demo Producer Docker logs "
+docker logs kafka-producer | grep c.d.p.p.SimpleProducer
+space
+echo "Demo Consumer Docker logs "
+docker logs kafka-consumer | grep c.d.c.c.SimpleConsumer
+space
+
+echo "Done."
+
+containers=("kafka-producer" "kafka-consumer")
+
+for container in "${containers[@]}"; do
+  if docker logs "$container" | grep -q ERROR; then
+    echo "Errors found in logs of $container"
+    docker logs "$container" | grep ERROR
+    echo "FAIL"
+    exit 1
+  else
+    echo "No errors found in logs of $container"
+  fi
+done
+echo "SUCCESS"
+exit 0
diff --git a/sample-services/ics-producer-consumer/stop.sh b/sample-services/ics-producer-consumer/stop.sh
new file mode 100644 (file)
index 0000000..60fba31
--- /dev/null
@@ -0,0 +1,27 @@
+#  ========================LICENSE_START=================================
+#  O-RAN-SC
+#
+#  Copyright (C) 2024: OpenInfra Foundation Europe
+#  ========================================================================
+#  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=================================================
+
+#!/bin/bash
+docker-compose down
+
+docker-compose -f docker-composeRedPanda.yaml down
+
+docker-compose -f ./docker-compose/docker-compose.yaml \
+    -f ./docker-compose/control-panel/docker-compose.yaml \
+    -f ./docker-compose/nonrtric-gateway/docker-compose.yaml \
+    down
diff --git a/sample-services/ics-producer-consumer/utils.sh b/sample-services/ics-producer-consumer/utils.sh
new file mode 100644 (file)
index 0000000..af1cfa0
--- /dev/null
@@ -0,0 +1,115 @@
+#  ========================LICENSE_START=================================
+#  O-RAN-SC
+#
+#  Copyright (C) 2024: OpenInfra Foundation Europe
+#  ========================================================================
+#  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=================================================
+
+#!/bin/bash
+
+checkJava() {
+    if ! command -v java >/dev/null 2>&1; then
+        echo "Java is not installed. Please install Java."
+        echo "Suggested fix for ubuntu:"
+        echo "sudo apt install default-jdk"
+        exit 1
+    else
+        echo "Java is installed."
+    fi
+}
+
+checkMaven() {
+    if mvn -v >/dev/null 2>&1; then
+        echo "Maven is installed."
+    else
+        echo "Maven is not installed. Please install Maven."
+        echo "Suggested fix for ubuntu:"
+        echo "sudo apt install maven"
+        exit 1
+    fi
+}
+
+checkDocker() {
+    if ! docker -v > /dev/null 2>&1; then
+        echo "Docker is not installed. Please install Docker."
+        echo "Suggested fix for ubuntu:"
+        echo "sudo apt-get update"
+        echo "sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release"
+        echo "curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg"
+        echo "echo \"deb [arch=\$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \$(lsb_release -cs) stable\" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null"
+        echo "sudo apt-get update"
+        echo "sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin"
+        echo "sudo usermod -aG docker \$USER"
+               echo "newgrp docker"
+        exit 1
+    else
+        echo "Docker is installed."
+    fi
+}
+
+checkDockerCompose() {
+    if ! docker-compose -v > /dev/null 2>&1; then
+        echo "docker-compose is not installed. Please install docker-compose"
+        echo "Suggested fix for ubuntu:"
+        echo "sudo apt-get install docker-compose-plugin"
+        exit 1
+    else
+        echo "docker-compose is installed."
+    fi
+}
+
+# Function to wait for a Docker container to be running and log a specific string with a maximum timeout of 20 minutes
+wait_for_container() {
+    local container_name="$1"
+    local log_string="$2"
+    local timeout=1200  # Timeout set to 20 minutes (20 minutes * 60 seconds)
+
+    local start_time=$(date +%s)
+    local end_time=$((start_time + timeout))
+
+    while ! docker inspect "$container_name" &>/dev/null; do
+        echo "Waiting for container '$container_name' to be created..."
+        sleep 5
+        if [ "$(date +%s)" -ge "$end_time" ]; then
+            echo "Timeout: Container creation exceeded 20 minutes."
+            exit 1
+        fi
+    done
+
+    while [ "$(docker inspect -f '{{.State.Status}}' "$container_name")" != "running" ]; do
+        echo "Waiting for container '$container_name' to be running..."
+        sleep 5
+        if [ "$(date +%s)" -ge "$end_time" ]; then
+            echo "Timeout: Container start exceeded 20 minutes."
+            exit 1
+        fi
+    done
+
+    # Check container logs for the specified string
+    while ! docker logs "$container_name" 2>&1 | grep "$log_string"; do
+        echo "Waiting for '$log_string' in container logs of '$container_name'..."
+        sleep 5
+        if [ "$(date +%s)" -ge "$end_time" ]; then
+            echo "Timeout: Log string not found within 20 minutes."
+            exit 1
+        fi
+    done
+}
+
+
+space() {
+    echo ""
+    echo "++++++++++++++++++++++++++++++++++++++++++++++++++++"
+    echo ""
+}
index 8683a9d..8401bfd 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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.
@@ -34,7 +35,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW "
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
@@ -45,246 +46,278 @@ setup_testenvironment
 #### TEST BEGIN ####
 
 sim_generate_policy_uuid
+VERSIONS_TO_RUN=2
 
-# Tested variants of REST/DMAAP/SDNC config
-TESTED_VARIANTS="REST   DMAAP   REST+SDNC   DMAAP+SDNC"
-
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    TESTED_VARIANTS="REST   REST+SDNC"
+if [ -n "$A1PMS_V3_FLAG" ] && [ "${A1PMS_V3_FLAG,,}" == "true" ]; then
+  VERSIONS_TO_RUN=3
 fi
 
-#Test a1pms and simulator protocol versions (others are http only)
-TESTED_PROTOCOLS="HTTP HTTPS"
-for __httpx in $TESTED_PROTOCOLS ; do
-    for interface in $TESTED_VARIANTS ; do
-
-        echo "#####################################################################"
-        echo "#####################################################################"
-        echo "### Testing a1pms: $interface using $__httpx"
-        echo "#####################################################################"
-        echo "#####################################################################"
-
-        clean_environment
-
-        start_kube_proxy
-
-        if [ $__httpx == "HTTPS" ]; then
-            use_a1pms_rest_https
-        else
-            use_a1pms_rest_http
-        fi
-
-        start_a1pms NORPOXY $SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_CONFIG_FILE
-
-        set_a1pms_trace
-
-        # Create service to be able to receive events when rics becomes available
-        # Must use rest towards the a1pms since dmaap is not configured yet
-        a1pms_api_put_service 201 "ric-registration" 0 "$CR_SERVICE_APP_PATH_0/ric-registration"
-
-        if [ $__httpx == "HTTPS" ]; then
-            use_cr_https
-            use_simulator_https
-            if [[ $interface = *"SDNC"* ]]; then
-                if [[ "$SDNC_FEATURE_LEVEL" == *"NO_NB_HTTPS"* ]]; then
-                    deviation "SDNC does not support NB https"
-                    use_sdnc_http
-                else
-                    use_sdnc_https
-                fi
-            fi
-            if [[ $interface = *"DMAAP"* ]]; then
-                use_a1pms_dmaap_https
-            else
-                use_a1pms_rest_https
-            fi
-        else
-            use_cr_http
-            use_simulator_http
-            if [[ $interface = *"SDNC"* ]]; then
-                use_sdnc_http
-            fi
-            if [[ $interface = *"DMAAP"* ]]; then
-                use_a1pms_dmaap_http
-            else
-                use_a1pms_rest_http
-            fi
-        fi
-        if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-            :
-        else
-            if [ $__httpx == "HTTPS" ]; then
-                use_mr_https
-            else
-                use_mr_http
-            fi
-        fi
-
-        start_ric_simulators ricsim_g1 1  OSC_2.1.0
-        start_ric_simulators ricsim_g2 1  STD_1.1.3
-        start_ric_simulators ricsim_g3 1  STD_2.0.0
-
-        if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-            :
-        else
-            start_mr    "$MR_READ_TOPIC"  "/events" "users/policy-agent" \
-                        "$MR_WRITE_TOPIC" "/events" "users/mr-stub"
-        fi
-
-        start_cr 1
-
-        start_control_panel $SIM_GROUP/$CONTROL_PANEL_COMPOSE_DIR/$CONTROL_PANEL_CONFIG_FILE
-
-        if [ ! -z "$NRT_GATEWAY_APP_NAME" ]; then
-            start_gateway $SIM_GROUP/$NRT_GATEWAY_COMPOSE_DIR/$NRT_GATEWAY_CONFIG_FILE
-        fi
-
-
-        if [[ $interface = *"SDNC"* ]]; then
-            start_sdnc
-            controller_api_wait_for_status_ok 200 ricsim_g1_1
-            prepare_a1pms_config      SDNC    ".a1pms_config.json"
-        else
-            prepare_a1pms_config      NOSDNC  ".a1pms_config.json"
-        fi
-
-        if [ $RUNMODE == "KUBE" ]; then
-            a1pms_load_config                       ".a1pms_config.json"
-        else
-            #Temporary switch to http/https if dmaap use. Otherwise it is not possible to push config
-            if [ $__httpx == "HTTPS" ]; then
-                use_a1pms_rest_https
-            else
-                use_a1pms_rest_http
-            fi
-            a1pms_api_put_configuration 200 ".a1pms_config.json"
-            if [ $__httpx == "HTTPS" ]; then
-                if [[ $interface = *"DMAAP"* ]]; then
-                    use_a1pms_dmaap_https
-                else
-                    use_a1pms_rest_https
-                fi
-            else
-                if [[ $interface = *"DMAAP"* ]]; then
-                    use_a1pms_dmaap_http
-                else
-                    use_a1pms_rest_http
-                fi
-            fi
-        fi
-
-        if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-            :
-        else
-            mr_equal requests_submitted 0
-        fi
-
-        sim_put_policy_type 201 ricsim_g1_1 1 testdata/OSC/sim_1.json
-
-        sim_put_policy_type 201 ricsim_g3_1 STD_QOS_0_2_0 testdata/STD2/sim_qos.json
-
-        a1pms_equal json:rics 3 300
-
-        a1pms_equal json:policy-types 3 120
-
-        a1pms_equal json:policies 0
-
-        a1pms_equal json:policy-instances 0
-
-        cr_equal 0 received_callbacks 3 120
-
-        cr_api_check_all_sync_events 200 0 ric-registration ricsim_g1_1 ricsim_g2_1 ricsim_g3_1
-
-        echo "############################################"
-        echo "############## Health check ################"
-        echo "############################################"
-
-        sleep_wait 120 "Let A1PMS configuration take effect"
-
-        a1pms_api_get_status 200
-
-        echo "############################################"
-        echo "##### Service registry and supervision #####"
-        echo "############################################"
-
-        a1pms_api_put_service 201 "serv1" 1000 "$CR_SERVICE_APP_PATH_0/1"
-
-        a1pms_api_get_service_ids 200 "serv1" "ric-registration"
+for version in $(seq 2 $VERSIONS_TO_RUN); do
+
+  if [ "$version" == "3" ]; then
+    if [ -n "$A1PMS_V3" ] && [ -n "$A1PMS_API_PREFIX_V3" ] && [ -n "$A1PMS_ALIVE_URL_V3" ]; then
+      export A1PMS_VERSION="$A1PMS_V3"
+      export A1PMS_API_PREFIX="$A1PMS_API_PREFIX_V3"
+      export A1PMS_ALIVE_URL="$A1PMS_API_PREFIX$A1PMS_ALIVE_URL_V3"
+    else
+      echo "One/All parameters not set in env file (<A1PMS_V3>, <A1PMS_API_PREFIX_V3>, <A1PMS_ALIVE_URL_V3>)"
+      break
+    fi
+  fi
+  # Tested variants of REST/DMAAP/SDNC config
+  TESTED_VARIANTS="REST   DMAAP   REST+SDNC   DMAAP+SDNC"
+
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      TESTED_VARIANTS="REST   REST+SDNC"
+  fi
+
+  #Test a1pms and simulator protocol versions (others are http only)
+  TESTED_PROTOCOLS="HTTP HTTPS"
+  for __httpx in $TESTED_PROTOCOLS ; do
+      for interface in $TESTED_VARIANTS ; do
+
+          echo "#####################################################################"
+          echo "#####################################################################"
+          echo "### Testing a1pms: $interface using $__httpx with a1pms V${version}"
+          echo "#####################################################################"
+          echo "#####################################################################"
+
+          clean_environment
+
+          start_kube_proxy
+
+          if [ $__httpx == "HTTPS" ]; then
+              use_a1pms_rest_https
+          else
+              use_a1pms_rest_http
+          fi
+
+          start_a1pms NORPOXY $SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_CONFIG_FILE
+
+          set_a1pms_trace
+
+          # Create service to be able to receive events when rics becomes available
+          # Must use rest towards the a1pms since dmaap is not configured yet
+          a1pms_api_put_service 201 "ric-registration" 0 "$CR_SERVICE_APP_PATH_0/ric-registration"
+
+          if [ $__httpx == "HTTPS" ]; then
+              use_cr_https
+              use_simulator_https
+              if [[ $interface = *"SDNC"* ]]; then
+                  if [[ "$SDNC_FEATURE_LEVEL" == *"NO_NB_HTTPS"* ]]; then
+                      deviation "SDNC does not support NB https"
+                      use_sdnc_http
+                  else
+                      use_sdnc_https
+                  fi
+              fi
+              if [[ $interface = *"DMAAP"* ]]; then
+                  use_a1pms_dmaap_https
+              else
+                  use_a1pms_rest_https
+              fi
+          else
+              use_cr_http
+              use_simulator_http
+              if [[ $interface = *"SDNC"* ]]; then
+                  use_sdnc_http
+              fi
+              if [[ $interface = *"DMAAP"* ]]; then
+                  use_a1pms_dmaap_http
+              else
+                  use_a1pms_rest_http
+              fi
+          fi
+          if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+              :
+          else
+              if [ $__httpx == "HTTPS" ]; then
+                  use_mr_https
+              else
+                  use_mr_http
+              fi
+          fi
+
+          start_ric_simulators ricsim_g1 1  OSC_2.1.0
+          start_ric_simulators ricsim_g2 1  STD_1.1.3
+          start_ric_simulators ricsim_g3 1  STD_2.0.0
+
+          if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+              :
+          else
+              start_mr    "$MR_READ_TOPIC"  "/events" "users/policy-agent" \
+                          "$MR_WRITE_TOPIC" "/events" "users/mr-stub"
+          fi
+
+          start_cr 1
+
+          start_control_panel $SIM_GROUP/$CONTROL_PANEL_COMPOSE_DIR/$CONTROL_PANEL_CONFIG_FILE
+
+          if [ ! -z "$NRT_GATEWAY_APP_NAME" ]; then
+              start_gateway $SIM_GROUP/$NRT_GATEWAY_COMPOSE_DIR/$NRT_GATEWAY_CONFIG_FILE
+          fi
+
+
+          if [[ $interface = *"SDNC"* ]]; then
+              start_sdnc
+              controller_api_wait_for_status_ok 200 ricsim_g1_1
+              prepare_a1pms_config      SDNC    ".a1pms_config.json"
+          else
+              prepare_a1pms_config      NOSDNC  ".a1pms_config.json"
+          fi
+
+          if [ $RUNMODE == "KUBE" ]; then
+              a1pms_load_config                       ".a1pms_config.json"
+          else
+              #Temporary switch to http/https if dmaap use. Otherwise it is not possible to push config
+              if [ $__httpx == "HTTPS" ]; then
+                  use_a1pms_rest_https
+              else
+                  use_a1pms_rest_http
+              fi
+              a1pms_api_put_configuration 200 ".a1pms_config.json"
+              if [ $__httpx == "HTTPS" ]; then
+                  if [[ $interface = *"DMAAP"* ]]; then
+                      use_a1pms_dmaap_https
+                  else
+                      use_a1pms_rest_https
+                  fi
+              else
+                  if [[ $interface = *"DMAAP"* ]]; then
+                      use_a1pms_dmaap_http
+                  else
+                      use_a1pms_rest_http
+                  fi
+              fi
+          fi
+
+          if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+              :
+          else
+              mr_equal requests_submitted 0
+          fi
+
+          sim_put_policy_type 201 ricsim_g1_1 1 testdata/OSC/sim_1.json
+
+          sim_put_policy_type 201 ricsim_g3_1 STD_QOS_0_2_0 testdata/STD2/sim_qos.json
+
+          a1pms_equal json:rics 3 300
+
+          if [ "$A1PMS_VERSION" == "V3" ]; then
+            a1pms_equal json:policytypes 3 120
+          else
+            a1pms_equal json:policy-types 3 120
+            a1pms_equal json:policy-instances 0
+          fi
+
+          a1pms_equal json:policies 0
+
+          cr_equal 0 received_callbacks 3 120
+
+          cr_api_check_all_sync_events 200 0 ric-registration ricsim_g1_1 ricsim_g2_1 ricsim_g3_1
+
+          echo "############################################"
+          echo "############## Health check ################"
+          echo "############################################"
+
+          sleep_wait 120 "Let A1PMS configuration take effect"
+
+          a1pms_api_get_status 200
+
+          echo "############################################"
+          echo "##### Service registry and supervision #####"
+          echo "############################################"
+
+          a1pms_api_put_service 201 "serv1" 1000 "$CR_SERVICE_APP_PATH_0/1"
+
+          a1pms_api_get_service_ids 200 "serv1" "ric-registration"
+
+          a1pms_api_put_services_keepalive 200 "serv1"
+
+          echo "############################################"
+          echo "############## RIC Repository ##############"
+          echo "############################################"
 
-        a1pms_api_put_services_keepalive 200 "serv1"
+          a1pms_api_get_rics 200 NOTYPE "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:1:AVAILABLE  ricsim_g2_1:me1_ricsim_g2_1,me2_ricsim_g2_1:EMPTYTYPE:AVAILABLE ricsim_g3_1:me1_ricsim_g3_1,me2_ricsim_g3_1:STD_QOS_0_2_0:AVAILABLE"
 
-        echo "############################################"
-        echo "############## RIC Repository ##############"
-        echo "############################################"
+          echo "############################################"
+          echo "########### A1 Policy Management ###########"
+          echo "############################################"
 
-        a1pms_api_get_rics 200 NOTYPE "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:1:AVAILABLE  ricsim_g2_1:me1_ricsim_g2_1,me2_ricsim_g2_1:EMPTYTYPE:AVAILABLE ricsim_g3_1:me1_ricsim_g3_1,me2_ricsim_g3_1:STD_QOS_0_2_0:AVAILABLE"
+          notificationurl=$CR_SERVICE_APP_PATH_0"/test"
+          if [ "$A1PMS_VERSION" == "V3" ]; then
+            a1pms_api_post_policy_v3 201 "serv1" ricsim_g1_1 1 5000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
+            a1pms_api_put_policy_v3 200 5000 testdata/OSC/pi1_template.json
+            a1pms_api_post_policy_v3 201 "serv1" ricsim_g3_1 STD_QOS_0_2_0 5200 true $notificationurl testdata/STD2/pi_qos_template.json
+            a1pms_api_put_policy_v3 200 5200 testdata/STD2/pi_qos_template.json
+            a1pms_api_post_policy_v3 201 "serv1" ricsim_g2_1 NOTYPE 5100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json
+            a1pms_api_put_policy_v3 200 5100 testdata/STD/pi1_template.json
+          else
+            a1pms_api_put_policy 201 "serv1" ricsim_g1_1 1 5000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
+            a1pms_api_put_policy 200 "serv1" ricsim_g1_1 1 5000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
+            a1pms_api_put_policy 201 "serv1" ricsim_g3_1 STD_QOS_0_2_0 5200 true $notificationurl testdata/STD2/pi_qos_template.json
+            a1pms_api_put_policy 200 "serv1" ricsim_g3_1 STD_QOS_0_2_0 5200 true $notificationurl testdata/STD2/pi_qos_template.json
+
+            a1pms_api_put_policy 201 "serv1" ricsim_g2_1 NOTYPE 5100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json
+            a1pms_api_put_policy 200 "serv1" ricsim_g2_1 NOTYPE 5100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json
+          fi
+
+          a1pms_equal json:policies 3
 
-        echo "############################################"
-        echo "########### A1 Policy Management ###########"
-        echo "############################################"
+          a1pms_api_delete_policy 204 5000
 
-        notificationurl=$CR_SERVICE_APP_PATH_0"/test"
-        a1pms_api_put_policy 201 "serv1" ricsim_g1_1 1 5000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
-        a1pms_api_put_policy 200 "serv1" ricsim_g1_1 1 5000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
-        a1pms_api_put_policy 201 "serv1" ricsim_g3_1 STD_QOS_0_2_0 5200 true $notificationurl testdata/STD2/pi_qos_template.json
-        a1pms_api_put_policy 200 "serv1" ricsim_g3_1 STD_QOS_0_2_0 5200 true $notificationurl testdata/STD2/pi_qos_template.json
+          a1pms_api_delete_policy 204 5100
 
-        a1pms_api_put_policy 201 "serv1" ricsim_g2_1 NOTYPE 5100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json
-        a1pms_api_put_policy 200 "serv1" ricsim_g2_1 NOTYPE 5100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json
+          a1pms_api_delete_policy 204 5200
 
-        a1pms_equal json:policies 3
+          a1pms_equal json:policies 0
 
-        a1pms_api_delete_policy 204 5000
+          if [ "$A1PMS_VERSION" != "V3" ]; then
+            a1pms_equal json:policy-instances 0
+          fi
 
-        a1pms_api_delete_policy 204 5100
+          cr_equal 0 received_callbacks 3
 
-        a1pms_api_delete_policy 204 5200
+          if [[ $interface = *"DMAAP"* ]]; then
 
-        a1pms_equal json:policies 0
+              VAL=14 # Number of a1pms API calls over DMAAP
+              mr_equal requests_fetched $VAL
+              mr_equal responses_submitted $VAL
+              mr_equal responses_fetched $VAL
+              mr_equal current_requests 0
+              mr_equal current_responses 0
+          else
+              if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+                  :
+              else
+                  mr_equal requests_submitted 0
+              fi
+          fi
 
-        a1pms_equal json:policy-instances 0
+          if [[ $interface = *"SDNC"* ]]; then
+              sim_contains_str ricsim_g1_1 remote_hosts $SDNC_APP_NAME
+              sim_contains_str ricsim_g2_1 remote_hosts $SDNC_APP_NAME
+              sim_contains_str ricsim_g3_1 remote_hosts $SDNC_APP_NAME
+          else
+              sim_contains_str ricsim_g1_1 remote_hosts $A1PMS_APP_NAME
+              sim_contains_str ricsim_g2_1 remote_hosts $A1PMS_APP_NAME
+              sim_contains_str ricsim_g3_1 remote_hosts $A1PMS_APP_NAME
+          fi
 
-        cr_equal 0 received_callbacks 3
+          check_a1pms_logs
 
-        if [[ $interface = *"DMAAP"* ]]; then
 
-            VAL=14 # Number of a1pms API calls over DMAAP
-            mr_equal requests_fetched $VAL
-            mr_equal responses_submitted $VAL
-            mr_equal responses_fetched $VAL
-            mr_equal current_requests 0
-            mr_equal current_responses 0
-        else
-            if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-                :
-            else
-                mr_equal requests_submitted 0
-            fi
-        fi
+          if [[ $interface = *"SDNC"* ]]; then
+              check_sdnc_logs
+          fi
 
-        if [[ $interface = *"SDNC"* ]]; then
-            sim_contains_str ricsim_g1_1 remote_hosts $SDNC_APP_NAME
-            sim_contains_str ricsim_g2_1 remote_hosts $SDNC_APP_NAME
-            sim_contains_str ricsim_g3_1 remote_hosts $SDNC_APP_NAME
-        else
-            sim_contains_str ricsim_g1_1 remote_hosts $A1PMS_APP_NAME
-            sim_contains_str ricsim_g2_1 remote_hosts $A1PMS_APP_NAME
-            sim_contains_str ricsim_g3_1 remote_hosts $A1PMS_APP_NAME
-        fi
+          store_logs          "${__httpx}__${interface}"
 
-        check_a1pms_logs
+      done
 
-
-        if [[ $interface = *"SDNC"* ]]; then
-            check_sdnc_logs
-        fi
-
-        store_logs          "${__httpx}__${interface}"
-
-    done
+  done
 
 done
-
 #### TEST COMPLETE ####
 
 
index 6fb5003..a302cc3 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
@@ -42,258 +43,344 @@ SUPPORTED_RUNMODES="DOCKER KUBE"
 setup_testenvironment
 
 #### TEST BEGIN ####
+VERSIONS_TO_RUN=2
 
-sim_generate_policy_uuid
-
-use_simulator_http
-use_mr_http
-use_a1pms_rest_http
-
-
-clean_environment
-
-start_kube_proxy
-
-start_ric_simulators  ricsim_g1 3 OSC_2.1.0
-
-start_ric_simulators  ricsim_g2 5 STD_1.1.3
-
-start_ric_simulators ricsim_g3 1  STD_2.0.0
-
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    :
-else
-    start_mr
+if [ -n "$A1PMS_V3_FLAG" ] && [ "${A1PMS_V3_FLAG,,}" == "true" ]; then
+  VERSIONS_TO_RUN=3
 fi
 
-start_cr 1
+for version in $(seq 2 $VERSIONS_TO_RUN); do
 
+  echo "#####################################################################"
+  echo "#####################################################################"
+  echo "### Testing a1pms: V${version}"
+  echo "#####################################################################"
+  echo "#####################################################################"
 
-start_control_panel $SIM_GROUP/$CONTROL_PANEL_COMPOSE_DIR/$CONTROL_PANEL_CONFIG_FILE
+  if [ "$version" == "3" ]; then
+    if [ -n "$A1PMS_V3" ] && [ -n "$A1PMS_API_PREFIX_V3" ] && [ -n "$A1PMS_ALIVE_URL_V3" ]; then
+      export A1PMS_VERSION="$A1PMS_V3"
+      export A1PMS_API_PREFIX="$A1PMS_API_PREFIX_V3"
+      export A1PMS_ALIVE_URL="$A1PMS_API_PREFIX$A1PMS_ALIVE_URL_V3"
+    else
+      echo "One/All parameters not set in env file (<A1PMS_V3>, <A1PMS_API_PREFIX_V3>, <A1PMS_ALIVE_URL_V3>)"
+      break
+    fi
+  fi
+  sim_generate_policy_uuid
 
-if [ ! -z "$NRT_GATEWAY_APP_NAME" ]; then
-    start_gateway $SIM_GROUP/$NRT_GATEWAY_COMPOSE_DIR/$NRT_GATEWAY_CONFIG_FILE
-fi
+  use_simulator_http
+  use_mr_http
+  use_a1pms_rest_http
 
-start_a1pms NORPOXY $SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_CONFIG_FILE
 
-set_a1pms_debug
+  clean_environment
 
-use_a1pms_rest_http
+  start_kube_proxy
 
+  start_ric_simulators  ricsim_g1 3 OSC_2.1.0
 
-prepare_a1pms_config      NOSDNC  ".a1pms_config.json"
+  start_ric_simulators  ricsim_g2 5 STD_1.1.3
 
-if [ $RUNMODE == "KUBE" ]; then
-    a1pms_load_config                       ".a1pms_config.json"
-else
-    a1pms_api_put_configuration 200 ".a1pms_config.json"
-fi
+  start_ric_simulators ricsim_g3 1  STD_2.0.0
 
-sleep_wait 120 "Let A1PMS configuration take effect"
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      :
+  else
+      start_mr
+  fi
 
-a1pms_api_get_status 200
+  start_cr 1
 
-sim_print ricsim_g1_1 interface
 
-sim_print ricsim_g2_1 interface
+  start_control_panel $SIM_GROUP/$CONTROL_PANEL_COMPOSE_DIR/$CONTROL_PANEL_CONFIG_FILE
 
-sim_print ricsim_g3_1 interface
+  if [ ! -z "$NRT_GATEWAY_APP_NAME" ]; then
+      start_gateway $SIM_GROUP/$NRT_GATEWAY_COMPOSE_DIR/$NRT_GATEWAY_CONFIG_FILE
+  fi
 
-sim_put_policy_type 201 ricsim_g1_1 1 testdata/OSC/sim_1.json
+  start_a1pms NORPOXY $SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_CONFIG_FILE
 
-sim_put_policy_type 201 ricsim_g3_1 STD_QOS_0_2_0 testdata/STD2/sim_qos.json
-a1pms_equal json:policy-types 3 300
+  set_a1pms_debug
 
-# Create policies
+  use_a1pms_rest_http
 
-notificationurl=$CR_SERVICE_APP_PATH_0"/test"
 
-use_a1pms_rest_http
+  prepare_a1pms_config      NOSDNC  ".a1pms_config.json"
 
-a1pms_api_put_service 201 "service1" 3600 "$CR_SERVICE_APP_PATH_0/1"
+  if [ $RUNMODE == "KUBE" ]; then
+      a1pms_load_config                       ".a1pms_config.json"
+  else
+      a1pms_api_put_configuration 200 ".a1pms_config.json"
+  fi
 
-a1pms_api_put_policy 201 "service1" ricsim_g1_1 1 2000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json 1
+  sleep_wait 120 "Let A1PMS configuration take effect"
 
-sim_equal ricsim_g1_1 num_instances 1
+  a1pms_api_get_status 200
 
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    use_a1pms_rest_http
-else
-    use_a1pms_dmaap_http
-fi
+  sim_print ricsim_g1_1 interface
 
-a1pms_api_put_policy 201 "service1" ricsim_g1_1 1 3000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json 1
+  sim_print ricsim_g2_1 interface
 
-sim_equal ricsim_g1_1 num_instances 2
+  sim_print ricsim_g3_1 interface
 
+  sim_put_policy_type 201 ricsim_g1_1 1 testdata/OSC/sim_1.json
 
-use_a1pms_rest_http
+  sim_put_policy_type 201 ricsim_g3_1 STD_QOS_0_2_0 testdata/STD2/sim_qos.json
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_equal json:policytypes 7 300
+  else
+    a1pms_equal json:policy-types 3 300
+  fi
 
-a1pms_api_put_policy 201 "service1" ricsim_g2_1 NOTYPE 2100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json 1
+  # Create policies
 
-sim_equal ricsim_g2_1 num_instances 1
+  notificationurl=$CR_SERVICE_APP_PATH_0"/test"
 
+  use_a1pms_rest_http
 
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    use_a1pms_rest_http
-else
-    use_a1pms_dmaap_http
-fi
-
-a1pms_api_put_policy 201 "service1" ricsim_g2_1 NOTYPE 3100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json 1
-
-sim_equal ricsim_g2_1 num_instances 2
-
-use_a1pms_rest_http
-
-a1pms_api_put_policy 201 "service1" ricsim_g3_1 STD_QOS_0_2_0 2200 true $notificationurl testdata/STD2/pi_qos_template.json 1
+  a1pms_api_put_service 201 "service1" 3600 "$CR_SERVICE_APP_PATH_0/1"
 
-sim_equal ricsim_g3_1 num_instances 1
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_api_post_policy_v3 201 "service1" ricsim_g1_1 1 2000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json 1
+  else
+    a1pms_api_put_policy 201 "service1" ricsim_g1_1 1 2000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json 1
+  fi
 
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    use_a1pms_rest_http
-else
-    use_a1pms_dmaap_http
-fi
-
-a1pms_api_put_policy 201 "service1" ricsim_g3_1 STD_QOS_0_2_0 3200 NOTRANSIENT $notificationurl testdata/STD2/pi_qos_template.json 1
+  sim_equal ricsim_g1_1 num_instances 1
 
-sim_equal ricsim_g3_1 num_instances 2
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      use_a1pms_rest_http
+  else
+      use_a1pms_dmaap_http
+  fi
 
-#Update policies
-use_a1pms_rest_http
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_api_post_policy_v3 201 "service1" ricsim_g1_1 1 3000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json 1
+  else
+    a1pms_api_put_policy 201 "service1" ricsim_g1_1 1 3000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json 1
+  fi
 
-a1pms_api_put_service 200 "service1" 3600 "$CR_SERVICE_APP_PATH_0/1"
+  sim_equal ricsim_g1_1 num_instances 2
 
-a1pms_api_put_policy 200 "service1" ricsim_g1_1 1 2000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json 1
 
-sim_equal ricsim_g1_1 num_instances 2
+  use_a1pms_rest_http
 
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_api_post_policy_v3 201 "service1" ricsim_g2_1 NOTYPE 2100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json 1
+  else
+    a1pms_api_put_policy 201 "service1" ricsim_g2_1 NOTYPE 2100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json 1
+  fi
 
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    use_a1pms_rest_http
-else
-    use_a1pms_dmaap_http
-fi
+  sim_equal ricsim_g2_1 num_instances 1
 
-a1pms_api_put_policy 200 "service1" ricsim_g1_1 1 3000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json 1
 
-sim_equal ricsim_g1_1 num_instances 2
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      use_a1pms_rest_http
+  else
+      use_a1pms_dmaap_http
+  fi
 
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_api_post_policy_v3 201 "service1" ricsim_g2_1 NOTYPE 3100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json 1
+  else
+    a1pms_api_put_policy 201 "service1" ricsim_g2_1 NOTYPE 3100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json 1
+  fi
 
-use_a1pms_rest_http
+  sim_equal ricsim_g2_1 num_instances 2
 
+  use_a1pms_rest_http
 
-a1pms_api_put_policy 200 "service1" ricsim_g2_1 NOTYPE 2100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json 1
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_api_post_policy_v3 201 "service1" ricsim_g3_1 STD_QOS_0_2_0 2200 true $notificationurl testdata/STD2/pi_qos_template.json 1
+  else
+    a1pms_api_put_policy 201 "service1" ricsim_g3_1 STD_QOS_0_2_0 2200 true $notificationurl testdata/STD2/pi_qos_template.json 1
+  fi
 
-sim_equal ricsim_g2_1 num_instances 2
+  sim_equal ricsim_g3_1 num_instances 1
 
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      use_a1pms_rest_http
+  else
+      use_a1pms_dmaap_http
+  fi
 
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    use_a1pms_rest_http
-else
-    use_a1pms_dmaap_http
-fi
-
-a1pms_api_put_policy 200 "service1" ricsim_g2_1 NOTYPE 3100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json 1
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_api_post_policy_v3 201 "service1" ricsim_g3_1 STD_QOS_0_2_0 3200 NOTRANSIENT $notificationurl testdata/STD2/pi_qos_template.json 1
+  else
+    a1pms_api_put_policy 201 "service1" ricsim_g3_1 STD_QOS_0_2_0 3200 NOTRANSIENT $notificationurl testdata/STD2/pi_qos_template.json 1
+  fi
 
-sim_equal ricsim_g2_1 num_instances 2
+  sim_equal ricsim_g3_1 num_instances 2
 
-use_a1pms_rest_http
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    # Check policies
+    a1pms_api_get_policy 200 2000 testdata/OSC/pi1_template.json "service1" ricsim_g1_1 1 false $notificationurl
+    a1pms_api_get_policy 200 3000 testdata/OSC/pi1_template.json "service1" ricsim_g1_1 1 false $notificationurl
+    a1pms_api_get_policy 200 2100 testdata/STD/pi1_template.json "service1" ricsim_g2_1 NOTYPE false $notificationurl
+    a1pms_api_get_policy 200 3100 testdata/STD/pi1_template.json "service1" ricsim_g2_1 NOTYPE false $notificationurl
+    a1pms_api_get_policy 200 2200 testdata/STD2/pi_qos_template.json "service1" ricsim_g3_1 STD_QOS_0_2_0 true $notificationurl
+    a1pms_api_get_policy 200 3200 testdata/STD2/pi_qos_template.json "service1" ricsim_g3_1 STD_QOS_0_2_0 true $notificationurl
+  fi
 
-a1pms_api_put_policy 200 "service1" ricsim_g3_1 STD_QOS_0_2_0 2200 true $notificationurl testdata/STD2/pi_qos_template.json 1
+  #Update policies
+  use_a1pms_rest_http
 
-sim_equal ricsim_g3_1 num_instances 2
+  a1pms_api_put_service 200 "service1" 3600 "$CR_SERVICE_APP_PATH_0/1"
 
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_api_put_policy_v3 200 2000 testdata/OSC/pi1_template.json 1
+  else
+    a1pms_api_put_policy 200 "service1" ricsim_g1_1 1 2000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json 1
+  fi
 
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    use_a1pms_rest_http
-else
-    use_a1pms_dmaap_http
-fi
-
-a1pms_api_put_policy 200 "service1" ricsim_g3_1 STD_QOS_0_2_0 3200 true $notificationurl testdata/STD2/pi_qos_template.json 1
-
-sim_equal ricsim_g3_1 num_instances 2
-
-# Check policies
-a1pms_api_get_policy 200 2000 testdata/OSC/pi1_template.json "service1" ricsim_g1_1 1 false $notificationurl
-a1pms_api_get_policy 200 3000 testdata/OSC/pi1_template.json "service1" ricsim_g1_1 1 false $notificationurl
-a1pms_api_get_policy 200 2100 testdata/STD/pi1_template.json "service1" ricsim_g2_1 NOTYPE false $notificationurl
-a1pms_api_get_policy 200 3100 testdata/STD/pi1_template.json "service1" ricsim_g2_1 NOTYPE false $notificationurl
-a1pms_api_get_policy 200 2200 testdata/STD2/pi_qos_template.json "service1" ricsim_g3_1 STD_QOS_0_2_0 true $notificationurl
-a1pms_api_get_policy 200 3200 testdata/STD2/pi_qos_template.json "service1" ricsim_g3_1 STD_QOS_0_2_0 true $notificationurl
-
-sim_equal ricsim_g1_1 num_instances 2
-sim_equal ricsim_g2_1 num_instances 2
-
-sim_equal ricsim_g3_1 num_instances 2
-
-# Remove policies
-
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    use_a1pms_rest_http
-else
-    use_a1pms_dmaap_http
-fi
-a1pms_api_delete_policy 204 2000
-use_a1pms_rest_http
-a1pms_api_delete_policy 204 3000
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    use_a1pms_rest_http
-else
-    use_a1pms_dmaap_http
-fi
-a1pms_api_delete_policy 204 2100
-use_a1pms_rest_http
-a1pms_api_delete_policy 204 3100
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    use_a1pms_rest_http
-else
-    use_a1pms_dmaap_http
-fi
-a1pms_api_delete_policy 204 2200
-use_a1pms_rest_http
-a1pms_api_delete_policy 204 3200
-
-sim_equal ricsim_g1_1 num_instances 0
-sim_equal ricsim_g2_1 num_instances 0
-
-sim_equal ricsim_g3_1 num_instances 0
-
-# Check remote host access to simulator
-
-sim_contains_str ricsim_g1_1 remote_hosts $A1PMS_APP_NAME
-sim_contains_str ricsim_g2_1 remote_hosts $A1PMS_APP_NAME
-sim_contains_str ricsim_g3_1 remote_hosts $A1PMS_APP_NAME
-
-# Check policy removal
-use_a1pms_rest_http
-a1pms_api_get_policy 404 2000
-a1pms_api_get_policy 404 3000
-a1pms_api_get_policy 404 2100
-a1pms_api_get_policy 404 3100
-
-a1pms_api_get_policy 404 2200
-a1pms_api_get_policy 404 3200
-
-# Remove the service
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    use_a1pms_rest_http
-else
-    use_a1pms_dmaap_http
-fi
-a1pms_api_delete_services 204 "service1"
-
-a1pms_api_get_services 404 "service1"
+  sim_equal ricsim_g1_1 num_instances 2
 
-check_a1pms_logs
 
-#### TEST COMPLETE ####
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      use_a1pms_rest_http
+  else
+      use_a1pms_dmaap_http
+  fi
+
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_api_put_policy_v3 200 3000 testdata/OSC/pi1_template.json 1
+  else
+    a1pms_api_put_policy 200 "service1" ricsim_g1_1 1 3000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json 1
+  fi
+
+  sim_equal ricsim_g1_1 num_instances 2
+
+
+  use_a1pms_rest_http
+
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_api_put_policy_v3 200 2100 testdata/STD/pi1_template.json 1
+  else
+    a1pms_api_put_policy 200 "service1" ricsim_g2_1 NOTYPE 2100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json 1
+  fi
+
+  sim_equal ricsim_g2_1 num_instances 2
+
+
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      use_a1pms_rest_http
+  else
+      use_a1pms_dmaap_http
+  fi
+
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_api_put_policy_v3 200 3100 testdata/STD/pi1_template.json 1
+  else
+    a1pms_api_put_policy 200 "service1" ricsim_g2_1 NOTYPE 3100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json 1
+  fi
+
+  sim_equal ricsim_g2_1 num_instances 2
+
+  use_a1pms_rest_http
+
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_api_put_policy_v3 200 2200 testdata/STD2/pi_qos_template.json 1
+  else
+    a1pms_api_put_policy 200 "service1" ricsim_g3_1 STD_QOS_0_2_0 2200 true $notificationurl testdata/STD2/pi_qos_template.json 1
+  fi
+
+  sim_equal ricsim_g3_1 num_instances 2
+
+
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      use_a1pms_rest_http
+  else
+      use_a1pms_dmaap_http
+  fi
+
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_api_put_policy_v3 200 3200 testdata/STD2/pi_qos_template.json 1
+  else
+    a1pms_api_put_policy 200 "service1" ricsim_g3_1 STD_QOS_0_2_0 3200 true $notificationurl testdata/STD2/pi_qos_template.json 1
+  fi
+
+  sim_equal ricsim_g3_1 num_instances 2
+
+  if [ "$A1PMS_VERSION" != "V3" ]; then
+    # Check policies
+    a1pms_api_get_policy 200 2000 testdata/OSC/pi1_template.json "service1" ricsim_g1_1 1 false $notificationurl
+    a1pms_api_get_policy 200 3000 testdata/OSC/pi1_template.json "service1" ricsim_g1_1 1 false $notificationurl
+    a1pms_api_get_policy 200 2100 testdata/STD/pi1_template.json "service1" ricsim_g2_1 NOTYPE false $notificationurl
+    a1pms_api_get_policy 200 3100 testdata/STD/pi1_template.json "service1" ricsim_g2_1 NOTYPE false $notificationurl
+    a1pms_api_get_policy 200 2200 testdata/STD2/pi_qos_template.json "service1" ricsim_g3_1 STD_QOS_0_2_0 true $notificationurl
+    a1pms_api_get_policy 200 3200 testdata/STD2/pi_qos_template.json "service1" ricsim_g3_1 STD_QOS_0_2_0 true $notificationurl
+  fi
+
+  sim_equal ricsim_g1_1 num_instances 2
+  sim_equal ricsim_g2_1 num_instances 2
+
+  sim_equal ricsim_g3_1 num_instances 2
+
+  # Remove policies
+
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      use_a1pms_rest_http
+  else
+      use_a1pms_dmaap_http
+  fi
+  a1pms_api_delete_policy 204 2000
+  use_a1pms_rest_http
+  a1pms_api_delete_policy 204 3000
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      use_a1pms_rest_http
+  else
+      use_a1pms_dmaap_http
+  fi
+  a1pms_api_delete_policy 204 2100
+  use_a1pms_rest_http
+  a1pms_api_delete_policy 204 3100
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      use_a1pms_rest_http
+  else
+      use_a1pms_dmaap_http
+  fi
+  a1pms_api_delete_policy 204 2200
+  use_a1pms_rest_http
+  a1pms_api_delete_policy 204 3200
+
+  sim_equal ricsim_g1_1 num_instances 0
+  sim_equal ricsim_g2_1 num_instances 0
+
+  sim_equal ricsim_g3_1 num_instances 0
+
+  # Check remote host access to simulator
+
+  sim_contains_str ricsim_g1_1 remote_hosts $A1PMS_APP_NAME
+  sim_contains_str ricsim_g2_1 remote_hosts $A1PMS_APP_NAME
+  sim_contains_str ricsim_g3_1 remote_hosts $A1PMS_APP_NAME
+
+  # Check policy removal
+  use_a1pms_rest_http
+  a1pms_api_get_policy 404 2000
+  a1pms_api_get_policy 404 3000
+  a1pms_api_get_policy 404 2100
+  a1pms_api_get_policy 404 3100
+
+  a1pms_api_get_policy 404 2200
+  a1pms_api_get_policy 404 3200
+
+  # Remove the service
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      use_a1pms_rest_http
+  else
+      use_a1pms_dmaap_http
+  fi
+  a1pms_api_delete_services 204 "service1"
+
+  a1pms_api_get_services 404 "service1"
+
+  check_a1pms_logs
+done
+  #### TEST COMPLETE ####
 
 store_logs          END
 
 print_result
 
-auto_clean_environment
\ No newline at end of file
+auto_clean_environment
index f048cdb..c034e71 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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.
@@ -40,7 +41,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
@@ -80,538 +81,636 @@ else
     TESTED_PROTOCOLS="HTTP"
 fi
 
-for __httpx in $TESTED_PROTOCOLS ; do
-    for interface in $TESTED_VARIANTS ; do
+VERSIONS_TO_RUN=2
 
-        echo "#####################################################################"
-        echo "#####################################################################"
-        echo "### Testing a1pms: $interface using $__httpx"
-        echo "#####################################################################"
-        echo "#####################################################################"
-
-        # Clean container and start all needed containers #
-        clean_environment
-
-        if [ $RUNMODE != "KUBE" ]; then
-            USE_ISTIO=0
-            echo "ISTIO not supported by docker - setting USE-ISTIO=0"
-        fi
-
-        if [ $USE_ISTIO -eq 1 ]; then
-            echo -e $RED"#########################################"$ERED
-            echo -e $RED"# Work around istio jwks cache"$ERED
-            echo -e $RED"# Cycle istiod down and up to clear cache"$ERED
-            echo ""
-            __kube_scale deployment istiod istio-system 0
-            __kube_scale deployment istiod istio-system 1
-            echo -e $RED"# Cycle istiod done"
-            echo -e $RED"#########################################"$ERED
-
-            istio_enable_istio_namespace $KUBE_SIM_NAMESPACE
-            istio_enable_istio_namespace $KUBE_NONRTRIC_NAMESPACE
-            istio_enable_istio_namespace $KUBE_A1SIM_NAMESPACE
-        fi
-
-
-        start_kube_proxy
-
-        if [ $USE_ISTIO -eq 1 ]; then
-            start_keycloak
-
-            keycloak_api_obtain_admin_token
-
-            keycloak_api_create_realm                   nrtrealm   true   60
-            keycloak_api_create_confidential_client     nrtrealm   a1pmsc
-            keycloak_api_generate_client_secret         nrtrealm   a1pmsc
-            keycloak_api_get_client_secret              nrtrealm   a1pmsc
-            keycloak_api_create_client_roles            nrtrealm   a1pmsc nrtrole
-            keycloak_api_map_client_roles               nrtrealm   a1pmsc nrtrole
-
-            keycloak_api_get_client_token               nrtrealm   a1pmsc
-
-            CLIENT_TOKEN=$(keycloak_api_read_client_token nrtrealm   a1pmsc)
-            echo "CLIENT_TOKEN: "$CLIENT_TOKEN
+if [ -n "$A1PMS_V3_FLAG" ] && [ "${A1PMS_V3_FLAG,,}" == "true" ]; then
+  VERSIONS_TO_RUN=3
+fi
 
-            A1PMS_SEC=$(keycloak_api_read_client_secret nrtrealm   a1pmsc)
-            echo "A1PMS_SEC: "$A1PMS_SEC
+for version in $(seq 2 $VERSIONS_TO_RUN); do
+  if [ "$version" == "3" ]; then
+    if [ -n "$A1PMS_V3" ] && [ -n "$A1PMS_API_PREFIX_V3" ] && [ -n "$A1PMS_ALIVE_URL_V3" ]; then
+      export A1PMS_VERSION="$A1PMS_V3"
+      export A1PMS_API_PREFIX="$A1PMS_API_PREFIX_V3"
+      export A1PMS_ALIVE_URL="$A1PMS_API_PREFIX$A1PMS_ALIVE_URL_V3"
+    else
+      echo "One/All parameters not set in env file (<A1PMS_V3>, <A1PMS_API_PREFIX_V3>, <A1PMS_ALIVE_URL_V3>)"
+      break
+    fi
+  fi
+  for __httpx in $TESTED_PROTOCOLS ; do
+      for interface in $TESTED_VARIANTS ; do
 
-            # Protect ricsim-g3
-            istio_req_auth_by_jwks              ricsim-g1 $KUBE_A1SIM_NAMESPACE KUBEPROXY "$KUBE_PROXY_ISTIO_JWKS_KEYS"
-            istio_auth_policy_by_issuer         ricsim-g1 $KUBE_A1SIM_NAMESPACE KUBEPROXY
+          echo "#####################################################################"
+          echo "#####################################################################"
+          echo "### Testing a1pms: ${interface} and ${__httpx} with a1pms V${version} "
+          echo "#####################################################################"
+          echo "#####################################################################"
 
-            istio_req_auth_by_jwksuri           ricsim-g1 $KUBE_A1SIM_NAMESPACE nrtrealm
-            istio_auth_policy_by_realm          ricsim-g1 $KUBE_A1SIM_NAMESPACE nrtrealm a1pmsc nrtrole
+          # Clean container and start all needed containers #
+          clean_environment
 
-            # Protect ricsim-g2
-            istio_req_auth_by_jwks              ricsim-g2 $KUBE_A1SIM_NAMESPACE KUBEPROXY "$KUBE_PROXY_ISTIO_JWKS_KEYS"
-            istio_auth_policy_by_issuer         ricsim-g2 $KUBE_A1SIM_NAMESPACE KUBEPROXY
+          if [ $RUNMODE != "KUBE" ]; then
+              USE_ISTIO=0
+              echo "ISTIO not supported by docker - setting USE-ISTIO=0"
+          fi
+
+          if [ $USE_ISTIO -eq 1 ]; then
+              echo -e $RED"#########################################"$ERED
+              echo -e $RED"# Work around istio jwks cache"$ERED
+              echo -e $RED"# Cycle istiod down and up to clear cache"$ERED
+              echo ""
+              __kube_scale deployment istiod istio-system 0
+              __kube_scale deployment istiod istio-system 1
+              echo -e $RED"# Cycle istiod done"
+              echo -e $RED"#########################################"$ERED
+
+              istio_enable_istio_namespace $KUBE_SIM_NAMESPACE
+              istio_enable_istio_namespace $KUBE_NONRTRIC_NAMESPACE
+              istio_enable_istio_namespace $KUBE_A1SIM_NAMESPACE
+          fi
+
+
+          start_kube_proxy
+
+          if [ $USE_ISTIO -eq 1 ]; then
+              start_keycloak
+
+              keycloak_api_obtain_admin_token
+
+              keycloak_api_create_realm                   nrtrealm   true   60
+              keycloak_api_create_confidential_client     nrtrealm   a1pmsc
+              keycloak_api_generate_client_secret         nrtrealm   a1pmsc
+              keycloak_api_get_client_secret              nrtrealm   a1pmsc
+              keycloak_api_create_client_roles            nrtrealm   a1pmsc nrtrole
+              keycloak_api_map_client_roles               nrtrealm   a1pmsc nrtrole
+
+              keycloak_api_get_client_token               nrtrealm   a1pmsc
+
+              CLIENT_TOKEN=$(keycloak_api_read_client_token nrtrealm   a1pmsc)
+              echo "CLIENT_TOKEN: "$CLIENT_TOKEN
+
+              A1PMS_SEC=$(keycloak_api_read_client_secret nrtrealm   a1pmsc)
+              echo "A1PMS_SEC: "$A1PMS_SEC
+
+              # Protect ricsim-g3
+              istio_req_auth_by_jwks              ricsim-g1 $KUBE_A1SIM_NAMESPACE KUBEPROXY "$KUBE_PROXY_ISTIO_JWKS_KEYS"
+              istio_auth_policy_by_issuer         ricsim-g1 $KUBE_A1SIM_NAMESPACE KUBEPROXY
+
+              istio_req_auth_by_jwksuri           ricsim-g1 $KUBE_A1SIM_NAMESPACE nrtrealm
+              istio_auth_policy_by_realm          ricsim-g1 $KUBE_A1SIM_NAMESPACE nrtrealm a1pmsc nrtrole
+
+              # Protect ricsim-g2
+              istio_req_auth_by_jwks              ricsim-g2 $KUBE_A1SIM_NAMESPACE KUBEPROXY "$KUBE_PROXY_ISTIO_JWKS_KEYS"
+              istio_auth_policy_by_issuer         ricsim-g2 $KUBE_A1SIM_NAMESPACE KUBEPROXY
+
+              istio_req_auth_by_jwksuri           ricsim-g2 $KUBE_A1SIM_NAMESPACE nrtrealm
+              istio_auth_policy_by_realm          ricsim-g2 $KUBE_A1SIM_NAMESPACE nrtrealm a1pmsc nrtrole
+
+              # Protect ricsim-g3
+              istio_req_auth_by_jwks              ricsim-g3 $KUBE_A1SIM_NAMESPACE KUBEPROXY "$KUBE_PROXY_ISTIO_JWKS_KEYS"
+              istio_auth_policy_by_issuer         ricsim-g3 $KUBE_A1SIM_NAMESPACE KUBEPROXY
+
+              istio_req_auth_by_jwksuri           ricsim-g3 $KUBE_A1SIM_NAMESPACE nrtrealm
+              istio_auth_policy_by_realm          ricsim-g3 $KUBE_A1SIM_NAMESPACE nrtrealm a1pmsc nrtrole
+
+              # Protect CR
+              istio_req_auth_by_jwks              $CR_APP_NAME $KUBE_SIM_NAMESPACE KUBEPROXY "$KUBE_PROXY_ISTIO_JWKS_KEYS"
+              istio_auth_policy_by_issuer         $CR_APP_NAME $KUBE_SIM_NAMESPACE KUBEPROXY
+
+              istio_req_auth_by_jwksuri           $CR_APP_NAME $KUBE_SIM_NAMESPACE nrtrealm
+              istio_auth_policy_by_realm          $CR_APP_NAME $KUBE_SIM_NAMESPACE nrtrealm a1pmsc nrtrole
+
+              a1pms_configure_sec nrtrealm a1pmsc $A1PMS_SEC
+          fi
+
+          if [ $__httpx == "HTTPS" ]; then
+              use_cr_https
+              use_a1pms_rest_https
+          else
+              use_a1pms_rest_http
+              use_cr_http
+          fi
+
+          start_a1pms NORPOXY $SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_CONFIG_FILE
+
+          set_a1pms_debug
+
+          # Create service to be able to receive events when rics becomes available
+          # Must use rest towards the a1pms since dmaap is not configured yet
+          a1pms_api_put_service 201 "ric-registration" 0 "$CR_SERVICE_APP_PATH_0/ric-registration"
+
+
+          if [ $__httpx == "HTTPS" ]; then
+              use_simulator_https
+              use_mr_https
+              if [[ $interface = *"SDNC"* ]]; then
+                  if [[ "$SDNC_FEATURE_LEVEL" == *"NO_NB_HTTPS"* ]]; then
+                      deviation "SDNC does not support NB https"
+                      use_sdnc_http
+                  else
+                      use_sdnc_https
+                  fi
+              fi
+              if [[ $interface = *"DMAAP"* ]]; then
+                  use_a1pms_dmaap_https
+              else
+                  use_a1pms_rest_https
+              fi
+          else
+              use_simulator_http
+              use_mr_http
+              if [[ $interface = *"SDNC"* ]]; then
+                  use_sdnc_http
+              fi
+              if [[ $interface = *"DMAAP"* ]]; then
+                  use_a1pms_dmaap_http
+              else
+                  use_a1pms_rest_http
+              fi
+          fi
+
+          start_ric_simulators ricsim_g1 1  OSC_2.1.0
+          start_ric_simulators ricsim_g2 1  STD_1.1.3
+
+          sim_put_policy_type 201 ricsim_g1_1 1 testdata/OSC/sim_1.json
+          sim_put_policy_type 201 ricsim_g1_1 2 testdata/OSC/sim_2.json
+
+          start_ric_simulators ricsim_g3 1  STD_2.0.0
+          sim_put_policy_type 201 ricsim_g3_1 STD_QOS_0_2_0 testdata/STD2/sim_qos.json
+          sim_put_policy_type 201 ricsim_g3_1 STD_QOS2_0.1.0 testdata/STD2/sim_qos2.json
+
+          if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+              :
+          else
+              start_mr
+          fi
+
+          start_cr 1
+
+          start_control_panel $SIM_GROUP/$CONTROL_PANEL_COMPOSE_DIR/$CONTROL_PANEL_CONFIG_FILE
 
-            istio_req_auth_by_jwksuri           ricsim-g2 $KUBE_A1SIM_NAMESPACE nrtrealm
-            istio_auth_policy_by_realm          ricsim-g2 $KUBE_A1SIM_NAMESPACE nrtrealm a1pmsc nrtrole
+          if [ ! -z "$NRT_GATEWAY_APP_NAME" ]; then
+              start_gateway $SIM_GROUP/$NRT_GATEWAY_COMPOSE_DIR/$NRT_GATEWAY_CONFIG_FILE
+          fi
 
-            # Protect ricsim-g3
-            istio_req_auth_by_jwks              ricsim-g3 $KUBE_A1SIM_NAMESPACE KUBEPROXY "$KUBE_PROXY_ISTIO_JWKS_KEYS"
-            istio_auth_policy_by_issuer         ricsim-g3 $KUBE_A1SIM_NAMESPACE KUBEPROXY
 
-            istio_req_auth_by_jwksuri           ricsim-g3 $KUBE_A1SIM_NAMESPACE nrtrealm
-            istio_auth_policy_by_realm          ricsim-g3 $KUBE_A1SIM_NAMESPACE nrtrealm a1pmsc nrtrole
+          if [[ $interface = *"SDNC"* ]]; then
+              start_sdnc
+              controller_api_wait_for_status_ok 200 ricsim_g1_1
+              prepare_a1pms_config      SDNC    ".a1pms_config.json"
+          else
+              prepare_a1pms_config      NOSDNC  ".a1pms_config.json"
+          fi
 
-            # Protect CR
-            istio_req_auth_by_jwks              $CR_APP_NAME $KUBE_SIM_NAMESPACE KUBEPROXY "$KUBE_PROXY_ISTIO_JWKS_KEYS"
-            istio_auth_policy_by_issuer         $CR_APP_NAME $KUBE_SIM_NAMESPACE KUBEPROXY
+          if [ $RUNMODE == "KUBE" ]; then
+              a1pms_load_config                       ".a1pms_config.json"
+          else
+              #Temporary switch to http/https if dmaap use. Otherwise it is not possible to push config
+              if [ $__httpx == "HTTPS" ]; then
+                  use_a1pms_rest_https
+              else
+                  use_a1pms_rest_http
+              fi
 
-            istio_req_auth_by_jwksuri           $CR_APP_NAME $KUBE_SIM_NAMESPACE nrtrealm
-            istio_auth_policy_by_realm          $CR_APP_NAME $KUBE_SIM_NAMESPACE nrtrealm a1pmsc nrtrole
+              if [[ $interface != *"DMAAP"* ]]; then
+                  echo "{}" > ".a1pms_config_incorrect.json"
+                  a1pms_api_put_configuration 400 ".a1pms_config_incorrect.json"
+              fi
 
-            a1pms_configure_sec nrtrealm a1pmsc $A1PMS_SEC
-        fi
+              a1pms_api_put_configuration 200 ".a1pms_config.json"
+              a1pms_api_get_configuration 200 ".a1pms_config.json"
+              if [ $__httpx == "HTTPS" ]; then
+                  if [[ $interface = *"DMAAP"* ]]; then
+                      use_a1pms_dmaap_https
+                  else
+                      use_a1pms_rest_https
+                  fi
+              else
+                  if [[ $interface = *"DMAAP"* ]]; then
+                      use_a1pms_dmaap_http
+                  else
+                      use_a1pms_rest_http
+                  fi
+              fi
+          fi
 
-        if [ $__httpx == "HTTPS" ]; then
-            use_cr_https
-            use_a1pms_rest_https
-        else
-            use_a1pms_rest_http
-            use_cr_http
-        fi
+          a1pms_equal json:rics 3 300
 
-        start_a1pms NORPOXY $SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_CONFIG_FILE
+          if [ "$A1PMS_VERSION" == "V2" ]; then
+            a1pms_equal json:policy-types 5 120  #Wait for the a1pms to refresh types from the simulator
+          elif [ "$A1PMS_VERSION" == "V3" ]; then
+            a1pms_equal json:policytypes 5 120  #Wait for the a1pms to refresh types from the simulator
+          fi
 
-        set_a1pms_debug
+          a1pms_equal json:policies 0
 
-        # Create service to be able to receive events when rics becomes available
-        # Must use rest towards the a1pms since dmaap is not configured yet
-        a1pms_api_put_service 201 "ric-registration" 0 "$CR_SERVICE_APP_PATH_0/ric-registration"
+          if [ "$A1PMS_VERSION" == "V2" ]; then
+            a1pms_equal json:policy-instances 0
+          fi
 
+          cr_equal 0 received_callbacks 3 120
+          cr_api_check_all_sync_events 200 0 ric-registration ricsim_g1_1 ricsim_g2_1 ricsim_g3_1
 
-        if [ $__httpx == "HTTPS" ]; then
-            use_simulator_https
-            use_mr_https
-            if [[ $interface = *"SDNC"* ]]; then
-                if [[ "$SDNC_FEATURE_LEVEL" == *"NO_NB_HTTPS"* ]]; then
-                    deviation "SDNC does not support NB https"
-                    use_sdnc_http
-                else
-                    use_sdnc_https
-                fi
-            fi
-            if [[ $interface = *"DMAAP"* ]]; then
-                use_a1pms_dmaap_https
-            else
-                use_a1pms_rest_https
-            fi
-        else
-            use_simulator_http
-            use_mr_http
-            if [[ $interface = *"SDNC"* ]]; then
-                use_sdnc_http
-            fi
-            if [[ $interface = *"DMAAP"* ]]; then
-                use_a1pms_dmaap_http
-            else
-                use_a1pms_rest_http
-            fi
-        fi
+          if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+              :
+          else
+              mr_equal requests_submitted 0
+          fi
 
-        start_ric_simulators ricsim_g1 1  OSC_2.1.0
-        start_ric_simulators ricsim_g2 1  STD_1.1.3
 
-        sim_put_policy_type 201 ricsim_g1_1 1 testdata/OSC/sim_1.json
-        sim_put_policy_type 201 ricsim_g1_1 2 testdata/OSC/sim_2.json
+          echo "############################################"
+          echo "############## Health check ################"
+          echo "############################################"
 
-        start_ric_simulators ricsim_g3 1  STD_2.0.0
-        sim_put_policy_type 201 ricsim_g3_1 STD_QOS_0_2_0 testdata/STD2/sim_qos.json
-        sim_put_policy_type 201 ricsim_g3_1 STD_QOS2_0.1.0 testdata/STD2/sim_qos2.json
+          sleep_wait 120 "Let A1PMS configuration take effect"
 
-        if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-            :
-        else
-            start_mr
-        fi
+          a1pms_api_get_status 200
 
-        start_cr 1
+          a1pms_api_get_status_root 200
 
-        start_control_panel $SIM_GROUP/$CONTROL_PANEL_COMPOSE_DIR/$CONTROL_PANEL_CONFIG_FILE
+          echo "############################################"
+          echo "##### Service registry and supervision #####"
+          echo "############################################"
 
-        if [ ! -z "$NRT_GATEWAY_APP_NAME" ]; then
-            start_gateway $SIM_GROUP/$NRT_GATEWAY_COMPOSE_DIR/$NRT_GATEWAY_CONFIG_FILE
-        fi
+          a1pms_api_get_services 404 "service1"
 
+          a1pms_api_put_service 201 "service1" 1000 "$CR_SERVICE_APP_PATH_0/1"
 
-        if [[ $interface = *"SDNC"* ]]; then
-            start_sdnc
-            controller_api_wait_for_status_ok 200 ricsim_g1_1
-            prepare_a1pms_config      SDNC    ".a1pms_config.json"
-        else
-            prepare_a1pms_config      NOSDNC  ".a1pms_config.json"
-        fi
+          a1pms_api_put_service 200 "service1" 2000 "$CR_SERVICE_APP_PATH_0/1"
 
-        if [ $RUNMODE == "KUBE" ]; then
-            a1pms_load_config                       ".a1pms_config.json"
-        else
-            #Temporary switch to http/https if dmaap use. Otherwise it is not possible to push config
-            if [ $__httpx == "HTTPS" ]; then
-                use_a1pms_rest_https
-            else
-                use_a1pms_rest_http
-            fi
 
-            if [[ $interface != *"DMAAP"* ]]; then
-                echo "{}" > ".a1pms_config_incorrect.json"
-                a1pms_api_put_configuration 400 ".a1pms_config_incorrect.json"
-            fi
+          a1pms_api_put_service 400 "service2" -1 "$CR_SERVICE_APP_PATH_0/2"
 
-            a1pms_api_put_configuration 200 ".a1pms_config.json"
-            a1pms_api_get_configuration 200 ".a1pms_config.json"
-            if [ $__httpx == "HTTPS" ]; then
-                if [[ $interface = *"DMAAP"* ]]; then
-                    use_a1pms_dmaap_https
-                else
-                    use_a1pms_rest_https
-                fi
-            else
-                if [[ $interface = *"DMAAP"* ]]; then
-                    use_a1pms_dmaap_http
-                else
-                    use_a1pms_rest_http
-                fi
-            fi
-        fi
+          a1pms_api_put_service 400 "service2" "wrong" "$CR_SERVICE_APP_PATH_0/2"
 
-        a1pms_equal json:rics 3 300
+          a1pms_api_put_service 400 "service2" 100 "/test"
 
-        a1pms_equal json:policy-types 5 120
+          a1pms_api_put_service 400 "service2" 100 "test-path"
 
-        a1pms_equal json:policies 0
+          a1pms_api_put_service 201 "service2" 300 "ftp://localhost:80/test"
 
-        a1pms_equal json:policy-instances 0
+          a1pms_api_get_services 200 "service1" "service1" 2000 "$CR_SERVICE_APP_PATH_0/1"
 
-        cr_equal 0 received_callbacks 3 120
-        cr_api_check_all_sync_events 200 0 ric-registration ricsim_g1_1 ricsim_g2_1 ricsim_g3_1
+          a1pms_api_get_service_ids 200 "service1" "service2" "ric-registration"
 
-        if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-            :
-        else
-            mr_equal requests_submitted 0
-        fi
+          a1pms_api_put_service 201 "service3" 5000 "$CR_SERVICE_APP_PATH_0/3"
 
 
-        echo "############################################"
-        echo "############## Health check ################"
-        echo "############################################"
+          a1pms_api_get_service_ids 200 "service1" "service2" "service3" "ric-registration"
 
-        sleep_wait 120 "Let A1PMS configuration take effect"
 
-        a1pms_api_get_status 200
+          a1pms_api_get_services 200 "service1" "service1" 2000 "$CR_SERVICE_APP_PATH_0/1"
 
-        a1pms_api_get_status_root 200
+          a1pms_api_get_services 200 NOSERVICE "service1" 2000 "$CR_SERVICE_APP_PATH_0/1" "service2" 300 "ftp://localhost:80/test" "service3" 5000 "$CR_SERVICE_APP_PATH_0/3"  "ric-registration" 0 "$CR_SERVICE_APP_PATH_0/ric-registration"
 
-        echo "############################################"
-        echo "##### Service registry and supervision #####"
-        echo "############################################"
+          a1pms_api_get_services 200
 
-        a1pms_api_get_services 404 "service1"
+          if [ "$A1PMS_VERSION" == "V2" ]; then
+            deviation "TR2 - Keep alive shall return 200/201 according to doc, only 200 works - test combo $interface and $__httpx"
+            #The below should work, kept here until fixed or other decision made
+            #a1pms_api_put_services_keepalive 201 "service1"
+            #Using the below until decision
+            a1pms_api_put_services_keepalive 200 "service1"
 
-        a1pms_api_put_service 201 "service1" 1000 "$CR_SERVICE_APP_PATH_0/1"
+            deviation "TR2 - Keep alive shall return 200/201 according to doc, only 200 works - test combo $interface and $__httpx"
+            #The below should work, keept here until fixed or other decision made
+            #a1pms_api_put_services_keepalive 201 "service3"
+            #Using the below until decision
+            a1pms_api_put_services_keepalive 200 "service3"
 
-        a1pms_api_put_service 200 "service1" 2000 "$CR_SERVICE_APP_PATH_0/1"
+            a1pms_api_put_services_keepalive 200 "service1"
 
+            a1pms_api_put_services_keepalive 200 "service3"
 
-        a1pms_api_put_service 400 "service2" -1 "$CR_SERVICE_APP_PATH_0/2"
+            a1pms_api_put_services_keepalive 404 "service5"
+          fi
 
-        a1pms_api_put_service 400 "service2" "wrong" "$CR_SERVICE_APP_PATH_0/2"
+          a1pms_api_get_service_ids 200 "service1" "service2" "service3"  "ric-registration"
 
-        a1pms_api_put_service 400 "service2" 100 "/test"
+          a1pms_api_delete_services 204 "service1"
 
-        a1pms_api_put_service 400 "service2" 100 "test-path"
+          a1pms_api_get_service_ids 200 "service2" "service3" "ric-registration"
 
-        a1pms_api_put_service 201 "service2" 300 "ftp://localhost:80/test"
 
-        a1pms_api_get_services 200 "service1" "service1" 2000 "$CR_SERVICE_APP_PATH_0/1"
+          a1pms_api_put_service 201 "service1" 50 "$CR_SERVICE_APP_PATH_0/1"
 
-        a1pms_api_get_service_ids 200 "service1" "service2" "ric-registration"
+          a1pms_api_get_service_ids 200 "service1" "service2" "service3"  "ric-registration"
 
 
-        a1pms_api_put_service 201 "service3" 5000 "$CR_SERVICE_APP_PATH_0/3"
+          a1pms_api_delete_services 204 "service1"
+          a1pms_api_delete_services 204 "service3"
 
+          a1pms_equal json:services 2
 
-        a1pms_api_get_service_ids 200 "service1" "service2" "service3" "ric-registration"
+          a1pms_api_delete_services 204 "service2"
 
+          a1pms_equal json:services 1
 
-        a1pms_api_get_services 200 "service1" "service1" 2000 "$CR_SERVICE_APP_PATH_0/1"
+          echo "############################################"
+          echo "############## RIC Repository ##############"
+          echo "############################################"
 
-        a1pms_api_get_services 200 NOSERVICE "service1" 2000 "$CR_SERVICE_APP_PATH_0/1" "service2" 300 "ftp://localhost:80/test" "service3" 5000 "$CR_SERVICE_APP_PATH_0/3"  "ric-registration" 0 "$CR_SERVICE_APP_PATH_0/ric-registration"
+          a1pms_api_get_rics 200 NOTYPE "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:1,2:AVAILABLE  ricsim_g2_1:me1_ricsim_g2_1,me2_ricsim_g2_1:EMPTYTYPE:AVAILABLE ricsim_g3_1:me1_ricsim_g3_1,me2_ricsim_g3_1:STD_QOS_0_2_0,STD_QOS2_0.1.0:AVAILABLE"
 
-        a1pms_api_get_services 200
+          a1pms_api_get_rics 200 1 "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:1,2:AVAILABLE"
 
-        deviation "TR2 - Keep alive shall return 200/201 according to doc, only 200 works - test combo $interface and $__httpx"
-        #The below should work, keept here until fixed or other decision made
-        #a1pms_api_put_services_keepalive 201 "service1"
-        #Using the below until decision
-        a1pms_api_put_services_keepalive 200 "service1"
+          a1pms_api_get_rics 404 47
 
-        deviation "TR2 - Keep alive shall return 200/201 according to doc, only 200 works - test combo $interface and $__httpx"
-        #The below should work, keept here until fixed or other decision made
-        #a1pms_api_put_services_keepalive 201 "service3"
-        #Using the below until decision
-        a1pms_api_put_services_keepalive 200 "service3"
+          a1pms_api_get_rics 404 "test"
 
-        a1pms_api_put_services_keepalive 200 "service1"
+          a1pms_api_get_ric 200 me1_ricsim_g1_1 NORIC "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:1,2:AVAILABLE"
 
-        a1pms_api_put_services_keepalive 200 "service3"
+          a1pms_api_get_ric 200 me2_ricsim_g1_1 NORIC "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:1,2:AVAILABLE"
 
-        a1pms_api_put_services_keepalive 404 "service5"
+          a1pms_api_get_ric 200 me1_ricsim_g2_1 NORIC "ricsim_g2_1:me1_ricsim_g2_1,me2_ricsim_g2_1:EMPTYTYPE:AVAILABLE"
 
-        a1pms_api_get_service_ids 200 "service1" "service2" "service3"  "ric-registration"
+          a1pms_api_get_ric 200 me2_ricsim_g2_1 NORIC "ricsim_g2_1:me1_ricsim_g2_1,me2_ricsim_g2_1:EMPTYTYPE:AVAILABLE"
 
-        a1pms_api_delete_services 204 "service1"
+          a1pms_api_get_ric 200 me1_ricsim_g3_1 NORIC "ricsim_g3_1:me1_ricsim_g3_1,me2_ricsim_g3_1:STD_QOS_0_2_0,STD_QOS2_0.1.0:AVAILABLE"
 
-        a1pms_api_get_service_ids 200 "service2" "service3" "ric-registration"
+          a1pms_api_get_ric 200 me2_ricsim_g3_1 NORIC "ricsim_g3_1:me1_ricsim_g3_1,me2_ricsim_g3_1:STD_QOS_0_2_0,STD_QOS2_0.1.0:AVAILABLE"
 
+          a1pms_api_get_ric 200 NOME      ricsim_g1_1 "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:1,2:AVAILABLE"
 
-        a1pms_api_put_service 201 "service1" 50 "$CR_SERVICE_APP_PATH_0/1"
+          a1pms_api_get_ric 200 NOME      ricsim_g2_1 "ricsim_g2_1:me1_ricsim_g2_1,me2_ricsim_g2_1:EMPTYTYPE:AVAILABLE"
 
-        a1pms_api_get_service_ids 200 "service1" "service2" "service3"  "ric-registration"
+          a1pms_api_get_ric 200 NOME      ricsim_g3_1 "ricsim_g3_1:me1_ricsim_g3_1,me2_ricsim_g3_1:STD_QOS_0_2_0,STD_QOS2_0.1.0:AVAILABLE"
 
+          a1pms_api_get_ric 404 NOME test1
 
-        a1pms_api_delete_services 204 "service1"
-        a1pms_api_delete_services 204 "service3"
+          a1pms_api_get_ric 404 test NORIC
 
-        a1pms_equal json:services 2
+          a1pms_api_get_ric 400 me1_ricsim_g1_1 ricsim_g1_1
 
-        a1pms_api_delete_services 204 "service2"
+          a1pms_api_get_ric 400 me1_ricsim_g1_1 TESTRIC
 
-        a1pms_equal json:services 1
+          a1pms_api_get_ric 400 TESTME ricsim_g1_1
 
+          echo "############################################"
+          echo "########### A1 Policy Management ###########"
+          echo "############################################"
 
-        echo "############################################"
-        echo "############## RIC Repository ##############"
-        echo "############################################"
+          deviation "TR9 - a1pms modify the type with type id - test combo $interface and $__httpx"
+          #Behaviour accepted for now
+          a1pms_api_get_policy_type 200 1 testdata/OSC/1-a1pms-modified.json
+          deviation "TR9 - a1pms modify the type with type id - test combo $interface and $__httpx"
+          #Behaviour accepted for now
+          a1pms_api_get_policy_type 200 2 testdata/OSC/2-a1pms-modified.json
+          deviation "TR9 - a1pms modify the type with type id - test combo $interface and $__httpx"
+          #Behaviour accepted for now
+          a1pms_api_get_policy_type 200 STD_QOS_0_2_0 testdata/STD2/qos-a1pms-modified.json
+          deviation "TR9 - a1pms modify the type with type id - test combo $interface and $__httpx"
+          #Behaviour accepted for now
+          a1pms_api_get_policy_type 200 STD_QOS2_0.1.0 testdata/STD2/qos2-a1pms-modified.json
 
-        a1pms_api_get_rics 200 NOTYPE "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:1,2:AVAILABLE  ricsim_g2_1:me1_ricsim_g2_1,me2_ricsim_g2_1:EMPTYTYPE:AVAILABLE ricsim_g3_1:me1_ricsim_g3_1,me2_ricsim_g3_1:STD_QOS_0_2_0,STD_QOS2_0.1.0:AVAILABLE"
+          a1pms_api_get_policy_type 404 3
+          if [ "$A1PMS_VERSION" != "V3" ]; then
+            a1pms_api_get_policy_schemas 404
 
-        a1pms_api_get_rics 200 1 "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:1,2:AVAILABLE"
+            a1pms_api_get_policy_types 200 NORIC 1 2 EMPTY STD_QOS_0_2_0 STD_QOS2_0.1.0
 
-        a1pms_api_get_rics 404 47
+            a1pms_api_get_policy_types 200 ricsim_g1_1 1 2
 
-        a1pms_api_get_rics 404 "test"
+            a1pms_api_get_policy_types 200 ricsim_g2_1 EMPTY
 
-        a1pms_api_get_ric 200 me1_ricsim_g1_1 NORIC "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:1,2:AVAILABLE"
+            a1pms_api_get_policy_types 200 ricsim_g3_1 STD_QOS_0_2_0 STD_QOS2_0.1.0
 
-        a1pms_api_get_ric 200 me2_ricsim_g1_1 NORIC "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:1,2:AVAILABLE"
+            a1pms_api_get_policy_types 404 dummy-ric
+          fi
 
-        a1pms_api_get_ric 200 me1_ricsim_g2_1 NORIC "ricsim_g2_1:me1_ricsim_g2_1,me2_ricsim_g2_1:EMPTYTYPE:AVAILABLE"
+          if [ "$A1PMS_VERSION" == "V3" ]; then
 
-        a1pms_api_get_ric 200 me2_ricsim_g2_1 NORIC "ricsim_g2_1:me1_ricsim_g2_1,me2_ricsim_g2_1:EMPTYTYPE:AVAILABLE"
+            a1pms_api_get_policy_types_v3 200 NORIC 1:ricsim_g1_1 2:ricsim_g1_1 EMPTY:ricsim_g2_1 STD_QOS_0_2_0:ricsim_g3_1 STD_QOS2_0.1.0:ricsim_g3_1
 
-        a1pms_api_get_ric 200 me1_ricsim_g3_1 NORIC "ricsim_g3_1:me1_ricsim_g3_1,me2_ricsim_g3_1:STD_QOS_0_2_0,STD_QOS2_0.1.0:AVAILABLE"
+            a1pms_api_get_policy_types_v3 200 ricsim_g1_1 1:ricsim_g1_1 2:ricsim_g1_1
 
-        a1pms_api_get_ric 200 me2_ricsim_g3_1 NORIC "ricsim_g3_1:me1_ricsim_g3_1,me2_ricsim_g3_1:STD_QOS_0_2_0,STD_QOS2_0.1.0:AVAILABLE"
+            a1pms_api_get_policy_types_v3 200 ricsim_g2_1 EMPTY:ricsim_g2_1
 
-        a1pms_api_get_ric 200 NOME      ricsim_g1_1 "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:1,2:AVAILABLE"
+            a1pms_api_get_policy_types_v3 200 ricsim_g3_1 STD_QOS_0_2_0:ricsim_g3_1 STD_QOS2_0.1.0:ricsim_g3_1
 
-        a1pms_api_get_ric 200 NOME      ricsim_g2_1 "ricsim_g2_1:me1_ricsim_g2_1,me2_ricsim_g2_1:EMPTYTYPE:AVAILABLE"
+            a1pms_api_get_policy_types_v3 404 dummy-ric
 
-        a1pms_api_get_ric 200 NOME      ricsim_g3_1 "ricsim_g3_1:me1_ricsim_g3_1,me2_ricsim_g3_1:STD_QOS_0_2_0,STD_QOS2_0.1.0:AVAILABLE"
+            a1pms_api_post_policy_v3 201 "unregistered-service" ricsim_g1_1 1 2000 NOTRANSIENT NONOTIFYURL testdata/OSC/pi1_template.json
 
-        a1pms_api_get_ric 404 NOME test1
+            a1pms_api_post_policy_v3 201 "service10" ricsim_g1_1 1 5000 NOTRANSIENT NONOTIFYURL testdata/OSC/pi1_template.json
 
-        a1pms_api_get_ric 404 test NORIC
+            a1pms_api_post_policy_v3 201 NOSERVICE ricsim_g2_1 NOTYPE 5100 NOTRANSIENT NONOTIFYURL testdata/STD/pi1_template.json
 
-        a1pms_api_get_ric 400 me1_ricsim_g1_1 ricsim_g1_1
+            a1pms_api_post_policy_v3 201 NOSERVICE ricsim_g3_1 STD_QOS2_0.1.0 5200 NOTRANSIENT NONOTIFYURL testdata/STD2/pi_qos2_template.json
+          fi
 
-        a1pms_api_get_ric 400 me1_ricsim_g1_1 TESTRIC
+          a1pms_api_put_service 201 "service10" 3600 "$CR_SERVICE_APP_PATH_0/1"
 
-        a1pms_api_get_ric 400 TESTME ricsim_g1_1
+          notificationurl=$CR_SERVICE_APP_PATH_0"/test"
+          deviation "TR10 - a1pms allows policy creation on unregistered service (orig problem) - test combo $interface and $__httpx"
 
-        echo "############################################"
-        echo "########### A1 Policy Management ###########"
-        echo "############################################"
+          if [ "$A1PMS_VERSION" != "V3" ]; then
 
-        deviation "TR9 - a1pms modify the type with type id - test combo $interface and $__httpx"
-        #Behaviour accepted for now
-        a1pms_api_get_policy_type 200 1 testdata/OSC/1-a1pms-modified.json
-        deviation "TR9 - a1pms modify the type with type id - test combo $interface and $__httpx"
-        #Behaviour accepted for now
-        a1pms_api_get_policy_type 200 2 testdata/OSC/2-a1pms-modified.json
-        deviation "TR9 - a1pms modify the type with type id - test combo $interface and $__httpx"
-        #Behaviour accepted for now
-        a1pms_api_get_policy_type 200 STD_QOS_0_2_0 testdata/STD2/qos-a1pms-modified.json
-        deviation "TR9 - a1pms modify the type with type id - test combo $interface and $__httpx"
-        #Behaviour accepted for now
-        a1pms_api_get_policy_type 200 STD_QOS2_0.1.0 testdata/STD2/qos2-a1pms-modified.json
-
-        a1pms_api_get_policy_type 404 3
-
-        a1pms_api_get_policy_schemas 404
-
-
-        a1pms_api_get_policy_types 200 NORIC 1 2 EMPTY STD_QOS_0_2_0 STD_QOS2_0.1.0
-
-        a1pms_api_get_policy_types 200 ricsim_g1_1 1 2
-
-        a1pms_api_get_policy_types 200 ricsim_g2_1 EMPTY
-
-        a1pms_api_get_policy_types 200 ricsim_g3_1 STD_QOS_0_2_0 STD_QOS2_0.1.0
-
-        a1pms_api_get_policy_types 404 dummy-ric
-
-
-
-        a1pms_api_put_service 201 "service10" 3600 "$CR_SERVICE_APP_PATH_0/1"
-
-        notificationurl=$CR_SERVICE_APP_PATH_0"/test"
+            if [[ $interface != *"DMAAP"* ]]; then
+                # Badly formatted json is not possible to send via dmaap
+                a1pms_api_put_policy 400 "unregistered-service" ricsim_g1_1 1 2000 NOTRANSIENT $notificationurl testdata/OSC/pi_bad_template.json
+            fi
+            a1pms_api_put_policy 201 "unregistered-service" ricsim_g1_1 1 2000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
 
-        if [[ $interface != *"DMAAP"* ]]; then
-            # Badly formatted json is not possible to send via dmaap
-            a1pms_api_put_policy 400 "unregistered-service" ricsim_g1_1 1 2000 NOTRANSIENT $notificationurl testdata/OSC/pi_bad_template.json
-        fi
-        deviation "TR10 - a1pms allows policy creation on unregistered service (orig problem) - test combo $interface and $__httpx"
-        #Kept until decison
-        #a1pms_api_put_policy 400 "unregistered-service" ricsim_g1_1 1 2000 NOTRANSIENT testdata/OSC/pi1_template.json
-        #Allow 201 for now
-        a1pms_api_put_policy 201 "unregistered-service" ricsim_g1_1 1 2000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
+            a1pms_api_put_policy 201 "service10" ricsim_g1_1 1 5000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
+            a1pms_api_put_policy 200 "service10" ricsim_g1_1 1 5000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
 
-        a1pms_api_put_policy 201 "service10" ricsim_g1_1 1 5000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
-        a1pms_api_put_policy 200 "service10" ricsim_g1_1 1 5000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
+            a1pms_api_put_policy 200 "service10" ricsim_g1_1 1 5000 true $notificationurl testdata/OSC/pi1_template.json
+            a1pms_api_put_policy 200 "service10" ricsim_g1_1 1 5000 false $notificationurl testdata/OSC/pi1_template.json
 
-        a1pms_api_put_policy 200 "service10" ricsim_g1_1 1 5000 true $notificationurl testdata/OSC/pi1_template.json
-        a1pms_api_put_policy 200 "service10" ricsim_g1_1 1 5000 false $notificationurl testdata/OSC/pi1_template.json
+            a1pms_api_put_policy 201 "service10" ricsim_g2_1 NOTYPE 5100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json
+            a1pms_api_put_policy 200 "service10" ricsim_g2_1 NOTYPE 5100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json
 
-        a1pms_api_put_policy 201 "service10" ricsim_g2_1 NOTYPE 5100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json
-        a1pms_api_put_policy 200 "service10" ricsim_g2_1 NOTYPE 5100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json
+            a1pms_api_put_policy 200 "service10" ricsim_g2_1 NOTYPE 5100 true $notificationurl testdata/STD/pi1_template.json
+            a1pms_api_put_policy 200 "service10" ricsim_g2_1 NOTYPE 5100 false $notificationurl testdata/STD/pi1_template.json
 
-        a1pms_api_put_policy 200 "service10" ricsim_g2_1 NOTYPE 5100 true $notificationurl testdata/STD/pi1_template.json
-        a1pms_api_put_policy 200 "service10" ricsim_g2_1 NOTYPE 5100 false $notificationurl testdata/STD/pi1_template.json
+            a1pms_api_put_policy 201 "service10" ricsim_g3_1 STD_QOS2_0.1.0 5200 NOTRANSIENT $notificationurl testdata/STD2/pi_qos2_template.json
+            a1pms_api_put_policy 200 "service10" ricsim_g3_1 STD_QOS2_0.1.0 5200 NOTRANSIENT $notificationurl testdata/STD2/pi_qos2_template.json
 
-        a1pms_api_put_policy 201 "service10" ricsim_g3_1 STD_QOS2_0.1.0 5200 NOTRANSIENT $notificationurl testdata/STD2/pi_qos2_template.json
-        a1pms_api_put_policy 200 "service10" ricsim_g3_1 STD_QOS2_0.1.0 5200 NOTRANSIENT $notificationurl testdata/STD2/pi_qos2_template.json
+            a1pms_api_put_policy 200 "service10" ricsim_g3_1 STD_QOS2_0.1.0 5200 true $notificationurl testdata/STD2/pi_qos2_template.json
+            a1pms_api_put_policy 200 "service10" ricsim_g3_1 STD_QOS2_0.1.0 5200 false $notificationurl testdata/STD2/pi_qos2_template.json
 
-        a1pms_api_put_policy 200 "service10" ricsim_g3_1 STD_QOS2_0.1.0 5200 true $notificationurl testdata/STD2/pi_qos2_template.json
-        a1pms_api_put_policy 200 "service10" ricsim_g3_1 STD_QOS2_0.1.0 5200 false $notificationurl testdata/STD2/pi_qos2_template.json
+            a1pms_api_get_policy_status 404 1
+            a1pms_api_get_policy_status 404 2
+            if [[ $TEST_ENV_PROFILE =~ ^ORAN-[A-H] ]] || [[ $TEST_ENV_PROFILE =~ ^ONAP-[A-L] ]]; then
+              VAL='NOT IN EFFECT'
+              VAL2="false"
+              VAL3=EMPTY
+              VAL4=EMPTY
+            else
+              VAL="NOT_ENFORCED"
+              VAL2="OTHER_REASON"
+              VAL3="NOT_ENFORCED"
+              VAL4="OTHER_REASON"
+            fi
+            a1pms_api_get_policy_status 200 5000 OSC "$VAL" "$VAL2"
+            a1pms_api_get_policy_status 200 5100 STD "UNDEFINED"
+            a1pms_api_get_policy_status 200 5200 STD2 $VAL3 $VAL4
 
-        a1pms_api_get_policy_status 404 1
-        a1pms_api_get_policy_status 404 2
-        VAL='NOT IN EFFECT'
-        a1pms_api_get_policy_status 200 5000 OSC "$VAL" "false"
-        a1pms_api_get_policy_status 200 5100 STD "UNDEFINED"
-        a1pms_api_get_policy_status 200 5200 STD2 EMPTY EMPTY
+            deviation "TR10 - a1pms allows policy creation on unregistered service (side effect of orig. problem)- test combo $interface and $__httpx"
+            #kept until decision
+            #a1pms_equal json:policy_ids 2
+            #Allow 3 for now
+            a1pms_equal json:policy-instances 4
+          fi
 
+          deviation "TR10 - a1pms allows policy creation on unregistered service (side effect of orig. problem)- test combo $interface and $__httpx"
+          #kept until decision
+          #a1pms_equal json:policies 2
+          #Allow 3 for now
+          a1pms_equal json:policies 4
 
-        deviation "TR10 - a1pms allows policy creation on unregistered service (side effect of orig. problem)- test combo $interface and $__httpx"
-        #kept until decision
-        #a1pms_equal json:policies 2
-        #Allow 3 for now
-        a1pms_equal json:policies 4
+          deviation "TR10 - a1pms allows policy creation on unregistered service (side effect of orig. problem)- test combo $interface and $__httpx"
+          #kept until decision
+          #a1pms_api_get_policy_ids 200 NORIC NOSERVICE NOTYPE 5000 5100
+          #Allow policy create with unregistered service for now
 
-        deviation "TR10 - a1pms allows policy creation on unregistered service (side effect of orig. problem)- test combo $interface and $__httpx"
-        #kept until decision
-        #a1pms_equal json:policy_ids 2
-        #Allow 3 for now
-        a1pms_equal json:policy-instances 4
+          if [ "$A1PMS_VERSION" != "V3" ]; then
+            a1pms_api_get_policy_ids 200 NORIC NOSERVICE NOTYPE 5000 5100 2000 5200
 
-        deviation "TR10 - a1pms allows policy creation on unregistered service (side effect of orig. problem)- test combo $interface and $__httpx"
-        #kept until decision
-        #a1pms_api_get_policy_ids 200 NORIC NOSERVICE NOTYPE 5000 5100
-        #Allow policy create with unregistered service for now
-        a1pms_api_get_policy_ids 200 NORIC NOSERVICE NOTYPE 5000 5100 2000 5200
+            deviation "TR10 - a1pms allows policy creation on unregistered service (side effect of orig. problem)- test combo $interface and $__httpx"
+            #kept until decision
+            #a1pms_api_get_policy_ids 200 ricsim_g1_1 NOSERVICE NOTYPE 5000
+            #Allow policy create with unregistered service for now
+            a1pms_api_get_policy_ids 200 ricsim_g1_1 NOSERVICE NOTYPE 5000 2000
 
-        deviation "TR10 - a1pms allows policy creation on unregistered service (side effect of orig. problem)- test combo $interface and $__httpx"
-        #kept until decision
-        #a1pms_api_get_policy_ids 200 ricsim_g1_1 NOSERVICE NOTYPE 5000
-        #Allow policy create with unregistered service for now
-        a1pms_api_get_policy_ids 200 ricsim_g1_1 NOSERVICE NOTYPE 5000 2000
+            a1pms_api_get_policy_ids 200 ricsim_g2_1 NOSERVICE NOTYPE 5100
 
-        a1pms_api_get_policy_ids 200 ricsim_g2_1 NOSERVICE NOTYPE 5100
+            a1pms_api_get_policy_ids 200 ricsim_g3_1 NOSERVICE NOTYPE 5200
 
-        a1pms_api_get_policy_ids 200 ricsim_g3_1 NOSERVICE NOTYPE 5200
+            a1pms_api_get_policy_ids 200 NORIC "service10" NOTYPE 5000 5100 5200
 
-        a1pms_api_get_policy_ids 200 NORIC "service10" NOTYPE 5000 5100 5200
+            deviation "TR10 - a1pms allows policy creation on unregistered service (side effect of orig. problem)- test combo $interface and $__httpx"
+            #kept until decision
+            #a1pms_api_get_policy_ids 200 NORIC NOSERVICE 1 5000
+            #Allow policy create with unregistered service for now
 
-        deviation "TR10 - a1pms allows policy creation on unregistered service (side effect of orig. problem)- test combo $interface and $__httpx"
-        #kept until decision
-        #a1pms_api_get_policy_ids 200 NORIC NOSERVICE 1 5000
-        #Allow policy create with unregistered service for now
+            a1pms_api_get_policy_ids 200 NORIC NOSERVICE 1 5000 2000
 
-        a1pms_api_get_policy_ids 200 NORIC NOSERVICE 1 5000 2000
+            a1pms_api_get_policy_ids 200 NORIC NOSERVICE 2 NOID
 
-        a1pms_api_get_policy_ids 200 NORIC NOSERVICE 2 NOID
+            a1pms_api_get_policy_ids 200 NORIC NOSERVICE STD_QOS2_0.1.0 5200
 
-        a1pms_api_get_policy_ids 200 NORIC NOSERVICE STD_QOS2_0.1.0 5200
+            a1pms_api_get_policy_ids 200 ricsim_g2_1 NOSERVICE 1 NOID
+          fi
 
-        a1pms_api_get_policy_ids 200 ricsim_g2_1 NOSERVICE 1 NOID
+          if [ "$A1PMS_VERSION" == "V3" ]; then
+            a1pms_api_get_all_policies_v3 200 NORIC NOSERVICE NOTYPE 5000:ricsim_g1_1 5100:ricsim_g2_1 2000:ricsim_g1_1 5200:ricsim_g3_1
 
-        a1pms_api_get_policy 200 5000 testdata/OSC/pi1_template.json "service10" ricsim_g1_1 1 false $notificationurl
+            deviation "TR10 - a1pms allows policy creation on unregistered service (side effect of orig. problem)- test combo $interface and $__httpx"
+            #kept until decision
+            #a1pms_api_get_policy_ids 200 ricsim_g1_1 NOSERVICE NOTYPE 5000
+            #Allow policy create with unregistered service for now
+            a1pms_api_get_all_policies_v3 200 ricsim_g1_1 NOSERVICE NOTYPE 5000:ricsim_g1_1 2000:ricsim_g1_1
 
-        a1pms_api_get_policy 200 5100 testdata/STD/pi1_template.json "service10" ricsim_g2_1 NOTYPE false $notificationurl
+            a1pms_api_get_all_policies_v3 200 ricsim_g2_1 NOSERVICE NOTYPE 5100:ricsim_g2_1
 
-        a1pms_api_get_policy 200 5200 testdata/STD2/pi_qos2_template.json "service10" ricsim_g3_1 STD_QOS2_0.1.0 false $notificationurl
+            a1pms_api_get_all_policies_v3 200 ricsim_g3_1 NOSERVICE NOTYPE 5200:ricsim_g3_1
 
-        a1pms_api_get_policies 200 ricsim_g1_1 "service10" 1 5000 ricsim_g1_1 "service10" 1 false $notificationurl testdata/OSC/pi1_template.json
+            a1pms_api_get_all_policies_v3 200 NORIC "service10" NOTYPE 5000:ricsim_g1_1
 
-        deviation "TR10 - a1pms allows policy creation on unregistered service (side effect of orig. problem)- test combo $interface and $__httpx"
-        #kept until decision
-        #a1pms_api_delete_policy 404 2000
-        #Allow policy create with unregistered service for now
-        a1pms_api_delete_policy 204 2000
+            deviation "TR10 - a1pms allows policy creation on unregistered service (side effect of orig. problem)- test combo $interface and $__httpx"
+            #kept until decision
+            #a1pms_api_get_policy_ids 200 NORIC NOSERVICE 1 5000
+            #Allow policy create with unregistered service for now
 
-        a1pms_api_delete_policy 404 1500
+            a1pms_api_get_all_policies_v3 200 NORIC NOSERVICE 1 5000:ricsim_g1_1 2000:ricsim_g1_1
 
-        a1pms_api_delete_policy 204 5000
+            a1pms_api_get_all_policies_v3 200 NORIC NOSERVICE 2 NOID
 
-        a1pms_api_delete_policy 204 5200
+            a1pms_api_get_all_policies_v3 200 NORIC NOSERVICE STD_QOS2_0.1.0 5200:ricsim_g3_1
 
-        a1pms_equal json:policies 1
+            a1pms_api_get_all_policies_v3 200 ricsim_g2_1 NOSERVICE 1 NOID
+          fi
 
+          a1pms_api_get_policy 200 5000 testdata/OSC/pi1_template.json "service10" ricsim_g1_1 1 false $notificationurl
 
-        a1pms_equal json:policy-instances 1
+          a1pms_api_get_policy 200 5100 testdata/STD/pi1_template.json "service10" ricsim_g2_1 NOTYPE false $notificationurl
 
-        a1pms_api_delete_policy 204 5100
+          a1pms_api_get_policy 200 5200 testdata/STD2/pi_qos2_template.json "service10" ricsim_g3_1 STD_QOS2_0.1.0 false $notificationurl
 
-        a1pms_equal json:policies 0
+          if [ "$A1PMS_VERSION" != "V3" ]; then
+            a1pms_api_get_policies 200 ricsim_g1_1 "service10" 1 5000 ricsim_g1_1 "service10" 1 false $notificationurl testdata/OSC/pi1_template.json
+          fi
 
-        a1pms_equal json:policy-instances 0
+          if [ "$A1PMS_VERSION" == "V3" ]; then
+            a1pms_api_put_policy_v3 200 5100 testdata/STD/pi1_template.json
 
-        cr_equal 0 received_callbacks 3
+            a1pms_api_put_policy_v3 200 5200 testdata/STD2/pi_qos2_template.json
 
-        if [[ $interface = *"DMAAP"* ]]; then
-            mr_greater requests_submitted 0
-            VAL=$(mr_read requests_submitted)
-            mr_equal requests_fetched $VAL
-            mr_equal responses_submitted $VAL
-            mr_equal responses_fetched $VAL
-            mr_equal current_requests 0
-            mr_equal current_responses 0
-        else
-            if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-                :
-            else
-                mr_equal requests_submitted 0
-            fi
-        fi
-        if [ $USE_ISTIO -eq 0 ]; then
-            if [[ $interface = *"SDNC"* ]]; then
-                sim_contains_str ricsim_g1_1 remote_hosts $SDNC_APP_NAME
-                sim_contains_str ricsim_g2_1 remote_hosts $SDNC_APP_NAME
-                sim_contains_str ricsim_g3_1 remote_hosts $SDNC_APP_NAME
-            else
-                sim_contains_str ricsim_g1_1 remote_hosts $A1PMS_APP_NAME
-                sim_contains_str ricsim_g2_1 remote_hosts $A1PMS_APP_NAME
-                sim_contains_str ricsim_g3_1 remote_hosts $A1PMS_APP_NAME
+            if [[ $interface != *"DMAAP"* ]]; then
+               a1pms_api_put_policy_v3 400 2000 testdata/OSC/pi_bad_template.json
             fi
-        fi
-
-        check_a1pms_logs
-
-        if [[ $interface = *"SDNC"* ]]; then
-            check_sdnc_logs
-        fi
-
-        store_logs          "${__httpx}__${interface}"
-
-    done
+          fi
+          deviation "TR10 - a1pms allows policy creation on unregistered service (side effect of orig. problem)- test combo $interface and $__httpx"
+          #kept until decision
+          #a1pms_api_delete_policy 404 2000
+          #Allow policy create with unregistered service for now
+          a1pms_api_delete_policy 204 2000
+
+          a1pms_api_delete_policy 404 1500
+
+          a1pms_api_delete_policy 204 5000
+
+          a1pms_api_delete_policy 204 5200
+
+          a1pms_equal json:policies 1
+
+          if [ "$A1PMS_VERSION" != "V3" ]; then
+            a1pms_equal json:policy-instances 1
+          fi
+
+          a1pms_api_delete_policy 204 5100
+
+          a1pms_equal json:policies 0
+
+          if [ "$A1PMS_VERSION" != "V3" ]; then
+            a1pms_equal json:policy-instances 0
+          fi
+
+          cr_equal 0 received_callbacks 3
+
+          if [[ $interface = *"DMAAP"* ]]; then
+              mr_greater requests_submitted 0
+              VAL=$(mr_read requests_submitted)
+              mr_equal requests_fetched $VAL
+              mr_equal responses_submitted $VAL
+              mr_equal responses_fetched $VAL
+              mr_equal current_requests 0
+              mr_equal current_responses 0
+          else
+              if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+                  :
+              else
+                  mr_equal requests_submitted 0
+              fi
+          fi
+          if [ $USE_ISTIO -eq 0 ]; then
+              if [[ $interface = *"SDNC"* ]]; then
+                  sim_contains_str ricsim_g1_1 remote_hosts $SDNC_APP_NAME
+                  sim_contains_str ricsim_g2_1 remote_hosts $SDNC_APP_NAME
+                  sim_contains_str ricsim_g3_1 remote_hosts $SDNC_APP_NAME
+              else
+                  sim_contains_str ricsim_g1_1 remote_hosts $A1PMS_APP_NAME
+                  sim_contains_str ricsim_g2_1 remote_hosts $A1PMS_APP_NAME
+                  sim_contains_str ricsim_g3_1 remote_hosts $A1PMS_APP_NAME
+              fi
+          fi
+
+          check_a1pms_logs
+
+          if [[ $interface = *"SDNC"* ]]; then
+              check_sdnc_logs
+          fi
+
+          store_logs          "${__httpx}__${interface}"
+
+      done
+
+  done
 
 done
-
 #### TEST COMPLETE ####
 
 
index ea3a7f2..985fd46 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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.
@@ -34,7 +35,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
@@ -43,211 +44,252 @@ SUPPORTED_RUNMODES="DOCKER KUBE"
 setup_testenvironment
 
 #### TEST BEGIN ####
+VERSIONS_TO_RUN=2
 
-sim_generate_policy_uuid
+if [ -n "$A1PMS_V3_FLAG" ] && [ "${A1PMS_V3_FLAG,,}" == "true" ]; then
+  VERSIONS_TO_RUN=3
+fi
 
-use_cr_http
-use_simulator_http
-use_mr_http
-use_a1pms_rest_http
+for version in $(seq 2 $VERSIONS_TO_RUN); do
 
-clean_environment
+  echo "#####################################################################"
+  echo "#####################################################################"
+  echo "### Testing a1pms: V${version}"
+  echo "#####################################################################"
+  echo "#####################################################################"
 
-start_kube_proxy
+  if [ "$version" == "3" ]; then
+    if [ -n "$A1PMS_V3" ] && [ -n "$A1PMS_API_PREFIX_V3" ] && [ -n "$A1PMS_ALIVE_URL_V3" ]; then
+      export A1PMS_VERSION="$A1PMS_V3"
+      export A1PMS_API_PREFIX="$A1PMS_API_PREFIX_V3"
+      export A1PMS_ALIVE_URL="$A1PMS_API_PREFIX$A1PMS_ALIVE_URL_V3"
+    else
+      echo "One/All parameters not set in env file (<A1PMS_V3>, <A1PMS_API_PREFIX_V3>, <A1PMS_ALIVE_URL_V3>)"
+      break
+    fi
+  fi
+  sim_generate_policy_uuid
 
-start_ric_simulators ricsim_g1 1  OSC_2.1.0
-start_ric_simulators ricsim_g2 1  STD_1.1.3
-start_ric_simulators ricsim_g3 1  STD_2.0.0
+  use_cr_http
+  use_simulator_http
+  use_mr_http
+  use_a1pms_rest_http
 
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    :
-else
-    start_mr
-fi
+  clean_environment
 
-start_cr 1
+  start_kube_proxy
 
-start_control_panel $SIM_GROUP/$CONTROL_PANEL_COMPOSE_DIR/$CONTROL_PANEL_CONFIG_FILE
+  start_ric_simulators ricsim_g1 1  OSC_2.1.0
+  start_ric_simulators ricsim_g2 1  STD_1.1.3
+  start_ric_simulators ricsim_g3 1  STD_2.0.0
 
-if [ ! -z "$NRT_GATEWAY_APP_NAME" ]; then
-    start_gateway $SIM_GROUP/$NRT_GATEWAY_COMPOSE_DIR/$NRT_GATEWAY_CONFIG_FILE
-fi
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      :
+  else
+      start_mr
+  fi
 
-start_a1pms NORPOXY $SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_CONFIG_FILE
+  start_cr 1
 
+  start_control_panel $SIM_GROUP/$CONTROL_PANEL_COMPOSE_DIR/$CONTROL_PANEL_CONFIG_FILE
 
-prepare_a1pms_config      NOSDNC  ".a1pms_config.json"
+  if [ ! -z "$NRT_GATEWAY_APP_NAME" ]; then
+      start_gateway $SIM_GROUP/$NRT_GATEWAY_COMPOSE_DIR/$NRT_GATEWAY_CONFIG_FILE
+  fi
 
-if [ $RUNMODE == "KUBE" ]; then
-    a1pms_load_config                       ".a1pms_config.json"
-else
-    a1pms_api_put_configuration 200 ".a1pms_config.json"
-fi
+  start_a1pms NORPOXY $SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_CONFIG_FILE
 
-set_a1pms_debug
 
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    :
-else
-    mr_equal requests_submitted 0
-fi
+  prepare_a1pms_config      NOSDNC  ".a1pms_config.json"
 
-sleep_wait 120 "Let A1PMS configuration take effect"
+  if [ $RUNMODE == "KUBE" ]; then
+      a1pms_load_config                       ".a1pms_config.json"
+  else
+      a1pms_api_put_configuration 200 ".a1pms_config.json"
+  fi
 
-#Check a1pms alive
-a1pms_api_get_status 200
+  set_a1pms_debug
 
-#Print simulator interface version
-sim_print ricsim_g1_1 interface
-sim_print ricsim_g2_1 interface
-sim_print ricsim_g3_1 interface
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      :
+  else
+      mr_equal requests_submitted 0
+  fi
 
-a1pms_api_put_service 201 "service1" 15 "$CR_SERVICE_APP_PATH_0/service1"
+  sleep_wait 120 "Let A1PMS configuration take effect"
 
-a1pms_api_get_services 200 "service1" "service1" 15 "$CR_SERVICE_APP_PATH_0/service1"
+  #Check a1pms alive
+  a1pms_api_get_status 200
 
-a1pms_api_put_service 201 "service2" 120 "$CR_SERVICE_APP_PATH_0/service2"
+  #Print simulator interface version
+  sim_print ricsim_g1_1 interface
+  sim_print ricsim_g2_1 interface
+  sim_print ricsim_g3_1 interface
 
-a1pms_api_get_services 200 "service2" "service2" 120 "$CR_SERVICE_APP_PATH_0/service2"
+  a1pms_api_put_service 201 "service1" 15 "$CR_SERVICE_APP_PATH_0/service1"
 
-a1pms_api_put_service 200 "service1" 50 "$CR_SERVICE_APP_PATH_0/service1"
-a1pms_api_put_service 200 "service2" 180 "$CR_SERVICE_APP_PATH_0/service2"
+  a1pms_api_get_services 200 "service1" "service1" 15 "$CR_SERVICE_APP_PATH_0/service1"
 
-a1pms_api_get_services 200 "service1" "service1" 50 "$CR_SERVICE_APP_PATH_0/service1"
-a1pms_api_get_services 200 "service2" "service2" 180 "$CR_SERVICE_APP_PATH_0/service2"
+  a1pms_api_put_service 201 "service2" 120 "$CR_SERVICE_APP_PATH_0/service2"
 
-a1pms_api_get_service_ids 200 "service1" "service2"
+  a1pms_api_get_services 200 "service2" "service2" 120 "$CR_SERVICE_APP_PATH_0/service2"
 
-sleep_wait 30 "Waiting for keep alive timeout"
+  a1pms_api_put_service 200 "service1" 50 "$CR_SERVICE_APP_PATH_0/service1"
+  a1pms_api_put_service 200 "service2" 180 "$CR_SERVICE_APP_PATH_0/service2"
 
-a1pms_api_get_services 200 "service1" "service1" 50 "$CR_SERVICE_APP_PATH_0/service1"
-a1pms_api_get_services 200 "service2" "service2" 180 "$CR_SERVICE_APP_PATH_0/service2"
+  a1pms_api_get_services 200 "service1" "service1" 50 "$CR_SERVICE_APP_PATH_0/service1"
+  a1pms_api_get_services 200 "service2" "service2" 180 "$CR_SERVICE_APP_PATH_0/service2"
 
-sleep_wait 100 "Waiting for keep alive timeout"
+  a1pms_api_get_service_ids 200 "service1" "service2"
 
-a1pms_api_get_services 404 "service1"
-a1pms_api_get_services 200 "service2" "service2" 180 "$CR_SERVICE_APP_PATH_0/service2"
+  sleep_wait 30 "Waiting for keep alive timeout"
 
-a1pms_api_delete_services 204 "service2"
+  a1pms_api_get_services 200 "service1" "service1" 50 "$CR_SERVICE_APP_PATH_0/service1"
+  a1pms_api_get_services 200 "service2" "service2" 180 "$CR_SERVICE_APP_PATH_0/service2"
 
-a1pms_api_get_services 404 "service1"
-a1pms_api_get_services 404 "service2"
+  sleep_wait 100 "Waiting for keep alive timeout"
 
-a1pms_api_put_service 201 "service3" 60 "$CR_SERVICE_APP_PATH_0/service3"
+  a1pms_api_get_services 404 "service1"
+  a1pms_api_get_services 200 "service2" "service2" 180 "$CR_SERVICE_APP_PATH_0/service2"
 
-a1pms_api_get_services 200 "service3" "service3" 60 "$CR_SERVICE_APP_PATH_0/service3"
+  a1pms_api_delete_services 204 "service2"
 
-sleep_wait 30 "Waiting for keep alive timeout"
+  a1pms_api_get_services 404 "service1"
+  a1pms_api_get_services 404 "service2"
 
-a1pms_api_put_service 200 "service3" 60 "$CR_SERVICE_APP_PATH_0/service3"
+  a1pms_api_put_service 201 "service3" 60 "$CR_SERVICE_APP_PATH_0/service3"
 
-sleep_wait 100 "Waiting for keep alive timeout"
+  a1pms_api_get_services 200 "service3" "service3" 60 "$CR_SERVICE_APP_PATH_0/service3"
 
-a1pms_api_get_services 404 "service3"
+  sleep_wait 30 "Waiting for keep alive timeout"
 
-a1pms_api_put_service 201 "service4" 120 "$CR_SERVICE_APP_PATH_0/service4"
+  a1pms_api_put_service 200 "service3" 60 "$CR_SERVICE_APP_PATH_0/service3"
 
-sleep_wait 60 "Waiting for keep alive timeout"
+  sleep_wait 100 "Waiting for keep alive timeout"
 
-a1pms_api_get_services 200 "service4" "service4" 120 "$CR_SERVICE_APP_PATH_0/service4"
+  a1pms_api_get_services 404 "service3"
 
-a1pms_api_put_services_keepalive 200 "service4"
+  a1pms_api_put_service 201 "service4" 120 "$CR_SERVICE_APP_PATH_0/service4"
 
-sleep_wait 90 "Waiting for keep alive timeout"
+  sleep_wait 60 "Waiting for keep alive timeout"
 
-a1pms_api_get_services 200 "service4" "service4" 120 "$CR_SERVICE_APP_PATH_0/service4"
+  a1pms_api_get_services 200 "service4" "service4" 120 "$CR_SERVICE_APP_PATH_0/service4"
 
-a1pms_api_delete_services 204 "service4"
+  a1pms_api_put_services_keepalive 200 "service4"
 
-a1pms_api_get_services 404 "service4"
+  sleep_wait 90 "Waiting for keep alive timeout"
 
-a1pms_api_get_services 404 "service1"
-a1pms_api_get_services 404 "service2"
-a1pms_api_get_services 404 "service3"
+  a1pms_api_get_services 200 "service4" "service4" 120 "$CR_SERVICE_APP_PATH_0/service4"
 
-a1pms_api_get_service_ids 200
+  a1pms_api_delete_services 204 "service4"
 
-a1pms_api_delete_services 404 "service1"
-a1pms_api_delete_services 404 "service2"
-a1pms_api_delete_services 404 "service3"
-a1pms_api_delete_services 404 "service4"
+  a1pms_api_get_services 404 "service4"
 
-a1pms_api_put_services_keepalive 404 "service1"
-a1pms_api_put_services_keepalive 404 "service2"
-a1pms_api_put_services_keepalive 404 "service3"
-a1pms_api_put_services_keepalive 404 "service4"
+  a1pms_api_get_services 404 "service1"
+  a1pms_api_get_services 404 "service2"
+  a1pms_api_get_services 404 "service3"
 
-# Policy delete after timeout
-a1pms_api_put_service 201 "service10" 600 "$CR_SERVICE_APP_PATH_0/service10"
+  a1pms_api_get_service_ids 200
 
-sim_put_policy_type 201 ricsim_g1_1 1 testdata/OSC/sim_1.json
+  a1pms_api_delete_services 404 "service1"
+  a1pms_api_delete_services 404 "service2"
+  a1pms_api_delete_services 404 "service3"
+  a1pms_api_delete_services 404 "service4"
 
-sim_put_policy_type 201 ricsim_g3_1 STD_QOS2_0.1.0 testdata/STD2/sim_qos2.json
+  a1pms_api_put_services_keepalive 404 "service1"
+  a1pms_api_put_services_keepalive 404 "service2"
+  a1pms_api_put_services_keepalive 404 "service3"
+  a1pms_api_put_services_keepalive 404 "service4"
 
-a1pms_equal json:rics 3 300
+  # Policy delete after timeout
+  a1pms_api_put_service 201 "service10" 600 "$CR_SERVICE_APP_PATH_0/service10"
 
-#a1pms_equal json:policy_schemas 2 120
+  sim_put_policy_type 201 ricsim_g1_1 1 testdata/OSC/sim_1.json
 
-a1pms_equal json:policy-types 3 120
+  sim_put_policy_type 201 ricsim_g3_1 STD_QOS2_0.1.0 testdata/STD2/sim_qos2.json
 
-a1pms_equal json:policies 0
+  a1pms_equal json:rics 3 300
 
-notificationurl=$CR_SERVICE_APP_PATH_0"/test"
+  #a1pms_equal json:policy_schemas 2 120
 
-a1pms_api_put_policy 201 "service10" ricsim_g1_1 1 5000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
-a1pms_api_put_policy 201 "service10" ricsim_g2_1 NOTYPE 5100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json
+  a1pms_equal json:policies 0
 
-a1pms_api_put_policy 201 "service10" ricsim_g3_1 STD_QOS2_0.1.0 5200 NOTRANSIENT $notificationurl testdata/STD2/pi_qos2_template.json
-a1pms_equal json:policies 3
+  notificationurl=$CR_SERVICE_APP_PATH_0"/test"
 
-sim_equal ricsim_g1_1 num_instances 1
-sim_equal ricsim_g2_1 num_instances 1
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_equal json:policytypes 3 120
+    a1pms_api_post_policy_v3 201 "service10" ricsim_g1_1 1 5000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
+    a1pms_api_post_policy_v3 201 "service10" ricsim_g2_1 NOTYPE 5100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json
 
-a1pms_api_put_policy 201 "service10" ricsim_g1_1 1 5001 true $notificationurl testdata/OSC/pi1_template.json
-a1pms_api_put_policy 201 "service10" ricsim_g2_1 NOTYPE 5101 true $notificationurl testdata/STD/pi1_template.json
+    a1pms_api_post_policy_v3 201 "service10" ricsim_g3_1 STD_QOS2_0.1.0 5200 NOTRANSIENT $notificationurl testdata/STD2/pi_qos2_template.json
 
-a1pms_api_put_policy 201 "service10" ricsim_g3_1 STD_QOS2_0.1.0 5201 true $notificationurl testdata/STD2/pi_qos2_template.json
-a1pms_equal json:policies 6
+  else
+    a1pms_equal json:policy-types 3 120
+    a1pms_api_put_policy 201 "service10" ricsim_g1_1 1 5000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
+    a1pms_api_put_policy 201 "service10" ricsim_g2_1 NOTYPE 5100 NOTRANSIENT $notificationurl testdata/STD/pi1_template.json
 
-sim_equal ricsim_g1_1 num_instances 2
-sim_equal ricsim_g2_1 num_instances 2
-sim_equal ricsim_g3_1 num_instances 2
+    a1pms_api_put_policy 201 "service10" ricsim_g3_1 STD_QOS2_0.1.0 5200 NOTRANSIENT $notificationurl testdata/STD2/pi_qos2_template.json
 
-sim_post_delete_instances 200 ricsim_g1_1
-sim_post_delete_instances 200 ricsim_g2_1
+  fi
 
-sim_post_delete_instances 200 ricsim_g3_1
+  a1pms_equal json:policies 3
 
-#Wait for recreate of non transient policy
-a1pms_equal json:policies 3 180
+  sim_equal ricsim_g1_1 num_instances 1
+  sim_equal ricsim_g2_1 num_instances 1
 
-sim_equal ricsim_g1_1 num_instances 1
-sim_equal ricsim_g2_1 num_instances 1
-sim_equal ricsim_g3_1 num_instances 1
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    a1pms_api_post_policy_v3 201 "service10" ricsim_g1_1 1 5001 true $notificationurl testdata/OSC/pi1_template.json
+    a1pms_api_post_policy_v3 201 "service10" ricsim_g2_1 NOTYPE 5101 true $notificationurl testdata/STD/pi1_template.json
 
-a1pms_api_put_service 200 "service10" 10 "$CR_SERVICE_APP_PATH_0/service10"
+    a1pms_api_post_policy_v3 201 "service10" ricsim_g3_1 STD_QOS2_0.1.0 5201 true $notificationurl testdata/STD2/pi_qos2_template.json
+  else
+    a1pms_api_put_policy 201 "service10" ricsim_g1_1 1 5001 true $notificationurl testdata/OSC/pi1_template.json
+    a1pms_api_put_policy 201 "service10" ricsim_g2_1 NOTYPE 5101 true $notificationurl testdata/STD/pi1_template.json
 
-#Wait for service expiry
-a1pms_equal json:policies 0 120
+    a1pms_api_put_policy 201 "service10" ricsim_g3_1 STD_QOS2_0.1.0 5201 true $notificationurl testdata/STD2/pi_qos2_template.json
+  fi
+  a1pms_equal json:policies 6
 
-sim_equal ricsim_g1_1 num_instances 0
-sim_equal ricsim_g2_1 num_instances 0
-sim_equal ricsim_g3_1 num_instances 0
+  sim_equal ricsim_g1_1 num_instances 2
+  sim_equal ricsim_g2_1 num_instances 2
+  sim_equal ricsim_g3_1 num_instances 2
 
-a1pms_api_get_service_ids 200
+  sim_post_delete_instances 200 ricsim_g1_1
+  sim_post_delete_instances 200 ricsim_g2_1
 
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    :
-else
-    mr_equal requests_submitted 0
-fi
+  sim_post_delete_instances 200 ricsim_g3_1
+
+  #Wait for recreate of non transient policy
+  a1pms_equal json:policies 3 180
+
+  sim_equal ricsim_g1_1 num_instances 1
+  sim_equal ricsim_g2_1 num_instances 1
+  sim_equal ricsim_g3_1 num_instances 1
+
+  a1pms_api_put_service 200 "service10" 10 "$CR_SERVICE_APP_PATH_0/service10"
+
+  #Wait for service expiry
+  a1pms_equal json:policies 0 120
+
+  sim_equal ricsim_g1_1 num_instances 0
+  sim_equal ricsim_g2_1 num_instances 0
+  sim_equal ricsim_g3_1 num_instances 0
+
+  a1pms_api_get_service_ids 200
+
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      :
+  else
+      mr_equal requests_submitted 0
+  fi
 
-check_a1pms_logs
+  check_a1pms_logs
 
-#### TEST COMPLETE ####
+  #### TEST COMPLETE ####
 
-store_logs          END
+  store_logs          END
 
-print_result
+  print_result
 
-auto_clean_environment
\ No newline at end of file
+  auto_clean_environment
+done
\ No newline at end of file
index 5abaee5..c659805 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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.
@@ -40,7 +41,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index 25283a5..103d74c 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=" "
 CONDITIONALLY_IGNORED_IMAGES=""
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
@@ -127,9 +128,14 @@ for __nb_httpx in $NB_TESTED_PROTOCOLS ; do
 
         controller_api_get_A1_policy_status 200 OSC ricsim_g1_1 1 4000
         controller_api_get_A1_policy_status 200 STD ricsim_g2_1 5000
-
-        VAL='NOT_ENFORCED'
-        controller_api_get_A1_policy_status 200 OSC ricsim_g1_1 1 4000 "$VAL" "OTHER_REASON"
+        if [[ $TEST_ENV_PROFILE =~ ^ORAN-[A-H] ]] || [[ $TEST_ENV_PROFILE =~ ^ONAP-[A-L] ]]; then
+          VAL='NOT IN EFFECT'
+          VAL2="false"
+        else
+          VAL='NOT_ENFORCED'
+          VAL2="OTHER_REASON"
+        fi
+        controller_api_get_A1_policy_status 200 OSC ricsim_g1_1 1 4000 "$VAL" "$VAL2"
         controller_api_get_A1_policy_status 200 STD ricsim_g2_1 5000 "UNDEFINED"
 
         RESP=202
index ac21238..bd25495 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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.
@@ -34,7 +35,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index 3e27282..d5723f0 100755 (executable)
@@ -1,7 +1,8 @@
 #!/bin/bash
 
 #  ============LICENSE_START===============================================
-#  Copyright (C) 2020 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023-2024 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.
@@ -34,7 +35,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW "
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ORAN-H-RELEASE ONAP-LONDON"
+SUPPORTED_PROFILES="ORAN-I-RELEASE ONAP-MONTREAL"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
@@ -140,7 +141,7 @@ for __httpx in $TESTED_PROTOCOLS ; do
         fi
 
         sim_put_policy_type 201 ricsim_g1_1 STD_QOS_0_2_0 testdata/STD2/sim_qos.json
-        sim_put_policy_type 201 ricsim_g2_1 $A1PMS_ADAPTER_POLICY_NAME testdata/STD2/sim_qos.json
+        sim_put_policy_type 201 ricsim_g2_1 $A1PMS_ADAPTER_POLICY_TYPE testdata/STD2/sim_qos.json
 
         a1pms_equal json:rics 2 300
 
@@ -176,7 +177,7 @@ for __httpx in $TESTED_PROTOCOLS ; do
         echo "############## RIC Repository ##############"
         echo "############################################"
 
-        a1pms_api_get_rics 200 NOTYPE "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:STD_QOS_0_2_0:AVAILABLE ricsim_g2_1:me1_ricsim_g2_1,me2_ricsim_g2_1:$A1PMS_ADAPTER_POLICY_NAME:AVAILABLE"
+        a1pms_api_get_rics 200 NOTYPE "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:STD_QOS_0_2_0:AVAILABLE ricsim_g2_1:me1_ricsim_g2_1,me2_ricsim_g2_1:$A1PMS_ADAPTER_POLICY_TYPE:AVAILABLE"
 
         echo "############################################"
         echo "########### A1 Policy Management ###########"
@@ -187,8 +188,8 @@ for __httpx in $TESTED_PROTOCOLS ; do
         a1pms_api_put_policy 201 "serv1" ricsim_g1_1 STD_QOS_0_2_0 5000 true $notificationurl testdata/STD2/pi_qos_template.json
         a1pms_api_put_policy 200 "serv1" ricsim_g1_1 STD_QOS_0_2_0 5000 true $notificationurl testdata/STD2/pi_qos_template.json
 
-        a1pms_api_put_policy 201 "serv1" ricsim_g2_1 $A1PMS_ADAPTER_POLICY_NAME 5100 true $notificationurl testdata/STD2/pi_qos_template.json
-        a1pms_api_put_policy 200 "serv1" ricsim_g2_1 $A1PMS_ADAPTER_POLICY_NAME 5100 true $notificationurl testdata/STD2/pi_qos_template.json
+        a1pms_api_put_policy 201 "serv1" ricsim_g2_1 $A1PMS_ADAPTER_POLICY_TYPE 5100 true $notificationurl testdata/STD2/pi_qos_template.json
+        a1pms_api_put_policy 200 "serv1" ricsim_g2_1 $A1PMS_ADAPTER_POLICY_TYPE 5100 true $notificationurl testdata/STD2/pi_qos_template.json
 
         a1pms_equal json:policies 2
 
diff --git a/test/auto-test/FTC1_MEDIATOR_ADAPTER.sh b/test/auto-test/FTC1_MEDIATOR_ADAPTER.sh
new file mode 100644 (file)
index 0000000..6428b67
--- /dev/null
@@ -0,0 +1,147 @@
+#!/bin/bash
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2024 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=================================================
+
+TC_ONELINE_DESCR="Sanity test, create service and then create, update and delete a policy using http and A1PMS REST and REST+SDNC"
+
+# App names to include in the test when running docker, space separated list
+DOCKER_INCLUDED_IMAGES="CP CR A1PMS RICSIM RICMEDIATORSIM NGW KUBEPROXY SDNC"
+
+# App names to include in the test when running kubernetes, space separated list
+KUBE_INCLUDED_IMAGES="CP CR A1PMS RICSIM RICMEDIATORSIM NGW KUBEPROXY SDNC"
+# Pre-started app (not started by script) to include in the test when running kubernetes, space separated list
+KUBE_PRESTARTED_IMAGES=""
+# Ignore image in DOCKER_INCLUDED_IMAGES, KUBE_INCLUDED_IMAGES if the image is not configured in the supplied env_file
+# Used for images not applicable to all supported profile
+CONDITIONALLY_IGNORED_IMAGES="NGW "
+
+# Supported test environment profiles
+SUPPORTED_PROFILES="ORAN-I-RELEASE"
+# Supported run modes
+SUPPORTED_RUNMODES="DOCKER KUBE"
+
+. ../common/testcase_common.sh $@
+setup_testenvironment
+
+#### TEST BEGIN ####
+sim_generate_policy_uuid
+
+# Tested variants of REST config
+TESTED_VARIANTS="REST REST+SDNC"
+
+# Test a1pms and mediator protocol versions
+TESTED_PROTOCOLS="HTTP"
+
+for __httpx in $TESTED_PROTOCOLS ; do
+    for interface in $TESTED_VARIANTS ; do
+        echo "#####################################################################"
+        echo "#####################################################################"
+        echo "### Testing a1pms: $interface using $__httpx"
+        echo "#####################################################################"
+        echo "#####################################################################"
+
+        clean_environment
+
+        start_kube_proxy
+
+        use_a1pms_rest_http
+        use_ricmediator_simulator_http
+
+        start_a1pms NORPOXY $SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_CONFIG_FILE
+        set_a1pms_trace
+
+        a1pms_api_put_service 201 "ric-registration" 0 "$CR_SERVICE_APP_PATH_0/ric-registration"
+
+        use_cr_http
+        use_ricmediator_simulator_http
+        if [[ $interface = *"SDNC"* ]]; then
+            use_sdnc_http
+        fi
+        use_a1pms_rest_http
+
+        start_ricmediator_simulators ricsim_g4 1 NONE
+        start_cr 1
+        start_control_panel $SIM_GROUP/$CONTROL_PANEL_COMPOSE_DIR/$CONTROL_PANEL_CONFIG_FILE
+
+        if [ ! -z "$NRT_GATEWAY_APP_NAME" ]; then
+            start_gateway $SIM_GROUP/$NRT_GATEWAY_COMPOSE_DIR/$NRT_GATEWAY_CONFIG_FILE
+        fi
+
+        if [ -z "$A1PMS_SDNC_ADAPTER_CLASS" ] || [ -z "$A1PMS_NOSDNC_ADAPTER_CLASS" ]; then
+            echo -e $RED"Env vars A1PMS_SDNC_ADAPTER_CLASS and A1PMS_NOSDNC_ADAPTER_CLASS must be set with override file"$ERED
+            exit 1
+        fi
+
+        if [[ $interface = *"SDNC"* ]]; then
+            start_sdnc
+            prepare_a1pms_config SDNC ".a1pms_config.json" ricsim-g4 $A1PMS_SDNC_ADAPTER_CLASS
+        else
+            prepare_a1pms_config NOSDNC ".a1pms_config.json" ricsim-g4 $A1PMS_NOSDNC_ADAPTER_CLASS
+        fi
+
+        if [ $RUNMODE == "KUBE" ]; then
+            a1pms_load_config ".a1pms_config.json"
+        else
+            a1pms_api_put_configuration 200 ".a1pms_config.json"
+        fi
+
+        ricmediatorsim_put_policy_type 201 ricsim_g4_1 $A1PMS_ADAPTER_POLICY_TYPE testdata/OSC/sim_1.json
+
+        a1pms_equal json:rics 1 300
+        a1pms_equal json:policy-types 1 120
+        a1pms_equal json:policies 0
+        a1pms_equal json:policy-instances 0
+        cr_equal 0 received_callbacks 1 120
+        cr_api_check_all_sync_events 200 0 ric-registration ricsim_g4_1
+
+        echo "############################################"
+        echo "############## Health check ################"
+        echo "############################################"
+        sleep_wait 120 "Let A1PMS configuration take effect"
+        a1pms_api_get_status 200
+
+        echo "############################################"
+        echo "##### Service registry and supervision #####"
+        echo "############################################"
+        a1pms_api_put_service 201 "serv1" 1000 "$CR_SERVICE_APP_PATH_0/1"
+        a1pms_api_get_service_ids 200 "serv1" "ric-registration"
+        a1pms_api_put_services_keepalive 200 "serv1"
+
+        echo "############################################"
+        echo "############## RIC Repository ##############"
+        echo "############################################"
+        a1pms_api_get_rics 200 NOTYPE "ricsim_g4_1:me1_ricsim_g4_1,me2_ricsim_g4_1:$A1PMS_ADAPTER_POLICY_TYPE:AVAILABLE"
+
+        echo "############################################"
+        echo "########### A1 Policy Management ###########"
+        echo "############################################"
+        notificationurl=$CR_SERVICE_APP_PATH_0"/test"
+        a1pms_api_put_policy 201 "serv1" ricsim_g4_1 $A1PMS_ADAPTER_POLICY_TYPE 5300 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
+        a1pms_api_put_policy 200 "serv1" ricsim_g4_1 $A1PMS_ADAPTER_POLICY_TYPE 5300 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json
+
+        a1pms_equal json:policies 1
+        a1pms_api_delete_policy 204 5300
+        a1pms_equal json:policies 0
+        a1pms_equal json:policy-instances 0
+        cr_equal 0 received_callbacks 1
+
+        check_a1pms_logs
+    done
+done
+
+#### TEST COMPLETE ####
+print_result
+auto_clean_environment
\ No newline at end of file
index 8761a36..a17036a 100755 (executable)
@@ -1,7 +1,8 @@
 #!/bin/bash
 
 #  ============LICENSE_START===============================================
-#  Copyright (C) 2020 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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.
@@ -34,7 +35,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW "
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
@@ -150,7 +151,7 @@ for __httpx in $TESTED_PROTOCOLS ; do
 
         sim_put_policy_type 201 ricsim_g3_1 STD_QOS_0_2_0 testdata/STD2/sim_qos.json
 
-        ricmediatorsim_put_policy_type 201 ricsim_g4_1 1 testdata/OSC/sim_1.json
+        ricmediatorsim_put_policy_type 201 ricsim_g4_1 1 testdata/STD2/sim_qos.json
 
         a1pms_equal json:rics 4 300
 
index 6b80bb7..4909a5d 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/bash
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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.
@@ -31,7 +32,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW "
 
 # Supported test environment profiles
-SUPPORTED_PROFILES="ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ORAN-I-RELEASE"
 # Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
@@ -87,7 +88,7 @@ for __httpx in $TESTED_PROTOCOLS ; do
             a1pms_api_put_configuration 200 ".a1pms_config.json"
         fi
 
-        ricmediatorsim_put_policy_type 201 ricsim_g4_1 1 testdata/OSC/sim_1.json
+        ricmediatorsim_put_policy_type 201 ricsim_g4_1 1 testdata/STD2/sim_qos.json
 
         a1pms_equal json:rics 1 300
         a1pms_equal json:policy-types 1 120
index 651762a..f39eb02 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
@@ -42,205 +43,249 @@ SUPPORTED_RUNMODES="DOCKER KUBE"
 setup_testenvironment
 
 #### TEST BEGIN ####
+VERSIONS_TO_RUN=2
 
-#Local vars in test script
-##########################
-
-use_cr_https
-use_a1pms_rest_https
-use_simulator_https
-use_ics_rest_https
-use_prod_stub_https
-
-notificationurl=$CR_SERVICE_APP_PATH_0"/test"
-
-clean_environment
-
-start_kube_proxy
-
-STD_NUM_RICS=2
-
-start_http_proxy
-
-start_ric_simulators $RIC_SIM_PREFIX"_g3" $STD_NUM_RICS STD_2.0.0
-
-if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-    :
-else
-    start_mr #Just to prevent errors in the a1pms log...
-fi
-
-start_control_panel $SIM_GROUP/$CONTROL_PANEL_COMPOSE_DIR/$CONTROL_PANEL_CONFIG_FILE
-
-if [ ! -z "$NRT_GATEWAY_APP_NAME" ]; then
-    start_gateway $SIM_GROUP/$NRT_GATEWAY_COMPOSE_DIR/$NRT_GATEWAY_CONFIG_FILE
-fi
-
-start_a1pms PROXY $SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_CONFIG_FILE
-
-
-
-prepare_a1pms_config      NOSDNC  ".a1pms_config.json"
-
-if [ $RUNMODE == "KUBE" ]; then
-    a1pms_load_config                       ".a1pms_config.json"
-else
-    a1pms_api_put_configuration 200 ".a1pms_config.json"
+if [ -n "$A1PMS_V3_FLAG" ] && [ "${A1PMS_V3_FLAG,,}" == "true" ]; then
+  VERSIONS_TO_RUN=3
 fi
 
-start_cr 1
+for version in $(seq 2 $VERSIONS_TO_RUN); do
 
-start_prod_stub
+  echo "#####################################################################"
+  echo "#####################################################################"
+  echo "### Testing a1pms: V${version}"
+  echo "#####################################################################"
+  echo "#####################################################################"
 
-start_ics PROXY $SIM_GROUP/$ICS_COMPOSE_DIR/$ICS_CONFIG_FILE
+  if [ "$version" == "3" ]; then
+    if [ -n "$A1PMS_V3" ] && [ -n "$A1PMS_API_PREFIX_V3" ] && [ -n "$A1PMS_ALIVE_URL_V3" ]; then
+      export A1PMS_VERSION="$A1PMS_V3"
+      export A1PMS_API_PREFIX="$A1PMS_API_PREFIX_V3"
+      export A1PMS_ALIVE_URL="$A1PMS_API_PREFIX$A1PMS_ALIVE_URL_V3"
+    else
+      echo "One/All parameters not set in env file (<A1PMS_V3>, <A1PMS_API_PREFIX_V3>, <A1PMS_ALIVE_URL_V3>)"
+      break
+    fi
+  fi
+  #Local vars in test script
+  ##########################
 
-set_a1pms_trace
+  use_cr_https
+  use_a1pms_rest_https
+  use_simulator_https
+  use_ics_rest_https
+  use_prod_stub_https
 
-set_ics_debug
+  notificationurl=$CR_SERVICE_APP_PATH_0"/test"
 
-sleep_wait 120 "Let A1PMS configuration take effect"
+  clean_environment
+
+  start_kube_proxy
+
+  STD_NUM_RICS=2
+
+  start_http_proxy
+
+  start_ric_simulators $RIC_SIM_PREFIX"_g3" $STD_NUM_RICS STD_2.0.0
+
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+      :
+  else
+      start_mr #Just to prevent errors in the a1pms log...
+  fi
+
+  start_control_panel $SIM_GROUP/$CONTROL_PANEL_COMPOSE_DIR/$CONTROL_PANEL_CONFIG_FILE
+
+  if [ ! -z "$NRT_GATEWAY_APP_NAME" ]; then
+      start_gateway $SIM_GROUP/$NRT_GATEWAY_COMPOSE_DIR/$NRT_GATEWAY_CONFIG_FILE
+  fi
+
+  start_a1pms PROXY $SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_CONFIG_FILE
+
+
+
+  prepare_a1pms_config      NOSDNC  ".a1pms_config.json"
+
+  if [ $RUNMODE == "KUBE" ]; then
+      a1pms_load_config                       ".a1pms_config.json"
+  else
+      a1pms_api_put_configuration 200 ".a1pms_config.json"
+  fi
+
+  start_cr 1
+
+  start_prod_stub
+
+  start_ics PROXY $SIM_GROUP/$ICS_COMPOSE_DIR/$ICS_CONFIG_FILE
+
+  set_a1pms_trace
+
+  set_ics_debug
+
+  sleep_wait 120 "Let A1PMS configuration take effect"
+
+  a1pms_api_get_status 200
+
+  # Print the A1 version for STD 2.X
+  for ((i=1; i<=$STD_NUM_RICS; i++))
+  do
+      sim_print $RIC_SIM_PREFIX"_g3_"$i interface
+  done
+  total_policy_types=2
+  # Load the policytypes in std
+  for ((i=1; i<=$STD_NUM_RICS; i++))
+  do
+      sim_put_policy_type 201 $RIC_SIM_PREFIX"_g3_"$i STD_QOS_0_2_0 demo-testdata/STD2/sim_qos.json
+      sim_put_policy_type 201 $RIC_SIM_PREFIX"_g3_"$i STD_QOS2_0.1.0 demo-testdata/STD2/sim_qos2.json
+  done
+
+  #Check the number of schemas and the individual schemas in STD
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    total_policy_type_entries=$((STD_NUM_RICS * total_policy_types))
+    a1pms_equal json:policytypes ${total_policy_type_entries} 120
+  else
+    a1pms_equal json:policy-types ${total_policy_types} 120
+  fi
 
-a1pms_api_get_status 200
+  for ((i=1; i<=$STD_NUM_RICS; i++))
+  do
+    if [ "$A1PMS_VERSION" == "V3" ]; then
+      a1pms_equal json:policytypes?nearRtRicId=$RIC_SIM_PREFIX"_g3_"$i ${total_policy_types} 120
+    else
+      a1pms_equal json:policy-types?ric_id=$RIC_SIM_PREFIX"_g3_"$i ${total_policy_types} 120
+    fi
+  done
 
-# Print the A1 version for STD 2.X
-for ((i=1; i<=$STD_NUM_RICS; i++))
-do
-    sim_print $RIC_SIM_PREFIX"_g3_"$i interface
-done
-# Load the policytypes in std
-for ((i=1; i<=$STD_NUM_RICS; i++))
-do
-    sim_put_policy_type 201 $RIC_SIM_PREFIX"_g3_"$i STD_QOS_0_2_0 demo-testdata/STD2/sim_qos.json
-    sim_put_policy_type 201 $RIC_SIM_PREFIX"_g3_"$i STD_QOS2_0.1.0 demo-testdata/STD2/sim_qos2.json
-done
+  # Check the schemas in STD
+  for ((i=1; i<=$STD_NUM_RICS; i++))
+  do
+      a1pms_api_get_policy_type 200 STD_QOS_0_2_0 demo-testdata/STD2/qos-a1pms-modified.json
+      a1pms_api_get_policy_type 200 'STD_QOS2_0.1.0' demo-testdata/STD2/qos2-a1pms-modified.json
+  done
 
-#Check the number of schemas and the individual schemas in STD
-a1pms_equal json:policy-types 2 120
+  #Check the number of types
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    total_policy_type_entries=$((STD_NUM_RICS * total_policy_types))
+    a1pms_equal json:policytypes ${total_policy_type_entries} 300
+  else
+    a1pms_equal json:policy-types ${total_policy_types} 300
+  fi
 
-for ((i=1; i<=$STD_NUM_RICS; i++))
-do
-    a1pms_equal json:policy-types?ric_id=$RIC_SIM_PREFIX"_g3_"$i 2 120
-done
+  a1pms_api_put_service 201 "Emergency-response-app" 0 "$CR_SERVICE_APP_PATH_0/1"
 
-# Check the schemas in STD
-for ((i=1; i<=$STD_NUM_RICS; i++))
-do
-    a1pms_api_get_policy_type 200 STD_QOS_0_2_0 demo-testdata/STD2/qos-a1pms-modified.json
-    a1pms_api_get_policy_type 200 'STD_QOS2_0.1.0' demo-testdata/STD2/qos2-a1pms-modified.json
-done
-
-#Check the number of types
-a1pms_equal json:policy-types 2 300
-
-a1pms_api_put_service 201 "Emergency-response-app" 0 "$CR_SERVICE_APP_PATH_0/1"
+  # Create policies in STD
+  for ((i=1; i<=$STD_NUM_RICS; i++))
+  do
+      sim_generate_policy_uuid
+      if [ "$A1PMS_VERSION" == "V3" ]; then
+        a1pms_api_post_policy_v3 201 "Emergency-response-app" $RIC_SIM_PREFIX"_g3_"$i STD_QOS_0_2_0 $((2300+$i)) NOTRANSIENT $notificationurl demo-testdata/STD2/pi1_template.json 1
+        sim_generate_policy_uuid
+        a1pms_api_post_policy_v3 201 "Emergency-response-app" $RIC_SIM_PREFIX"_g3_"$i 'STD_QOS2_0.1.0' $((2400+$i)) NOTRANSIENT $notificationurl demo-testdata/STD2/pi1_template.json 1
+      else
+        a1pms_api_put_policy 201 "Emergency-response-app" $RIC_SIM_PREFIX"_g3_"$i STD_QOS_0_2_0 $((2300+$i)) NOTRANSIENT $notificationurl demo-testdata/STD2/pi1_template.json 1
+        sim_generate_policy_uuid
+        a1pms_api_put_policy 201 "Emergency-response-app" $RIC_SIM_PREFIX"_g3_"$i 'STD_QOS2_0.1.0' $((2400+$i)) NOTRANSIENT $notificationurl demo-testdata/STD2/pi1_template.json 1
+      fi
+  done
 
-# Create policies in STD
-for ((i=1; i<=$STD_NUM_RICS; i++))
-do
-    sim_generate_policy_uuid
-    a1pms_api_put_policy 201 "Emergency-response-app" $RIC_SIM_PREFIX"_g3_"$i STD_QOS_0_2_0 $((2300+$i)) NOTRANSIENT $notificationurl demo-testdata/STD2/pi1_template.json 1
-    sim_generate_policy_uuid
-    a1pms_api_put_policy 201 "Emergency-response-app" $RIC_SIM_PREFIX"_g3_"$i 'STD_QOS2_0.1.0' $((2400+$i)) NOTRANSIENT $notificationurl demo-testdata/STD2/pi1_template.json 1
-done
 
+  # Check the number of policies in STD
+  for ((i=1; i<=$STD_NUM_RICS; i++))
+  do
+      sim_equal $RIC_SIM_PREFIX"_g3_"$i num_instances 2
+  done
+
+  # Print calling hosts STD 2.X
+  for ((i=1; i<=$STD_NUM_RICS; i++))
+  do
+      sim_print $RIC_SIM_PREFIX"_g3_"$i remote_hosts
+      sim_contains_str $RIC_SIM_PREFIX"_g3_"$i remote_hosts proxy
+  done
+
+
+  CB_JOB="$PROD_STUB_SERVICE_PATH$PROD_STUB_JOB_CALLBACK"
+  CB_SV="$PROD_STUB_SERVICE_PATH$PROD_STUB_SUPERVISION_CALLBACK"
+  RIC_G1_1=$RIC_SIM_PREFIX"_g3_1"
+  RIC_G1_2=$RIC_SIM_PREFIX"_g3_2"
+  if [ $RUNMODE == "KUBE" ]; then
+      RIC_G1_1=$(get_kube_sim_host $RIC_G1_1)
+      RIC_G1_2=$(get_kube_sim_host $RIC_G1_2)
+  fi
+  TARGET1="$RIC_SIM_HTTPX://$RIC_G1_1:$RIC_SIM_PORT/datadelivery"
+  TARGET2="$RIC_SIM_HTTPX://$RIC_G1_1:$RIC_SIM_PORT/datadelivery"
+
+  STATUS1="$CR_SERVICE_APP_PATH_0/job1-status"
+  STATUS2="$CR_SERVICE_APP_PATH_0/job2-status"
+
+  prodstub_arm_producer 200 prod-a
+  prodstub_arm_type 200 prod-a type1
+  prodstub_arm_job_create 200 prod-a job1
+  prodstub_arm_job_create 200 prod-a job2
+
+  ### ics status
+  ics_api_service_status 200
+
+  if [[ "$ICS_FEATURE_LEVEL" == *"TYPE-SUBSCRIPTIONS"* ]]; then
+      #Type registration status callbacks
+      TYPESTATUS1="$CR_SERVICE_APP_PATH_0/type-status1"
+
+      ics_api_idc_put_subscription 201 subscription-id-1 owner1 $TYPESTATUS1
+
+      ics_api_idc_get_subscription_ids 200 owner1 subscription-id-1
+  fi
+
+  ## Setup prod-a
+  ics_api_edp_put_type_2 201 type1 testdata/ics/ei-type-1.json
+
+  ics_api_edp_put_producer_2 201 prod-a $CB_JOB/prod-a $CB_SV/prod-a type1
+
+  ics_api_edp_get_producer_2 200 prod-a $CB_JOB/prod-a $CB_SV/prod-a type1
+
+  ics_api_edp_get_producer_status 200 prod-a ENABLED
+
+
+  ## Create a job for prod-a
+  ## job1 - prod-a
+  ics_api_a1_put_job 201 job1 type1 $TARGET1 ricsim_g3_1 $STATUS1 testdata/ics/job-template.json
+
+  # Check the job data in the producer
+  prodstub_check_jobdata_3 200 prod-a job1 type1 $TARGET1 ricsim_g3_1 testdata/ics/job-template.json
+
+  ## Create a second job for prod-a
+  ## job2 - prod-a
+  ics_api_a1_put_job 201 job2 type1 $TARGET2 ricsim_g3_2 $STATUS2 testdata/ics/job-template.json
+
+  # Check the job data in the producer
+  prodstub_check_jobdata_3 200 prod-a job2 type1 $TARGET2 ricsim_g3_2 testdata/ics/job-template.json
+
+  # Arm producer prod-a for supervision failure
+  prodstub_arm_producer 200 prod-a 400
+
+  # Wait for producer prod-a to go disabled
+  ics_api_edp_get_producer_status 200 prod-a DISABLED 360
+
+  ics_equal json:data-producer/v1/info-producers 0 1000
+
+  if [[ "$ICS_FEATURE_LEVEL" == *"TYPE-SUBSCRIPTIONS"* ]]; then
+      cr_equal 0 received_callbacks 3 30
+      cr_api_check_all_ics_subscription_events 200 0 type-status1 type1 testdata/ics/ei-type-1.json REGISTERED
+      cr_api_check_all_ics_events 200 0 job1-status DISABLED
+      cr_api_check_all_ics_events 200 0 job2-status DISABLED
+  else
+      cr_equal 0 received_callbacks 2 30
+      cr_api_check_all_ics_events 200 0 job1-status DISABLED
+      cr_api_check_all_ics_events 200 0 job2-status DISABLED
+  fi
 
-# Check the number of policies in STD
-for ((i=1; i<=$STD_NUM_RICS; i++))
-do
-    sim_equal $RIC_SIM_PREFIX"_g3_"$i num_instances 2
-done
+  cr_contains_str 0 remote_hosts $HTTP_PROXY_APP_NAME
 
-# Print calling hosts STD 2.X
-for ((i=1; i<=$STD_NUM_RICS; i++))
-do
-    sim_print $RIC_SIM_PREFIX"_g3_"$i remote_hosts
-    sim_contains_str $RIC_SIM_PREFIX"_g3_"$i remote_hosts proxy
+  check_a1pms_logs
+  check_ics_logs
 done
-
-
-CB_JOB="$PROD_STUB_SERVICE_PATH$PROD_STUB_JOB_CALLBACK"
-CB_SV="$PROD_STUB_SERVICE_PATH$PROD_STUB_SUPERVISION_CALLBACK"
-RIC_G1_1=$RIC_SIM_PREFIX"_g3_1"
-RIC_G1_2=$RIC_SIM_PREFIX"_g3_2"
-if [ $RUNMODE == "KUBE" ]; then
-    RIC_G1_1=$(get_kube_sim_host $RIC_G1_1)
-    RIC_G1_2=$(get_kube_sim_host $RIC_G1_2)
-fi
-TARGET1="$RIC_SIM_HTTPX://$RIC_G1_1:$RIC_SIM_PORT/datadelivery"
-TARGET2="$RIC_SIM_HTTPX://$RIC_G1_1:$RIC_SIM_PORT/datadelivery"
-
-STATUS1="$CR_SERVICE_APP_PATH_0/job1-status"
-STATUS2="$CR_SERVICE_APP_PATH_0/job2-status"
-
-prodstub_arm_producer 200 prod-a
-prodstub_arm_type 200 prod-a type1
-prodstub_arm_job_create 200 prod-a job1
-prodstub_arm_job_create 200 prod-a job2
-
-### ics status
-ics_api_service_status 200
-
-if [[ "$ICS_FEATURE_LEVEL" == *"TYPE-SUBSCRIPTIONS"* ]]; then
-    #Type registration status callbacks
-    TYPESTATUS1="$CR_SERVICE_APP_PATH_0/type-status1"
-
-    ics_api_idc_put_subscription 201 subscription-id-1 owner1 $TYPESTATUS1
-
-    ics_api_idc_get_subscription_ids 200 owner1 subscription-id-1
-fi
-
-## Setup prod-a
-ics_api_edp_put_type_2 201 type1 testdata/ics/ei-type-1.json
-
-ics_api_edp_put_producer_2 201 prod-a $CB_JOB/prod-a $CB_SV/prod-a type1
-
-ics_api_edp_get_producer_2 200 prod-a $CB_JOB/prod-a $CB_SV/prod-a type1
-
-ics_api_edp_get_producer_status 200 prod-a ENABLED
-
-
-## Create a job for prod-a
-## job1 - prod-a
-ics_api_a1_put_job 201 job1 type1 $TARGET1 ricsim_g3_1 $STATUS1 testdata/ics/job-template.json
-
-# Check the job data in the producer
-prodstub_check_jobdata_3 200 prod-a job1 type1 $TARGET1 ricsim_g3_1 testdata/ics/job-template.json
-
-## Create a second job for prod-a
-## job2 - prod-a
-ics_api_a1_put_job 201 job2 type1 $TARGET2 ricsim_g3_2 $STATUS2 testdata/ics/job-template.json
-
-# Check the job data in the producer
-prodstub_check_jobdata_3 200 prod-a job2 type1 $TARGET2 ricsim_g3_2 testdata/ics/job-template.json
-
-# Arm producer prod-a for supervision failure
-prodstub_arm_producer 200 prod-a 400
-
-# Wait for producer prod-a to go disabled
-ics_api_edp_get_producer_status 200 prod-a DISABLED 360
-
-ics_equal json:data-producer/v1/info-producers 0 1000
-
-if [[ "$ICS_FEATURE_LEVEL" == *"TYPE-SUBSCRIPTIONS"* ]]; then
-    cr_equal 0 received_callbacks 3 30
-    cr_api_check_all_ics_subscription_events 200 0 type-status1 type1 testdata/ics/ei-type-1.json REGISTERED
-    cr_api_check_all_ics_events 200 0 job1-status DISABLED
-    cr_api_check_all_ics_events 200 0 job2-status DISABLED
-else
-    cr_equal 0 received_callbacks 2 30
-    cr_api_check_all_ics_events 200 0 job1-status DISABLED
-    cr_api_check_all_ics_events 200 0 job2-status DISABLED
-fi
-
-cr_contains_str 0 remote_hosts $HTTP_PROXY_APP_NAME
-
-check_a1pms_logs
-check_ics_logs
-
-#### TEST COMPLETE ####
+  #### TEST COMPLETE ####
 
 store_logs          END
 
 print_result
 
-auto_clean_environment
\ No newline at end of file
+auto_clean_environment
index 3e07eea..c8d3f6e 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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.
@@ -32,7 +33,7 @@ KUBE_PRESTARTED_IMAGES=" "
 CONDITIONALLY_IGNORED_IMAGES=""
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON "
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER"
 
@@ -142,7 +143,13 @@ for __nb_httpx in $NB_TESTED_PROTOCOLS ; do
         controller_api_get_A1_policy_status 200 OSC ricsim_g1_1 1 4000
         controller_api_get_A1_policy_status 200 STD ricsim_g2_1 5000
 
-        VAL='NOT IN EFFECT'
+        if [[ $TEST_ENV_PROFILE =~ ^ORAN-[A-H]$  || $TEST_ENV_PROFILE =~ ^ONAP-[A-L]$ ]]; then
+            VAL='NOT IN EFFECT'
+            VAL2="false"
+        else
+            VAL='NOT_ENFORCED'
+            VAL2="OTHER_REASON"
+        fi
         controller_api_get_A1_policy_status 200 OSC ricsim_g1_1 1 4000 "$VAL" "false"
         controller_api_get_A1_policy_status 200 STD ricsim_g2_1 5000 "UNDEFINED"
 
index 3268e5b..a14a0bd 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES=""
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index bf8ca5f..1cdda4e 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index 66b7139..7f18089 100755 (executable)
@@ -1,7 +1,8 @@
 #!/usr/bin/env bash
 
 #  ============LICENSE_START===============================================
-#  Copyright (C) 2020 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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.
@@ -34,7 +35,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES=""
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index 3f50abe..3222da1 100755 (executable)
@@ -1,7 +1,8 @@
 #!/usr/bin/env bash
 
 #  ============LICENSE_START===============================================
-#  Copyright (C) 2020 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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.
@@ -34,7 +35,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES=""
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index 1d451ca..c0205f7 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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.
@@ -29,7 +30,7 @@ DOCKER_INCLUDED_IMAGES="CP CR MR A1PMS RICSIM KUBEPROXY"
 CONDITIONALLY_IGNORED_IMAGES=""
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER"
 
index a9faebc..a580f09 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES=""
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index 5050d42..d52a12c 100755 (executable)
@@ -1,7 +1,8 @@
 #!/bin/bash
 
 #  ============LICENSE_START===============================================
-#  Copyright (C) 2021 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2021-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES=""
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index 62c6d1d..a6914b4 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index 1346d69..544d65f 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index f03199e..2d0430d 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index a8c09cb..5c1c016 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023-2024 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
@@ -59,156 +60,223 @@ sim_generate_policy_uuid
 
 notificationurl=$CR_SERVICE_APP_PATH_0"/test"
 
-for __httpx in $TESTED_PROTOCOLS ; do
-    for interface in $TESTED_VARIANTS ; do
-
-        echo "#####################################################################"
-        echo "#####################################################################"
-        echo "### Testing a1pms: "$interface" and "$__httpx
-        echo "#####################################################################"
-        echo "#####################################################################"
-
-        if [ $__httpx == "HTTPS" ]; then
-            use_cr_https
-            use_simulator_https
-            if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-                :
-            else
-                use_mr_https
-            fi
-            if [[ $interface = *"SDNC"* ]]; then
-                if [[ "$SDNC_FEATURE_LEVEL" == *"NO_NB_HTTPS"* ]]; then
-                    deviation "SDNC does not support NB https"
-                    use_sdnc_http
+VERSIONS_TO_RUN=2
+
+if [ -n "$A1PMS_V3_FLAG" ] && [ "${A1PMS_V3_FLAG,,}" == "true" ]; then
+  VERSIONS_TO_RUN=3
+fi
+
+for version in $(seq 2 $VERSIONS_TO_RUN); do
+  if [ "$version" == "3" ]; then
+    if [ -n "$A1PMS_V3" ] && [ -n "$A1PMS_API_PREFIX_V3" ] && [ -n "$A1PMS_ALIVE_URL_V3" ]; then
+      export A1PMS_VERSION="$A1PMS_V3"
+      export A1PMS_API_PREFIX="$A1PMS_API_PREFIX_V3"
+      export A1PMS_ALIVE_URL="$A1PMS_API_PREFIX$A1PMS_ALIVE_URL_V3"
+    else
+      echo "One/All parameters not set in env file (<A1PMS_V3>, <A1PMS_API_PREFIX_V3>, <A1PMS_ALIVE_URL_V3>)"
+      break
+    fi
+  fi
+    for __httpx in $TESTED_PROTOCOLS ; do
+        for interface in $TESTED_VARIANTS ; do
+
+            echo "#####################################################################"
+            echo "#####################################################################"
+            echo "### Testing a1pms: "$interface" and "$__httpx" with a1pms V"$version
+            echo "#####################################################################"
+            echo "#####################################################################"
+
+            if [ $__httpx == "HTTPS" ]; then
+                use_cr_https
+                use_simulator_https
+                if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+                    :
                 else
-                    use_sdnc_https
+                    use_mr_https
                 fi
-            fi
-            use_a1pms_rest_https
-        else
-            use_cr_http
-            use_simulator_http
-            if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-                :
+                if [[ $interface = *"SDNC"* ]]; then
+                    if [[ "$SDNC_FEATURE_LEVEL" == *"NO_NB_HTTPS"* ]]; then
+                        deviation "SDNC does not support NB https"
+                        use_sdnc_http
+                    else
+                        use_sdnc_https
+                    fi
+                fi
+                use_a1pms_rest_https
             else
-                use_mr_http
-            fi
-            if [[ $interface = *"SDNC"* ]]; then
-                use_sdnc_http
+                use_cr_http
+                use_simulator_http
+                if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+                    :
+                else
+                    use_mr_http
+                fi
+                if [[ $interface = *"SDNC"* ]]; then
+                    use_sdnc_http
+                fi
+                use_a1pms_rest_http
             fi
-            use_a1pms_rest_http
-        fi
 
-        # Clean container and start all needed containers #
-        clean_environment
+            # Clean container and start all needed containers #
+            clean_environment
 
-        start_kube_proxy
+            start_kube_proxy
 
-        start_ric_simulators ricsim_g1 $NUM_RICS OSC_2.1.0
+            start_ric_simulators ricsim_g1 $NUM_RICS OSC_2.1.0
+
+            start_control_panel $SIM_GROUP/$CONTROL_PANEL_COMPOSE_DIR/$CONTROL_PANEL_CONFIG_FILE
+
+            if [ ! -z "$NRT_GATEWAY_APP_NAME" ]; then
+                start_gateway $SIM_GROUP/$NRT_GATEWAY_COMPOSE_DIR/$NRT_GATEWAY_CONFIG_FILE
+            fi
 
-        start_control_panel $SIM_GROUP/$CONTROL_PANEL_COMPOSE_DIR/$CONTROL_PANEL_CONFIG_FILE
+            start_a1pms NORPOXY $SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_CONFIG_FILE
 
-        if [ ! -z "$NRT_GATEWAY_APP_NAME" ]; then
-            start_gateway $SIM_GROUP/$NRT_GATEWAY_COMPOSE_DIR/$NRT_GATEWAY_CONFIG_FILE
-        fi
+            set_a1pms_debug
 
-        start_a1pms NORPOXY $SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_CONFIG_FILE
 
-        set_a1pms_debug
 
+            if [[ $interface = *"SDNC"* ]]; then
+                start_sdnc
+                controller_api_wait_for_status_ok 200 ricsim_g1_1
+                prepare_a1pms_config      SDNC  ".a1pms_config.json"
+            else
+                prepare_a1pms_config      NOSDNC  ".a1pms_config.json"
+            fi
+
+            if [ $RUNMODE == "KUBE" ]; then
+                a1pms_load_config                       ".a1pms_config.json"
+            else
+                a1pms_api_put_configuration 200 ".a1pms_config.json"
+            fi
 
+            if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+                :
+            else
+                start_mr #Just to prevent errors in the a1pms log...
+            fi
 
-        if [[ $interface = *"SDNC"* ]]; then
-            start_sdnc
-            controller_api_wait_for_status_ok 200 ricsim_g1_1
-            prepare_a1pms_config      SDNC  ".a1pms_config.json"
-        else
-            prepare_a1pms_config      NOSDNC  ".a1pms_config.json"
-        fi
+            start_cr 1
 
-        if [ $RUNMODE == "KUBE" ]; then
-            a1pms_load_config                       ".a1pms_config.json"
-        else
-            a1pms_api_put_configuration 200 ".a1pms_config.json"
-        fi
+            sleep_wait 120 "Let A1PMS configuration take effect"
 
-        if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-            :
-        else
-            start_mr #Just to prevent errors in the a1pms log...
-        fi
+            a1pms_api_get_status 200
 
-        start_cr 1
+            for ((i=1; i<=$NUM_RICS; i++))
+            do
+                sim_print ricsim_g1_$i interface
+            done
 
-        sleep_wait 120 "Let A1PMS configuration take effect"
+            echo "Load policy type in group 1 simulators"
+            for ((i=1; i<=$NUM_RICS; i++))
+            do
+                sim_put_policy_type 201 ricsim_g1_$i 1 testdata/OSC/sim_1.json
+            done
 
-        a1pms_api_get_status 200
+            if [ "$A1PMS_VERSION" == "V2" ]; then
+              a1pms_equal json:policy-types 1 300  #Wait for the a1pms to refresh types from the simulator
+            elif [ "$A1PMS_VERSION" == "V3" ]; then
+              a1pms_equal json:policytypes 20 300
+            fi
 
-        for ((i=1; i<=$NUM_RICS; i++))
-        do
-            sim_print ricsim_g1_$i interface
-        done
+            a1pms_api_put_service 201 "serv1" 600 "$CR_SERVICE_APP_PATH_0/1"
 
-        echo "Load policy type in group 1 simulators"
-        for ((i=1; i<=$NUM_RICS; i++))
-        do
-            sim_put_policy_type 201 ricsim_g1_$i 1 testdata/OSC/sim_1.json
-        done
+            echo "Check the number of types in the a1pms for each ric is 1"
+            for ((i=1; i<=$NUM_RICS; i++))
+            do
+              if [ "$A1PMS_VERSION" == "V2" ]; then
+                a1pms_equal json:policy-types?ric_id=ricsim_g1_$i 1 120
+              elif [ "$A1PMS_VERSION" == "V3" ]; then
+                a1pms_equal json:policytypes?nearRtRicId=ricsim_g1_$i 1 120
+              fi
+            done
 
-         a1pms_equal json:policy-types 1 300  #Wait for the a1pms to refresh types from the simulator
+            START_ID=2000
 
-        a1pms_api_put_service 201 "serv1" 600 "$CR_SERVICE_APP_PATH_0/1"
+            start_timer "Create $((NUM_POLICIES_PER_RIC*$NUM_RICS)) polices over $interface using $__httpx and V$version policymanagementservice"
 
-        echo "Check the number of types in the a1pms for each ric is 1"
-        for ((i=1; i<=$NUM_RICS; i++))
-        do
-            a1pms_equal json:policy-types?ric_id=ricsim_g1_$i 1 120
-        done
+            if [ "$A1PMS_VERSION" == "V3" ]; then
+              a1pms_api_post_policy_parallel 201 "serv1" ricsim_g1_ $NUM_RICS 1 $START_ID NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json $NUM_POLICIES_PER_RIC 7
+            else
+              a1pms_api_put_policy_parallel 201 "serv1" ricsim_g1_ $NUM_RICS 1 $START_ID NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json $NUM_POLICIES_PER_RIC 7
+            fi
 
-        START_ID=2000
+            print_timer "Create $((NUM_POLICIES_PER_RIC*$NUM_RICS)) polices over $interface using $__httpx and V$version policymanagementservice"
 
-        start_timer "Create $((NUM_POLICIES_PER_RIC*$NUM_RICS)) polices over $interface using "$__httpx
+            INSTANCES=$(($NUM_RICS*$NUM_POLICIES_PER_RIC))
+            a1pms_equal json:policies $INSTANCES
 
-        a1pms_api_put_policy_parallel 201 "serv1" ricsim_g1_ $NUM_RICS 1 $START_ID NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json $NUM_POLICIES_PER_RIC 7
+            for ((i=1; i<=$NUM_RICS; i++))
+            do
+                sim_equal ricsim_g1_$i num_instances $NUM_POLICIES_PER_RIC
+            done
 
-        print_timer "Create $((NUM_POLICIES_PER_RIC*$NUM_RICS)) polices over $interface using "$__httpx
+            if [ "$A1PMS_VERSION" == "V3" ]; then
+              allPolicyIds_file_path="./tmp/.policyIds.split.res.txt"
+              allPolicies_file_path="./tmp/.allPolicies.get.res.json"
+              res="$(__do_curl $A1PMS_SERVICE_PATH$A1PMS_API_PREFIX"/v1/policies")"
+              echo $res > "./tmp/.allPolicies.get.res.json"
+              jq -r '.[].policyId' $allPolicies_file_path > $allPolicyIds_file_path
+            fi
 
-        INSTANCES=$(($NUM_RICS*$NUM_POLICIES_PER_RIC))
-        a1pms_equal json:policies $INSTANCES
+            if [ "$A1PMS_VERSION" == "V3" ]; then
+              start_timer "Update $((NUM_POLICIES_PER_RIC*$NUM_RICS)) polices over $interface using $__httpx and V$version policymanagementservice"
+              a1pms_api_update_policy_parallel 200 "serv1" ricsim_g1_ $NUM_RICS 1 14000 NOTRANSIENT $notificationurl testdata/OSC/pi1_template.json $NUM_POLICIES_PER_RIC 7 $allPolicyIds_file_path
+              print_timer "Update $((NUM_POLICIES_PER_RIC*$NUM_RICS)) polices over $interface using $__httpx and V$version policymanagementservice"
+            fi
 
-        for ((i=1; i<=$NUM_RICS; i++))
-        do
-            sim_equal ricsim_g1_$i num_instances $NUM_POLICIES_PER_RIC
-        done
+            start_timer "GET $((NUM_POLICIES_PER_RIC*$NUM_RICS)) polices over $interface using $__httpx and V$version policymanagementservice"
 
-        start_timer "Delete $((NUM_POLICIES_PER_RIC*$NUM_RICS)) polices over $interface using "$__httpx
+            if [ "$A1PMS_VERSION" == "V3" ]; then
+              a1pms_api_get_policy_parallel_v3 200 $NUM_RICS $allPolicyIds_file_path $START_ID $NUM_POLICIES_PER_RIC 7
+            else
+              a1pms_api_get_policy_parallel 200 $NUM_RICS $START_ID $NUM_POLICIES_PER_RIC 7
+            fi
 
-        a1pms_api_delete_policy_parallel 204 $NUM_RICS $START_ID $NUM_POLICIES_PER_RIC 7
+            print_timer "GET $((NUM_POLICIES_PER_RIC*$NUM_RICS)) polices over $interface using $__httpx and V$version policymanagementservice"
 
-        print_timer "Delete $((NUM_POLICIES_PER_RIC*$NUM_RICS)) polices over $interface using "$__httpx
+            INSTANCES=$(($NUM_RICS*$NUM_POLICIES_PER_RIC))
+            a1pms_equal json:policies $INSTANCES
 
-        a1pms_equal json:policies 0
+            for ((i=1; i<=$NUM_RICS; i++))
+            do
+                sim_equal ricsim_g1_$i num_instances $NUM_POLICIES_PER_RIC
+            done
 
-        for ((i=1; i<=$NUM_RICS; i++))
-        do
-            sim_equal ricsim_g1_$i num_instances 0
-        done
+            start_timer "Delete $((NUM_POLICIES_PER_RIC*$NUM_RICS)) polices over $interface using $__httpx and V$version policymanagementservice"
 
-        for ((i=1; i<=$NUM_RICS; i++))
-        do
-            if [ $interface == "REST+SDNC" ]; then
-                sim_contains_str ricsim_g1_$i remote_hosts $SDNC_APP_NAME
+            if [ "$A1PMS_VERSION" == "V3" ]; then
+              a1pms_api_delete_policy_parallel_v3 204 $NUM_RICS $allPolicyIds_file_path $START_ID $NUM_POLICIES_PER_RIC 7
             else
-                sim_contains_str ricsim_g1_$i remote_hosts $A1PMS_APP_NAME
+              a1pms_api_delete_policy_parallel 204 $NUM_RICS $START_ID $NUM_POLICIES_PER_RIC 7
             fi
-        done
 
-        check_a1pms_logs
-        if [[ $interface = *"SDNC"* ]]; then
-            check_sdnc_logs
-        fi
+            print_timer "Delete $((NUM_POLICIES_PER_RIC*$NUM_RICS)) polices over $interface using $__httpx and V$version policymanagementservice"
+
+            a1pms_equal json:policies 0
 
-        store_logs          "${__httpx}__${interface}"
+            for ((i=1; i<=$NUM_RICS; i++))
+            do
+                sim_equal ricsim_g1_$i num_instances 0
+            done
+
+            for ((i=1; i<=$NUM_RICS; i++))
+            do
+                if [ $interface == "REST+SDNC" ]; then
+                    sim_contains_str ricsim_g1_$i remote_hosts $SDNC_APP_NAME
+                else
+                    sim_contains_str ricsim_g1_$i remote_hosts $A1PMS_APP_NAME
+                fi
+            done
+
+            check_a1pms_logs
+            if [[ $interface = *"SDNC"* ]]; then
+                check_sdnc_logs
+            fi
+
+            store_logs          "${__httpx}__${interface}"
+
+        done
 
     done
 
index 19891a5..8634dbd 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index 9a8f055..3dc724d 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON "
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
@@ -282,11 +283,17 @@ for interface in $TESTED_VARIANTS ; do
     done
 
     # Check status OSC
-    VAL='NOT IN EFFECT'
+    if [[ $TEST_ENV_PROFILE =~ ^ORAN-[A-H] ]] || [[ $TEST_ENV_PROFILE =~ ^ONAP-[A-L] ]]; then
+      VAL='NOT IN EFFECT'
+      VAL2="false"
+    else
+      VAL='NOT_ENFORCED'
+      VAL2="OTHER_REASON"
+    fi
     for ((i=1; i<=$OSC_NUM_RICS; i++))
     do
-        a1pms_api_get_policy_status 200 $((3000+$i)) OSC "$VAL" "false"
-        a1pms_api_get_policy_status 200 $((4000+$i)) OSC "$VAL" "false"
+        a1pms_api_get_policy_status 200 $((3000+$i)) OSC "$VAL" "$VAL2"
+        a1pms_api_get_policy_status 200 $((4000+$i)) OSC "$VAL" "$VAL2"
     done
 
     # Note: Status callback is not tested since this callback (http POST) is made from the
index 6e4bd44..a180b63 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index 57bc2cb..49a5c93 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES="NGW"
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ONAP-JAKARTA ONAP-KOHN ONAP-LONDON  ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ONAP-KOHN ONAP-LONDON ONAP-MONTREAL  ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index 5ea64bc..32529a1 100644 (file)
@@ -1,3 +1,20 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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=================================================
+
 # Overview
 
 The bash scripts in this dir are intended for function test of the Non-RT RIC in different configurations, using simulators when needed for the external interfaces.
@@ -22,7 +39,7 @@ If temporary changes are needed to the settings in a profile file, use an overri
 
 A test script, for example FTC1, is executed from the cmd line using the script filename and one or more parameters:
 
- >```./FTC1.sh remote docker --env-file ../common/test_env-oran-h-release.sh```
+ >```./FTC1.sh remote docker --env-file ../common/test_env-oran-i-release.sh```
 
 Note that this script will use the staging images. Once the release images are available,add the parameter "release" to run with released images.
 
@@ -34,17 +51,11 @@ The test scripts produce quite a number of logs; all container logs, a log of al
 
 To test all components on a very basic level, run the demo test script(s) for the desired release.
 Note that oran tests only include components from oran (exception is the onap sdnc).
-Note that onap test uses components from onap combined with released oran components available at that onap release (e.g. London contains onap images from London and oran images (released images from h-release).
+Note that onap test uses components from onap combined with released oran components available at that onap release (e.g. Montreal contains onap images from Montreal and oran images (released images from i-release).
 
 In general, the test scripts support the current ongoing release as well as two previous releases.
 
 
-ORAN F-RELEASE
-=========
->```./PM_EI_DEMO.sh remote-remove  docker  release  --env-file ../common/test_env-oran-f-release.sh  --use-release-image SDNC```
-
->```./PM_EI_DEMO.sh remote-remove  kube  release  --env-file ../common/test_env-oran-f-release.sh  --use-release-image SDNC```
-
 ORAN G-RELEASE
 =========
 >```./PM_EI_DEMO.sh remote-remove  docker  release  --env-file ../common/test_env-oran-g-release.sh  --use-release-image SDNC```
@@ -53,16 +64,15 @@ ORAN G-RELEASE
 
 ORAN H-RELEASE
 =========
->```./PM_EI_DEMO.sh remote-remove  docker  --env-file ../common/test_env-oran-h-release.sh --use-release-image SDNC```
-
->```./PM_EI_DEMO.sh remote-remove  kube  --env-file ../common/test_env-oran-h-release.sh --use-release-image SDNC```
+>```./PM_EI_DEMO.sh remote-remove  docker  release  --env-file ../common/test_env-oran-h-release.sh  --use-release-image SDNC```
 
+>```./PM_EI_DEMO.sh remote-remove  kube  release  --env-file ../common/test_env-oran-h-release.sh  --use-release-image SDNC```
 
-ONAP JAKARTA
-=============
->```./PM_EI_DEMO.sh remote-remove  docker  release  --env-file ../common/test_env-onap-jakarta.sh```
+ORAN I-RELEASE
+=========
+>```./PM_EI_DEMO.sh remote-remove  docker  --env-file ../common/test_env-oran-i-release.sh --use-release-image SDNC```
 
->```./PM_EI_DEMO.sh remote-remove  kube  release  --env-file ../common/test_env-onap-jakarta.sh```
+>```./PM_EI_DEMO.sh remote-remove  kube  --env-file ../common/test_env-oran-i-release.sh --use-release-image SDNC```
 
 
 ONAP KOHN
@@ -74,9 +84,16 @@ ONAP KOHN
 
 ONAP LONDON
 =============
->```./PM_EI_DEMO.sh remote-remove  docker  --env-file ../common/test_env-onap-london.sh```
+>```./PM_EI_DEMO.sh remote-remove  docker  release  --env-file ../common/test_env-onap-london.sh```
 
->```./PM_EI_DEMO.sh remote-remove  kube  --env-file ../common/test_env-onap-london.sh```
+>```./PM_EI_DEMO.sh remote-remove  kube  release  --env-file ../common/test_env-onap-london.sh```
+
+
+ONAP MONTREAL
+=============
+>```./PM_EI_DEMO.sh remote-remove  docker  --env-file ../common/test_env-onap-montreal.sh```
+
+>```./PM_EI_DEMO.sh remote-remove  kube  --env-file ../common/test_env-onap-montreal.sh```
 
 
 ## Useful features
@@ -139,7 +156,7 @@ The solution is to use another external registry as a temporary registry.
 Basically, the test script pulls the images, re-tag them and pushes them to the temporary registry. Locally built images are also pushed to the same report.
 All pods started by the script will then pull correct images from the temporary registry (a docker hub registry works fine - requires login to push images though). In this way, the test script has full control over which images are actually used and it is also guaranteed that multiple pod using the same image version actually use the same image.
 
-In addition, the kubernetes config file shall be downloaded from the master node of the cluster prior to the test - the config file is used by the command kubectrl to access the cluster.
+In addition, the kubernetes config file shall be downloaded from the master node of the cluster prior to the test - the config file is used by the command kubectl to access the cluster.
 
 The following flags shall be added to the command: `--kubeconfig <config-file> --image-repo <repo-address> --repo-policy local\|remote`
 The image repo flag shall be the name of the repo (in case of docker hub -  e.g. "myprivateregistry") and repo policy shall be set to `remote` indicating that all images shall use the temporary registry.
@@ -225,20 +242,3 @@ print_result
 store_logs          END
 
 ```
-
------------------------------------------------------------
-
-## License
-
-Copyright (C) 2020-2023 Nordix Foundation. 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.
index d53af8f..ef97938 100644 (file)
@@ -31,4 +31,6 @@ suite_setup
 
 ##########################################
 
-suite_complete
\ No newline at end of file
+suite_complete
+
+exit
diff --git a/test/auto-test/mediator-override-adapter.sh b/test/auto-test/mediator-override-adapter.sh
new file mode 100644 (file)
index 0000000..1b455a7
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/bash
+################################################################################                                     
+#   Copyright (C) 2024 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.                                             #
+################################################################################
+
+A1PMS_NOSDNC_ADAPTER_CLASS="org.onap.ccsdk.oran.a1policymanagementservice.clients.A1MediatorAdapterI"  # Adapter Java class
+A1PMS_SDNC_ADAPTER_CLASS="org.onap.ccsdk.oran.a1policymanagementservice.clients.A1MediatorAdapterICCSDK"  # Adapter Java class
+A1PMS_ADAPTER_POLICY_TYPE="1" # Policy type for adapter
\ No newline at end of file
index faef149..b020c49 100644 (file)
@@ -1,7 +1,7 @@
 #!/bin/bash
 ################################################################################
 #   Copyright (c) 2023 Nordix Foundation.                                      #
-#                                                                              #
+#   Copyright (C) 2024 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                                    #
@@ -14,6 +14,5 @@
 #   See the License for the specific language governing permissions and        #
 #   limitations under the License.                                             #
 ################################################################################
-
-A1PMS_ADAPTER_CLASS=""         # adapter java class
-A1PMS_ADAPTER_POLICY_NAME=""   # policy type for adapter
+A1PMS_ADAPTER_CLASS=""         # Adapter Java class
+A1PMS_ADAPTER_POLICY_TYPE=""   # Policy type for adapter
\ No newline at end of file
index 3b4f3db..250b433 100755 (executable)
@@ -1,7 +1,8 @@
 #!/bin/bash
 
 #  ============LICENSE_START===============================================
-#  Copyright (C) 2021 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2021-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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,7 +34,7 @@ KUBE_PRESTARTED_IMAGES=""
 CONDITIONALLY_IGNORED_IMAGES=""
 
 #Supported test environment profiles
-SUPPORTED_PROFILES="ORAN-F-RELEASE ORAN-G-RELEASE ORAN-H-RELEASE"
+SUPPORTED_PROFILES="ORAN-G-RELEASE ORAN-H-RELEASE ORAN-I-RELEASE"
 #Supported run modes
 SUPPORTED_RUNMODES="DOCKER KUBE"
 
index d0ad54a..e93e1a7 100644 (file)
@@ -1,8 +1,31 @@
 #!/bin/bash
 
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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=================================================
+#
+
 TEST_DIRECTORY="test/auto-test"
 TEST_SCRIPT="./Suite-Verify-jobs.sh"
 DOCKER_COMPOSE_VERSION="v2.21.0"
+PULL_IMAGE_TYPE="remote-remove"
+RUN_MODE="docker"
+IMAGE_VERSION="release"
+ENV_FLAG="--env-file"
+ENV_FILE="../common/test_env-oran-h-release.sh"
 
 # Check if jq is installed, and install it if not
 if ! command -v jq &> /dev/null; then
@@ -32,7 +55,8 @@ fi
 
 cd "$TEST_DIRECTORY"
 sudo chmod 775 "$TEST_SCRIPT"
-"$TEST_SCRIPT" remote-remove docker release --env-file ../common/test_env-oran-h-release.sh
+"$TEST_SCRIPT" $PULL_IMAGE_TYPE $RUN_MODE $IMAGE_VERSION $ENV_FLAG $ENV_FILE
+exit_val=$?
 
 # Remove docker-compose after tests are done
 if command -v docker-compose &> /dev/null; then
@@ -44,3 +68,5 @@ if command -v jq &> /dev/null; then
     echo "Removing jq..."
     sudo apt-get remove -y jq
 fi
+
+exit $exit_val
old mode 100644 (file)
new mode 100755 (executable)
index e065034..5fb6e25
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2021-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2024 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.
@@ -25,7 +26,7 @@
 # arg: <image-tag-suffix> (selects staging, snapshot, release etc)
 # <image-tag-suffix> is present only for images with staging, snapshot,release tags
 __A1PMS_imagesetup() {
-       __check_and_create_image_var A1PMS "A1PMS_IMAGE" "A1PMS_IMAGE_BASE" "A1PMS_IMAGE_TAG" $1 "$A1PMS_DISPLAY_NAME" ""
+  __check_and_create_image_var A1PMS "A1PMS_IMAGE" "A1PMS_IMAGE_BASE" "A1PMS_IMAGE_TAG" $1 "$A1PMS_DISPLAY_NAME" ""
 }
 
 # Pull image from remote repo or use locally built image
@@ -34,62 +35,62 @@ __A1PMS_imagesetup() {
 # <pull-policy-original> Shall be used for images that does not allow overriding
 # Both var may contain: 'remote', 'remote-remove' or 'local'
 __A1PMS_imagepull() {
-       __check_and_pull_image $1 "$A1PMS_DISPLAY_NAME" $A1PMS_APP_NAME A1PMS_IMAGE
+  __check_and_pull_image $1 "$A1PMS_DISPLAY_NAME" $A1PMS_APP_NAME A1PMS_IMAGE
 }
 
 # Build image (only for simulator or interfaces stubs owned by the test environment)
 # arg: <image-tag-suffix> (selects staging, snapshot, release etc)
 # <image-tag-suffix> is present only for images with staging, snapshot,release tags
 __A1PMS_imagebuild() {
-       echo -e $RED" Image for app A1PMS shall never be built"$ERED
+  echo -e $RED" Image for app A1PMS shall never be built"$ERED
 }
 
 # Generate a string for each included image using the app display name and a docker images format string
 # If a custom image repo is used then also the source image from the local repo is listed
 # arg: <docker-images-format-string> <file-to-append>
 __A1PMS_image_data() {
-       echo -e "$A1PMS_DISPLAY_NAME\t$(docker images --format $1 $A1PMS_IMAGE)" >>   $2
-       if [ ! -z "$A1PMS_IMAGE_SOURCE" ]; then
-               echo -e "-- source image --\t$(docker images --format $1 $A1PMS_IMAGE_SOURCE)" >>   $2
-       fi
+  echo -e "$A1PMS_DISPLAY_NAME\t$(docker images --format $1 $A1PMS_IMAGE)" >>$2
+  if [ ! -z "$A1PMS_IMAGE_SOURCE" ]; then
+    echo -e "-- source image --\t$(docker images --format $1 $A1PMS_IMAGE_SOURCE)" >>$2
+  fi
 }
 
 # Scale kubernetes resources to zero
 # All resources shall be ordered to be scaled to 0, if relevant. If not relevant to scale, then do no action.
 # This function is called for apps fully managed by the test script
 __A1PMS_kube_scale_zero() {
-       __kube_scale_all_resources $KUBE_NONRTRIC_NAMESPACE autotest A1PMS
+  __kube_scale_all_resources $KUBE_NONRTRIC_NAMESPACE autotest A1PMS
 }
 
 # Scale kubernetes resources to zero and wait until this has been accomplished, if relevant. If not relevant to scale, then do no action.
 # This function is called for pre-started apps not managed by the test script.
 __A1PMS_kube_scale_zero_and_wait() {
-       __kube_scale_and_wait_all_resources $KUBE_NONRTRIC_NAMESPACE app "$KUBE_NONRTRIC_NAMESPACE"-policymanagementservice
+  __kube_scale_and_wait_all_resources $KUBE_NONRTRIC_NAMESPACE app "$KUBE_NONRTRIC_NAMESPACE"-policymanagementservice
 }
 
 # Delete all kube resources for the app
 # This function is called for apps managed by the test script.
 __A1PMS_kube_delete_all() {
-       __kube_delete_all_resources $KUBE_NONRTRIC_NAMESPACE autotest A1PMS
+  __kube_delete_all_resources $KUBE_NONRTRIC_NAMESPACE autotest A1PMS
 }
 
 # Store docker logs
 # This function is called for apps managed by the test script.
 # args: <log-dir> <file-prefix>
 __A1PMS_store_docker_logs() {
-       if [ $RUNMODE == "KUBE" ]; then
-               kubectl $KUBECONF  logs -l "autotest=A1PMS" -n $KUBE_NONRTRIC_NAMESPACE --tail=-1 > $1$2_a1pms.log 2>&1
-       else
-               docker logs $A1PMS_APP_NAME > $1$2_a1pms.log 2>&1
-       fi
+  if [ $RUNMODE == "KUBE" ]; then
+    kubectl $KUBECONF logs -l "autotest=A1PMS" -n $KUBE_NONRTRIC_NAMESPACE --tail=-1 >$1$2_a1pms.log 2>&1
+  else
+    docker logs $A1PMS_APP_NAME >$1$2_a1pms.log 2>&1
+  fi
 }
 
 # Initial setup of protocol, host and ports
 # This function is called for apps managed by the test script.
 # args: -
 __A1PMS_initial_setup() {
-       use_a1pms_rest_http
-       export A1PMS_SIDECAR_JWT_FILE=""
+  use_a1pms_rest_http
+  export A1PMS_SIDECAR_JWT_FILE=""
 }
 
 # Set app short-name, app name and namespace for logging runtime statistics of kubernetes pods or docker containers
@@ -97,20 +98,19 @@ __A1PMS_initial_setup() {
 # This function is called for apps managed by the test script as well as for pre-started apps.
 # args: -
 __A1PMS_statistics_setup() {
-       if [ $RUNMODE == "KUBE" ]; then
-               echo "A1PMS $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE"
-       else
-               echo "A1PMS $A1PMS_APP_NAME"
-       fi
+  if [ $RUNMODE == "KUBE" ]; then
+    echo "A1PMS $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE"
+  else
+    echo "A1PMS $A1PMS_APP_NAME"
+  fi
 }
 
 # Check application requirements, e.g. helm, the the test needs. Exit 1 if req not satisfied
 # args: -
 __A1PMS_test_requirements() {
-       :
+  :
 }
 
-
 #######################################################
 
 ###########################
@@ -121,55 +121,55 @@ __A1PMS_test_requirements() {
 # args: -
 # (Function for test scripts)
 use_a1pms_rest_http() {
-       __a1pms_set_protocoll "http" $A1PMS_INTERNAL_PORT $A1PMS_EXTERNAL_PORT
+  __a1pms_set_protocoll "http" $A1PMS_INTERNAL_PORT $A1PMS_EXTERNAL_PORT
 }
 
 # Set https as the protocol to use for all communication to the A1PMS
 # args: -
 # (Function for test scripts)
 use_a1pms_rest_https() {
-       __a1pms_set_protocoll "https" $A1PMS_INTERNAL_SECURE_PORT $A1PMS_EXTERNAL_SECURE_PORT
+  __a1pms_set_protocoll "https" $A1PMS_INTERNAL_SECURE_PORT $A1PMS_EXTERNAL_SECURE_PORT
 }
 
 # All calls to the a1pms will be directed to the a1pms dmaap interface over http from now on
 # args: -
 # (Function for test scripts)
 use_a1pms_dmaap_http() {
-       echo -e $BOLD"$A1PMS_DISPLAY_NAME dmaap protocol setting"$EBOLD
-       echo -e " Using $BOLD http $EBOLD and $BOLD DMAAP $EBOLD towards the a1pms"
-       A1PMS_ADAPTER_TYPE="MR-HTTP"
-       echo ""
+  echo -e $BOLD"$A1PMS_DISPLAY_NAME dmaap protocol setting"$EBOLD
+  echo -e " Using $BOLD http $EBOLD and $BOLD DMAAP $EBOLD towards the a1pms"
+  A1PMS_ADAPTER_TYPE="MR-HTTP"
+  echo ""
 }
 
 # All calls to the a1pms will be directed to the a1pms dmaap interface over https from now on
 # args: -
 # (Function for test scripts)
 use_a1pms_dmaap_https() {
-       echo -e $BOLD"$A1PMS_DISPLAY_NAME dmaap protocol setting"$EBOLD
-       echo -e " Using $BOLD https $EBOLD and $BOLD DMAAP $EBOLD towards the a1pms"
-       echo -e $YELLOW" Setting http instead of https - MR only uses http"$EYELLOW
-       A1PMS_ADAPTER_TYPE="MR-HTTPS"
-       echo ""
+  echo -e $BOLD"$A1PMS_DISPLAY_NAME dmaap protocol setting"$EBOLD
+  echo -e " Using $BOLD https $EBOLD and $BOLD DMAAP $EBOLD towards the a1pms"
+  echo -e $YELLOW" Setting http instead of https - MR only uses http"$EYELLOW
+  A1PMS_ADAPTER_TYPE="MR-HTTPS"
+  echo ""
 }
 
 # Setup paths to svc/container for internal and external access
 # args: <protocol> <internal-port> <external-port>
 __a1pms_set_protocoll() {
-       echo -e $BOLD"$A1PMS_DISPLAY_NAME protocol setting"$EBOLD
-       echo -e " Using $BOLD $1 $EBOLD towards $A1PMS_DISPLAY_NAME"
+  echo -e $BOLD"$A1PMS_DISPLAY_NAME protocol setting"$EBOLD
+  echo -e " Using $BOLD $1 $EBOLD towards $A1PMS_DISPLAY_NAME"
 
-       ## Access to Dmaap adapter
+  ## Access to Dmaap adapter
 
-       A1PMS_SERVICE_PATH=$1"://"$A1PMS_APP_NAME":"$2  # docker access, container->container and script->container via proxy
-       if [ $RUNMODE == "KUBE" ]; then
-               A1PMS_SERVICE_PATH=$1"://"$A1PMS_APP_NAME.$KUBE_NONRTRIC_NAMESPACE":"$3 # kube access, pod->svc and script->svc via proxy
-       fi
+  A1PMS_SERVICE_PATH=$1"://"$A1PMS_APP_NAME":"$2 # docker access, container->container and script->container via proxy
+  if [ $RUNMODE == "KUBE" ]; then
+    A1PMS_SERVICE_PATH=$1"://"$A1PMS_APP_NAME.$KUBE_NONRTRIC_NAMESPACE":"$3 # kube access, pod->svc and script->svc via proxy
+  fi
 
-       # A1PMS_ADAPTER used for switching between REST and DMAAP (only REST supported currently)
-       A1PMS_ADAPTER_TYPE="REST"
-       A1PMS_ADAPTER=$A1PMS_SERVICE_PATH
+  # A1PMS_ADAPTER used for switching between REST and DMAAP (only REST supported currently)
+  A1PMS_ADAPTER_TYPE="REST"
+  A1PMS_ADAPTER=$A1PMS_SERVICE_PATH
 
-       echo ""
+  echo ""
 }
 
 # Make curl retries towards the a1pms for http response codes set in this env var, space separated list of codes
@@ -182,190 +182,189 @@ __A1PMS_WORKER_NODE=""
 # args: PROXY|NOPROXY
 __export_a1pms_vars() {
 
-               export A1PMS_APP_NAME
-               export A1PMS_APP_NAME_ALIAS
-               export A1PMS_DISPLAY_NAME
-
-               export KUBE_NONRTRIC_NAMESPACE
-               export A1PMS_IMAGE
-               export A1PMS_INTERNAL_PORT
-               export A1PMS_INTERNAL_SECURE_PORT
-               export A1PMS_EXTERNAL_PORT
-               export A1PMS_EXTERNAL_SECURE_PORT
-               export A1PMS_CONFIG_MOUNT_PATH
-               export A1PMS_DATA_MOUNT_PATH
-               export A1PMS_CONFIG_CONFIGMAP_NAME=$A1PMS_APP_NAME"-config"
-               export A1PMS_DATA_CONFIGMAP_NAME=$A1PMS_APP_NAME"-data"
-               export A1PMS_PKG_NAME
-               export A1PMS_CONFIG_KEY
-               export DOCKER_SIM_NWNAME
-               export A1PMS_HOST_MNT_DIR
-               export A1PMS_CONFIG_FILE
-
-               export A1PMS_DATA_PV_NAME=$A1PMS_APP_NAME"-pv"
-               export A1PMS_DATA_PVC_NAME=$A1PMS_APP_NAME"-pvc"
-               ##Create a unique path for the pv each time to prevent a previous volume to be reused
-               export A1PMS_PV_PATH="a1pmsdata-"$(date +%s)
-               export A1PMS_CONTAINER_MNT_DIR
-               export HOST_PATH_BASE_DIR
-
-               if [ $1 == "PROXY" ]; then
-                       export A1PMS_HTTP_PROXY_CONFIG_PORT=$HTTP_PROXY_CONFIG_PORT  #Set if proxy is started
-                       export A1PMS_HTTP_PROXY_CONFIG_HOST_NAME=$HTTP_PROXY_CONFIG_HOST_NAME #Set if proxy is started
-                       if [ $A1PMS_HTTP_PROXY_CONFIG_PORT -eq 0 ] || [ -z "$A1PMS_HTTP_PROXY_CONFIG_HOST_NAME" ]; then
-                               echo -e $YELLOW" Warning: HTTP PROXY will not be configured, proxy app not started"$EYELLOW
-                       else
-                               echo " Configured with http proxy"
-                       fi
-               else
-                       export A1PMS_HTTP_PROXY_CONFIG_PORT=0
-                       export A1PMS_HTTP_PROXY_CONFIG_HOST_NAME=""
-                       echo " Configured without http proxy"
-               fi
+  export A1PMS_APP_NAME
+  export A1PMS_APP_NAME_ALIAS
+  export A1PMS_DISPLAY_NAME
+
+  export KUBE_NONRTRIC_NAMESPACE
+  export A1PMS_IMAGE
+  export A1PMS_INTERNAL_PORT
+  export A1PMS_INTERNAL_SECURE_PORT
+  export A1PMS_EXTERNAL_PORT
+  export A1PMS_EXTERNAL_SECURE_PORT
+  export A1PMS_CONFIG_MOUNT_PATH
+  export A1PMS_DATA_MOUNT_PATH
+  export A1PMS_CONFIG_CONFIGMAP_NAME=$A1PMS_APP_NAME"-config"
+  export A1PMS_DATA_CONFIGMAP_NAME=$A1PMS_APP_NAME"-data"
+  export A1PMS_PKG_NAME
+  export A1PMS_CONFIG_KEY
+  export DOCKER_SIM_NWNAME
+  export A1PMS_HOST_MNT_DIR
+  export A1PMS_CONFIG_FILE
+
+  export A1PMS_DATA_PV_NAME=$A1PMS_APP_NAME"-pv"
+  export A1PMS_DATA_PVC_NAME=$A1PMS_APP_NAME"-pvc"
+  ##Create a unique path for the pv each time to prevent a previous volume to be reused
+  export A1PMS_PV_PATH="a1pmsdata-"$(date +%s)
+  export A1PMS_CONTAINER_MNT_DIR
+  export HOST_PATH_BASE_DIR
+
+  if [ $1 == "PROXY" ]; then
+    export A1PMS_HTTP_PROXY_CONFIG_PORT=$HTTP_PROXY_CONFIG_PORT           #Set if proxy is started
+    export A1PMS_HTTP_PROXY_CONFIG_HOST_NAME=$HTTP_PROXY_CONFIG_HOST_NAME #Set if proxy is started
+    if [ $A1PMS_HTTP_PROXY_CONFIG_PORT -eq 0 ] || [ -z "$A1PMS_HTTP_PROXY_CONFIG_HOST_NAME" ]; then
+      echo -e $YELLOW" Warning: HTTP PROXY will not be configured, proxy app not started"$EYELLOW
+    else
+      echo " Configured with http proxy"
+    fi
+  else
+    export A1PMS_HTTP_PROXY_CONFIG_PORT=0
+    export A1PMS_HTTP_PROXY_CONFIG_HOST_NAME=""
+    echo " Configured without http proxy"
+  fi
 }
 
-
 # Start the ms
 # args: (docker) PROXY|NOPROXY <config-file>
 # args: (kube) PROXY|NOPROXY <config-file> [ <data-file>]
 # (Function for test scripts)
 start_a1pms() {
-       echo -e $BOLD"Starting $A1PMS_DISPLAY_NAME"$EBOLD
-
-       if [ $RUNMODE == "KUBE" ]; then
-
-               # Check if app shall be fully managed by the test script
-               __check_included_image "A1PMS"
-               retcode_i=$?
-
-               # Check if app shall only be used by the test script
-               __check_prestarted_image "A1PMS"
-               retcode_p=$?
-
-               if [ $retcode_i -ne 0 ] && [ $retcode_p -ne 0 ]; then
-                       echo -e $RED"The $A1PMS_APP_NAME app is not included as managed nor prestarted in this test script"$ERED
-                       echo -e $RED"The $A1PMS_APP_NAME will not be started"$ERED
-                       exit
-               fi
-               if [ $retcode_i -eq 0 ] && [ $retcode_p -eq 0 ]; then
-                       echo -e $RED"The $A1PMS_APP_NAME app is included both as managed and prestarted in this test script"$ERED
-                       echo -e $RED"The $A1PMS_APP_NAME will not be started"$ERED
-                       exit
-               fi
-
-               if [ $retcode_p -eq 0 ]; then
-                       echo -e " Using existing $A1PMS_APP_NAME deployment and service"
-                       echo " Setting $A1PMS_APP_NAME replicas=1"
-                       res_type=$(__kube_get_resource_type $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE)
-                       __kube_scale $res_type $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE 1
-               fi
-
-               if [ $retcode_i -eq 0 ]; then
-
-                       echo -e " Creating $A1PMS_APP_NAME app and expose service"
-
-                       #Check if nonrtric namespace exists, if not create it
-                       __kube_create_namespace $KUBE_NONRTRIC_NAMESPACE
-
-                       __export_a1pms_vars $1
-
-                       # Create config map for config
-                       configfile=$PWD/tmp/$A1PMS_CONFIG_FILE
-                       cp $2 $configfile
-                       output_yaml=$PWD/tmp/a1pms-cfc.yaml
-                       __kube_create_configmap $A1PMS_CONFIG_CONFIGMAP_NAME $KUBE_NONRTRIC_NAMESPACE autotest A1PMS $configfile $output_yaml
-
-                       # Create config map for data
-                       data_json=$PWD/tmp/$A1PMS_DATA_FILE
-                       if [ $# -lt 3 ]; then
-                               #create empty dummy file
-                               echo "{}" > $data_json
-                       else
-                               cp $3 $data_json
-                       fi
-                       output_yaml=$PWD/tmp/a1pms-cfd.yaml
-                       __kube_create_configmap $A1PMS_DATA_CONFIGMAP_NAME $KUBE_NONRTRIC_NAMESPACE autotest A1PMS $data_json $output_yaml
-
-                       ## Create pv
-                       input_yaml=$SIM_GROUP"/"$A1PMS_COMPOSE_DIR"/"pv.yaml
-                       output_yaml=$PWD/tmp/a1pms-pv.yaml
-                       __kube_create_instance pv $A1PMS_APP_NAME $input_yaml $output_yaml
-
-                       ## Create pvc
-                       input_yaml=$SIM_GROUP"/"$A1PMS_COMPOSE_DIR"/"pvc.yaml
-                       output_yaml=$PWD/tmp/a1pms-pvc.yaml
-                       __kube_create_instance pvc $A1PMS_APP_NAME $input_yaml $output_yaml
-
-                       # Create service
-                       input_yaml=$SIM_GROUP"/"$A1PMS_COMPOSE_DIR"/"svc.yaml
-                       output_yaml=$PWD/tmp/a1pmssvc.yaml
-                       __kube_create_instance service $A1PMS_APP_NAME $input_yaml $output_yaml
-
-                       # Create app
-                       input_yaml=$SIM_GROUP"/"$A1PMS_COMPOSE_DIR"/"app.yaml
-                       output_yaml=$PWD/tmp/a1pmsapp.yaml
-                       if [ -z "$A1PMS_SIDECAR_JWT_FILE" ]; then
-                               cat $input_yaml | sed  '/#A1PMS_JWT_START/,/#A1PMS_JWT_STOP/d' > $PWD/tmp/a1pmsapp_tmp.yaml
-                               input_yaml=$PWD/tmp/a1pmsapp_tmp.yaml
-                       fi
-                       __kube_create_instance app $A1PMS_APP_NAME $input_yaml $output_yaml
-
-               fi
-
-               # Keep the initial worker node in case the pod need to be "restarted" - must be made to the same node due to a volume mounted on the host
-               if [ $retcode_i -eq 0 ]; then
-                       __A1PMS_WORKER_NODE=$(kubectl $KUBECONF get pod -l "autotest=A1PMS" -n $KUBE_NONRTRIC_NAMESPACE -o jsonpath='{.items[*].spec.nodeName}')
-                       if [ -z "$__A1PMS_WORKER_NODE" ]; then
-                               echo -e $YELLOW" Cannot find worker node for pod for $A1PMS_APP_NAME, persistency may not work"$EYELLOW
-                       fi
-               else
-                       echo -e $YELLOW" Persistency may not work for app $A1PMS_APP_NAME in multi-worker node config when running it as a prestarted app"$EYELLOW
-               fi
-
-               __check_service_start $A1PMS_APP_NAME $A1PMS_SERVICE_PATH$A1PMS_ALIVE_URL
-
-       else
-               __check_included_image 'A1PMS'
-               if [ $? -eq 1 ]; then
-                       echo -e $RED"The A1PMS app is not included in this test script"$ERED
-                       echo -e $RED"The A1PMS will not be started"$ERED
-                       exit
-               fi
-
-               curdir=$PWD
-               cd $SIM_GROUP
-               cd a1pms
-               cd $A1PMS_HOST_MNT_DIR
-               #cd ..
-               if [ -d db ]; then
-                       if [ "$(ls -A $DIR)" ]; then
-                               echo -e $BOLD" Cleaning files in mounted dir: $PWD/db"$EBOLD
-                               rm -rf db/*  &> /dev/null
-                               if [ $? -ne 0 ]; then
-                                       echo -e $RED" Cannot remove database files in: $PWD"$ERED
-                                       exit 1
-                               fi
-                       fi
-               else
-                       echo " No files in mounted dir or dir does not exists"
-                       mkdir db
-               fi
-               cd $curdir
-
-               __export_a1pms_vars $1
-
-               dest_file=$SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_HOST_MNT_DIR/application.yaml
-
-               envsubst < $2 > $dest_file
-
-               __start_container $A1PMS_COMPOSE_DIR "" NODOCKERARGS 1 $A1PMS_APP_NAME
-
-               __check_service_start $A1PMS_APP_NAME $A1PMS_SERVICE_PATH$A1PMS_ALIVE_URL
-       fi
-
-       __collect_endpoint_stats_image_info "A1PMS" $A1PMS_IMAGE
-       echo ""
-       return 0
+  echo -e $BOLD"Starting $A1PMS_DISPLAY_NAME"$EBOLD
+
+  if [ $RUNMODE == "KUBE" ]; then
+
+    # Check if app shall be fully managed by the test script
+    __check_included_image "A1PMS"
+    retcode_i=$?
+
+    # Check if app shall only be used by the test script
+    __check_prestarted_image "A1PMS"
+    retcode_p=$?
+
+    if [ $retcode_i -ne 0 ] && [ $retcode_p -ne 0 ]; then
+      echo -e $RED"The $A1PMS_APP_NAME app is not included as managed nor prestarted in this test script"$ERED
+      echo -e $RED"The $A1PMS_APP_NAME will not be started"$ERED
+      exit
+    fi
+    if [ $retcode_i -eq 0 ] && [ $retcode_p -eq 0 ]; then
+      echo -e $RED"The $A1PMS_APP_NAME app is included both as managed and prestarted in this test script"$ERED
+      echo -e $RED"The $A1PMS_APP_NAME will not be started"$ERED
+      exit
+    fi
+
+    if [ $retcode_p -eq 0 ]; then
+      echo -e " Using existing $A1PMS_APP_NAME deployment and service"
+      echo " Setting $A1PMS_APP_NAME replicas=1"
+      res_type=$(__kube_get_resource_type $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE)
+      __kube_scale $res_type $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE 1
+    fi
+
+    if [ $retcode_i -eq 0 ]; then
+
+      echo -e " Creating $A1PMS_APP_NAME app and expose service"
+
+      #Check if nonrtric namespace exists, if not create it
+      __kube_create_namespace $KUBE_NONRTRIC_NAMESPACE
+
+      __export_a1pms_vars $1
+
+      # Create config map for config
+      configfile=$PWD/tmp/$A1PMS_CONFIG_FILE
+      cp $2 $configfile
+      output_yaml=$PWD/tmp/a1pms-cfc.yaml
+      __kube_create_configmap $A1PMS_CONFIG_CONFIGMAP_NAME $KUBE_NONRTRIC_NAMESPACE autotest A1PMS $configfile $output_yaml
+
+      # Create config map for data
+      data_json=$PWD/tmp/$A1PMS_DATA_FILE
+      if [ $# -lt 3 ]; then
+        #create empty dummy file
+        echo "{}" >$data_json
+      else
+        cp $3 $data_json
+      fi
+      output_yaml=$PWD/tmp/a1pms-cfd.yaml
+      __kube_create_configmap $A1PMS_DATA_CONFIGMAP_NAME $KUBE_NONRTRIC_NAMESPACE autotest A1PMS $data_json $output_yaml
+
+      ## Create pv
+      input_yaml=$SIM_GROUP"/"$A1PMS_COMPOSE_DIR"/"pv.yaml
+      output_yaml=$PWD/tmp/a1pms-pv.yaml
+      __kube_create_instance pv $A1PMS_APP_NAME $input_yaml $output_yaml
+
+      ## Create pvc
+      input_yaml=$SIM_GROUP"/"$A1PMS_COMPOSE_DIR"/"pvc.yaml
+      output_yaml=$PWD/tmp/a1pms-pvc.yaml
+      __kube_create_instance pvc $A1PMS_APP_NAME $input_yaml $output_yaml
+
+      # Create service
+      input_yaml=$SIM_GROUP"/"$A1PMS_COMPOSE_DIR"/"svc.yaml
+      output_yaml=$PWD/tmp/a1pmssvc.yaml
+      __kube_create_instance service $A1PMS_APP_NAME $input_yaml $output_yaml
+
+      # Create app
+      input_yaml=$SIM_GROUP"/"$A1PMS_COMPOSE_DIR"/"app.yaml
+      output_yaml=$PWD/tmp/a1pmsapp.yaml
+      if [ -z "$A1PMS_SIDECAR_JWT_FILE" ]; then
+        cat $input_yaml | sed '/#A1PMS_JWT_START/,/#A1PMS_JWT_STOP/d' >$PWD/tmp/a1pmsapp_tmp.yaml
+        input_yaml=$PWD/tmp/a1pmsapp_tmp.yaml
+      fi
+      __kube_create_instance app $A1PMS_APP_NAME $input_yaml $output_yaml
+
+    fi
+
+    # Keep the initial worker node in case the pod need to be "restarted" - must be made to the same node due to a volume mounted on the host
+    if [ $retcode_i -eq 0 ]; then
+      __A1PMS_WORKER_NODE=$(kubectl $KUBECONF get pod -l "autotest=A1PMS" -n $KUBE_NONRTRIC_NAMESPACE -o jsonpath='{.items[*].spec.nodeName}')
+      if [ -z "$__A1PMS_WORKER_NODE" ]; then
+        echo -e $YELLOW" Cannot find worker node for pod for $A1PMS_APP_NAME, persistency may not work"$EYELLOW
+      fi
+    else
+      echo -e $YELLOW" Persistency may not work for app $A1PMS_APP_NAME in multi-worker node config when running it as a prestarted app"$EYELLOW
+    fi
+
+    __check_service_start $A1PMS_APP_NAME $A1PMS_SERVICE_PATH$A1PMS_ALIVE_URL
+
+  else
+    __check_included_image 'A1PMS'
+    if [ $? -eq 1 ]; then
+      echo -e $RED"The A1PMS app is not included in this test script"$ERED
+      echo -e $RED"The A1PMS will not be started"$ERED
+      exit
+    fi
+
+    curdir=$PWD
+    cd $SIM_GROUP
+    cd a1pms
+    cd $A1PMS_HOST_MNT_DIR
+    #cd ..
+    if [ -d db ]; then
+      if [ "$(ls -A $DIR)" ]; then
+        echo -e $BOLD" Cleaning files in mounted dir: $PWD/db"$EBOLD
+        rm -rf db/* &>/dev/null
+        if [ $? -ne 0 ]; then
+          echo -e $RED" Cannot remove database files in: $PWD"$ERED
+          exit 1
+        fi
+      fi
+    else
+      echo " No files in mounted dir or dir does not exists"
+      mkdir db
+    fi
+    cd $curdir
+
+    __export_a1pms_vars $1
+
+    dest_file=$SIM_GROUP/$A1PMS_COMPOSE_DIR/$A1PMS_HOST_MNT_DIR/application.yaml
+
+    envsubst <$2 >$dest_file
+
+    __start_container $A1PMS_COMPOSE_DIR "" NODOCKERARGS 1 $A1PMS_APP_NAME
+
+    __check_service_start $A1PMS_APP_NAME $A1PMS_SERVICE_PATH$A1PMS_ALIVE_URL
+  fi
+
+  __collect_endpoint_stats_image_info "A1PMS" $A1PMS_IMAGE
+  echo ""
+  return 0
 }
 
 # Stop the a1pms
@@ -373,297 +372,295 @@ start_a1pms() {
 # args: -
 # (Function for test scripts)
 stop_a1pms() {
-       echo -e $BOLD"Stopping $A1PMS_DISPLAY_NAME"$EBOLD
-
-       if [ $RUNMODE == "KUBE" ]; then
-
-               __check_prestarted_image "A1PMS"
-               if [ $? -eq 0 ]; then
-                       echo -e $YELLOW" Persistency may not work for app $A1PMS_APP_NAME in multi-worker node config when running it as a prestarted app"$EYELLOW
-                       res_type=$(__kube_get_resource_type $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE)
-                       __kube_scale $res_type $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE 0
-                       return 0
-               fi
-               __kube_scale_all_resources $KUBE_NONRTRIC_NAMESPACE autotest A1PMS
-               echo "  Deleting the replica set - a new will be started when the app is started"
-               tmp=$(kubectl $KUBECONF delete rs -n $KUBE_NONRTRIC_NAMESPACE -l "autotest=PA")
-               if [ $? -ne 0 ]; then
-                       echo -e $RED" Could not delete replica set "$RED
-                       ((RES_CONF_FAIL++))
-                       return 1
-               fi
-       else
-               docker stop $A1PMS_APP_NAME &> ./tmp/.dockererr
-               if [ $? -ne 0 ]; then
-                       __print_err "Could not stop $A1PMS_APP_NAME" $@
-                       cat ./tmp/.dockererr
-                       ((RES_CONF_FAIL++))
-                       return 1
-               fi
-       fi
-       echo -e $BOLD$GREEN"Stopped"$EGREEN$EBOLD
-       echo ""
-       return 0
+  echo -e $BOLD"Stopping $A1PMS_DISPLAY_NAME"$EBOLD
+
+  if [ $RUNMODE == "KUBE" ]; then
+
+    __check_prestarted_image "A1PMS"
+    if [ $? -eq 0 ]; then
+      echo -e $YELLOW" Persistency may not work for app $A1PMS_APP_NAME in multi-worker node config when running it as a prestarted app"$EYELLOW
+      res_type=$(__kube_get_resource_type $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE)
+      __kube_scale $res_type $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE 0
+      return 0
+    fi
+    __kube_scale_all_resources $KUBE_NONRTRIC_NAMESPACE autotest A1PMS
+    echo "  Deleting the replica set - a new will be started when the app is started"
+    tmp=$(kubectl $KUBECONF delete rs -n $KUBE_NONRTRIC_NAMESPACE -l "autotest=PA")
+    if [ $? -ne 0 ]; then
+      echo -e $RED" Could not delete replica set "$RED
+      ((RES_CONF_FAIL++))
+      return 1
+    fi
+  else
+    docker stop $A1PMS_APP_NAME &>./tmp/.dockererr
+    if [ $? -ne 0 ]; then
+      __print_err "Could not stop $A1PMS_APP_NAME" $@
+      cat ./tmp/.dockererr
+      ((RES_CONF_FAIL++))
+      return 1
+    fi
+  fi
+  echo -e $BOLD$GREEN"Stopped"$EGREEN$EBOLD
+  echo ""
+  return 0
 }
 
 # Start a previously stopped a1pms
 # args: -
 # (Function for test scripts)
 start_stopped_a1pms() {
-       echo -e $BOLD"Starting (the previously stopped) $A1PMS_DISPLAY_NAME"$EBOLD
-
-       if [ $RUNMODE == "KUBE" ]; then
-
-               __check_prestarted_image "A1PMS"
-               if [ $? -eq 0 ]; then
-                       echo -e $YELLOW" Persistency may not work for app $A1PMS_APP_NAME in multi-worker node config when running it as a prestarted app"$EYELLOW
-                       res_type=$(__kube_get_resource_type $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE)
-                       __kube_scale $res_type $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE 1
-                       __check_service_start $A1PMS_APP_NAME $A1PMS_SERVICE_PATH$A1PMS_ALIVE_URL
-                       return 0
-               fi
-
-               # Tie the A1PMS to the same worker node it was initially started on
-               # A PVC of type hostPath is mounted to A1PMS, for persistent storage, so the A1PMS must always be on the node which mounted the volume
-               if [ -z "$__A1PMS_WORKER_NODE" ]; then
-                       echo -e $RED" No initial worker node found for pod "$RED
-                       ((RES_CONF_FAIL++))
-                       return 1
-               else
-                       echo -e $BOLD" Setting nodeSelector kubernetes.io/hostname=$__A1PMS_WORKER_NODE to deployment for $A1PMS_APP_NAME. Pod will always run on this worker node: $__A1PMS_WORKER_NODE"$BOLD
-                       echo -e $BOLD" The mounted volume is mounted as hostPath and only available on that worker node."$BOLD
-                       tmp=$(kubectl $KUBECONF patch deployment $A1PMS_APP_NAME -n $KUBE_NONRTRIC_NAMESPACE --patch '{"spec": {"template": {"spec": {"nodeSelector": {"kubernetes.io/hostname": "'$__A1PMS_WORKER_NODE'"}}}}}')
-                       if [ $? -ne 0 ]; then
-                               echo -e $YELLOW" Cannot set nodeSelector to deployment for $A1PMS_APP_NAME, persistency may not work"$EYELLOW
-                       fi
-                       __kube_scale deployment $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE 1
-               fi
-       else
-               docker start $A1PMS_APP_NAME &> ./tmp/.dockererr
-               if [ $? -ne 0 ]; then
-                       __print_err "Could not start (the stopped) $A1PMS_APP_NAME" $@
-                       cat ./tmp/.dockererr
-                       ((RES_CONF_FAIL++))
-                       return 1
-               fi
-       fi
-       __check_service_start $A1PMS_APP_NAME $A1PMS_SERVICE_PATH$A1PMS_ALIVE_URL
-       if [ $? -ne 0 ]; then
-               return 1
-       fi
-       echo ""
-       return 0
-}
+  echo -e $BOLD"Starting (the previously stopped) $A1PMS_DISPLAY_NAME"$EBOLD
+
+  if [ $RUNMODE == "KUBE" ]; then
 
+    __check_prestarted_image "A1PMS"
+    if [ $? -eq 0 ]; then
+      echo -e $YELLOW" Persistency may not work for app $A1PMS_APP_NAME in multi-worker node config when running it as a prestarted app"$EYELLOW
+      res_type=$(__kube_get_resource_type $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE)
+      __kube_scale $res_type $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE 1
+      __check_service_start $A1PMS_APP_NAME $A1PMS_SERVICE_PATH$A1PMS_ALIVE_URL
+      return 0
+    fi
+
+    # Tie the A1PMS to the same worker node it was initially started on
+    # A PVC of type hostPath is mounted to A1PMS, for persistent storage, so the A1PMS must always be on the node which mounted the volume
+    if [ -z "$__A1PMS_WORKER_NODE" ]; then
+      echo -e $RED" No initial worker node found for pod "$RED
+      ((RES_CONF_FAIL++))
+      return 1
+    else
+      echo -e $BOLD" Setting nodeSelector kubernetes.io/hostname=$__A1PMS_WORKER_NODE to deployment for $A1PMS_APP_NAME. Pod will always run on this worker node: $__A1PMS_WORKER_NODE"$BOLD
+      echo -e $BOLD" The mounted volume is mounted as hostPath and only available on that worker node."$BOLD
+      tmp=$(kubectl $KUBECONF patch deployment $A1PMS_APP_NAME -n $KUBE_NONRTRIC_NAMESPACE --patch '{"spec": {"template": {"spec": {"nodeSelector": {"kubernetes.io/hostname": "'$__A1PMS_WORKER_NODE'"}}}}}')
+      if [ $? -ne 0 ]; then
+        echo -e $YELLOW" Cannot set nodeSelector to deployment for $A1PMS_APP_NAME, persistency may not work"$EYELLOW
+      fi
+      __kube_scale deployment $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE 1
+    fi
+  else
+    docker start $A1PMS_APP_NAME &>./tmp/.dockererr
+    if [ $? -ne 0 ]; then
+      __print_err "Could not start (the stopped) $A1PMS_APP_NAME" $@
+      cat ./tmp/.dockererr
+      ((RES_CONF_FAIL++))
+      return 1
+    fi
+  fi
+  __check_service_start $A1PMS_APP_NAME $A1PMS_SERVICE_PATH$A1PMS_ALIVE_URL
+  if [ $? -ne 0 ]; then
+    return 1
+  fi
+  echo ""
+  return 0
+}
 
 # Function to prepare the a1pms configuration according to the current simulator configuration
 # args: SDNC|NOSDNC <output-file> [ <sim-group> <adapter-class> ]
 # (Function for test scripts)
 prepare_a1pms_config() {
-       echo -e $BOLD"Prepare A1PMS config"$EBOLD
-
-       echo " Writing a1pms config for "$A1PMS_APP_NAME" to file: "$2
-
-       if [ $# != 2 ] && [ $# != 4 ];  then
-               ((RES_CONF_FAIL++))
-       __print_err "need two or four args,  SDNC|NOSDNC <output-file> [ <sim-group> <adapter-class> ]" $@
-               exit 1
-       fi
-
-       if [ $1 == "SDNC" ]; then
-               echo -e " Config$BOLD including SDNC$EBOLD configuration"
-       elif [ $1 == "NOSDNC" ];  then
-               echo -e " Config$BOLD excluding SDNC$EBOLD configuration"
-       else
-               ((RES_CONF_FAIL++))
-       __print_err "need three args,  SDNC|NOSDNC <output-file> HEADER|NOHEADER" $@
-               exit 1
-       fi
-
-       config_json="\n            {"
-       if [ $1 == "SDNC" ]; then
-               config_json=$config_json"\n   \"controller\": ["
-               config_json=$config_json"\n                     {"
-               config_json=$config_json"\n                       \"name\": \"$SDNC_APP_NAME\","
-               config_json=$config_json"\n                       \"baseUrl\": \"$SDNC_SERVICE_PATH\","
-               config_json=$config_json"\n                       \"userName\": \"$SDNC_USER\","
-               config_json=$config_json"\n                       \"password\": \"$SDNC_PWD\""
-               config_json=$config_json"\n                     }"
-               config_json=$config_json"\n   ],"
-       fi
-       if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
-               :
-       else
-               config_json=$config_json"\n   \"streams_publishes\": {"
-               config_json=$config_json"\n                            \"dmaap_publisher\": {"
-               config_json=$config_json"\n                              \"type\": \"message-router\","
-               config_json=$config_json"\n                              \"dmaap_info\": {"
-               config_json=$config_json"\n                                \"topic_url\": \"$MR_SERVICE_PATH$MR_WRITE_URL\""
-               config_json=$config_json"\n                              }"
-               config_json=$config_json"\n                            }"
-               config_json=$config_json"\n   },"
-               config_json=$config_json"\n   \"streams_subscribes\": {"
-               config_json=$config_json"\n                             \"dmaap_subscriber\": {"
-               config_json=$config_json"\n                               \"type\": \"message-router\","
-               config_json=$config_json"\n                               \"dmaap_info\": {"
-               config_json=$config_json"\n                                   \"topic_url\": \"$MR_SERVICE_PATH$MR_READ_URL\""
-               config_json=$config_json"\n                                 }"
-               config_json=$config_json"\n                               }"
-               config_json=$config_json"\n   },"
-       fi
-
-       config_json=$config_json"\n   \"ric\": ["
-
-       if [ $RUNMODE == "KUBE" ]; then
-               result=$(kubectl $KUBECONF get pods -n $KUBE_A1SIM_NAMESPACE -o jsonpath='{.items[?(@.metadata.labels.autotest=="RICSIM")].metadata.name}')
-               rics=""
-               ric_cntr=0
-               if [ $? -eq 0 ] && [ ! -z "$result" ]; then
-                       for im in $result; do
-                               if [[ $im != *"-0" ]]; then
-                                       ric_subdomain=$(kubectl $KUBECONF get pod $im -n $KUBE_A1SIM_NAMESPACE -o jsonpath='{.spec.subdomain}')
-                                       rics=$rics" "$im"."$ric_subdomain"."$KUBE_A1SIM_NAMESPACE
-                                       let ric_cntr=ric_cntr+1
-                               fi
-                       done
-               fi
-               result=$(kubectl $KUBECONF get pods -n $KUBE_A1SIM_NAMESPACE -o jsonpath='{.items[?(@.metadata.labels.autotest=="RICMEDIATORSIM")].metadata.name}')
-               oranrics=""
-               if [ $? -eq 0 ] && [ ! -z "$result" ]; then
-                       for im in $result; do
-                               if [[ $im != *"-0" ]]; then
-                                       ric_subdomain=$(kubectl $KUBECONF get pod $im -n $KUBE_A1SIM_NAMESPACE -o jsonpath='{.spec.subdomain}')
-                                       rics=$rics" "$im"."$ric_subdomain"."$KUBE_A1SIM_NAMESPACE
-                                       oranrics=$oranrics" "$im"."$ric_subdomain"."$KUBE_A1SIM_NAMESPACE
-                                       let ric_cntr=ric_cntr+1
-                               fi
-                       done
-               fi
-               if [ $ric_cntr -eq 0 ]; then
-                       echo $YELLOW"Warning: No rics found for the configuration"$EYELLOW
-               fi
-       else
-           rics=$(docker ps --filter "name=$RIC_SIM_PREFIX" --filter "network=$DOCKER_SIM_NWNAME" --filter "label=a1sim" --filter "status=running" --format {{.Names}})
-               oranrics=$(docker ps --filter "name=$RIC_SIM_PREFIX" --filter "network=$DOCKER_SIM_NWNAME" --filter "label=orana1sim" --filter "status=running" --format {{.Names}})
-
-               rics="$rics $oranrics"
-
-               if [ $? -ne 0 ] || [ -z "$rics" ]; then
-                       echo -e $RED" FAIL - the names of the running RIC Simulator or ORAN RIC cannot be retrieved." $ERED
-                       ((RES_CONF_FAIL++))
-                       exit 1
-               fi
-       fi
-       cntr=0
-       for ric in $rics; do
-               if [ $cntr -gt 0 ]; then
-                       config_json=$config_json"\n          ,"
-               fi
-               config_json=$config_json"\n          {"
-               if [ $RUNMODE == "KUBE" ]; then
-                       ric_id=${ric%.*.*} #extract pod id from full hosthame
-                       ric_id=$(echo "$ric_id" | tr '-' '_')
-               else
-                       ric_id=$(echo "$ric" | tr '-' '_')  #ric var still needs underscore as it is different from the container name
-               fi
-               echo " Found a1 sim: "$ric 
-               config_json=$config_json"\n            \"name\": \"$ric_id\","
-
-               xricfound=0
-               for xric in $oranrics; do
-                       if [ $xric == $ric ]; then
-                               xricfound=1
-                       fi
-               done
-               if [ $xricfound -eq 0 ]; then
-                       config_json=$config_json"\n            \"baseUrl\": \"$RIC_SIM_HTTPX://$ric:$RIC_SIM_PORT\","
-               else
-                       config_json=$config_json"\n            \"baseUrl\": \"$RICMEDIATOR_SIM_HTTPX://$ric:$RICMEDIATOR_SIM_PORT\","
-               fi
-               if [ ! -z "$3" ]; then
-                       if [[ $ric == "$3"* ]]; then
-                       config_json=$config_json"\n            \"customAdapterClass\": \"$4\","
-                       fi
-               fi
-               if [ $1 == "SDNC" ]; then
-                       config_json=$config_json"\n            \"controller\": \"$SDNC_APP_NAME\","
-               fi
-               config_json=$config_json"\n            \"managedElementIds\": ["
-               config_json=$config_json"\n              \"me1_$ric_id\","
-               config_json=$config_json"\n              \"me2_$ric_id\""
-               config_json=$config_json"\n            ]"
-               config_json=$config_json"\n          }"
-               let cntr=cntr+1
-       done
-
-       config_json=$config_json"\n           ]"
-       config_json=$config_json"\n}"
-
-       config_json="{\"config\":"$config_json"}"
-
-       printf "$config_json">$2
-
-       echo ""
+  echo -e $BOLD"Prepare A1PMS config"$EBOLD
+
+  echo " Writing a1pms config for "$A1PMS_APP_NAME" to file: "$2
+
+  if [ $# != 2 ] && [ $# != 4 ]; then
+    ((RES_CONF_FAIL++))
+    __print_err "need two or four args,  SDNC|NOSDNC <output-file> [ <sim-group> <adapter-class> ]" $@
+    exit 1
+  fi
+
+  if [ $1 == "SDNC" ]; then
+    echo -e " Config$BOLD including SDNC$EBOLD configuration"
+  elif [ $1 == "NOSDNC" ]; then
+    echo -e " Config$BOLD excluding SDNC$EBOLD configuration"
+  else
+    ((RES_CONF_FAIL++))
+    __print_err "need three args,  SDNC|NOSDNC <output-file> HEADER|NOHEADER" $@
+    exit 1
+  fi
+
+  config_json="\n            {"
+  if [ $1 == "SDNC" ]; then
+    config_json=$config_json"\n   \"controller\": ["
+    config_json=$config_json"\n                     {"
+    config_json=$config_json"\n                       \"name\": \"$SDNC_APP_NAME\","
+    config_json=$config_json"\n                       \"baseUrl\": \"$SDNC_SERVICE_PATH\","
+    config_json=$config_json"\n                       \"userName\": \"$SDNC_USER\","
+    config_json=$config_json"\n                       \"password\": \"$SDNC_PWD\""
+    config_json=$config_json"\n                     }"
+    config_json=$config_json"\n   ],"
+  fi
+  if [[ "$A1PMS_FEATURE_LEVEL" == *"NO-DMAAP"* ]]; then
+    :
+  else
+    config_json=$config_json"\n   \"streams_publishes\": {"
+    config_json=$config_json"\n                            \"dmaap_publisher\": {"
+    config_json=$config_json"\n                              \"type\": \"message-router\","
+    config_json=$config_json"\n                              \"dmaap_info\": {"
+    config_json=$config_json"\n                                \"topic_url\": \"$MR_SERVICE_PATH$MR_WRITE_URL\""
+    config_json=$config_json"\n                              }"
+    config_json=$config_json"\n                            }"
+    config_json=$config_json"\n   },"
+    config_json=$config_json"\n   \"streams_subscribes\": {"
+    config_json=$config_json"\n                             \"dmaap_subscriber\": {"
+    config_json=$config_json"\n                               \"type\": \"message-router\","
+    config_json=$config_json"\n                               \"dmaap_info\": {"
+    config_json=$config_json"\n                                   \"topic_url\": \"$MR_SERVICE_PATH$MR_READ_URL\""
+    config_json=$config_json"\n                                 }"
+    config_json=$config_json"\n                               }"
+    config_json=$config_json"\n   },"
+  fi
+
+  config_json=$config_json"\n   \"ric\": ["
+
+  if [ $RUNMODE == "KUBE" ]; then
+    result=$(kubectl $KUBECONF get pods -n $KUBE_A1SIM_NAMESPACE -o jsonpath='{.items[?(@.metadata.labels.autotest=="RICSIM")].metadata.name}')
+    rics=""
+    ric_cntr=0
+    if [ $? -eq 0 ] && [ ! -z "$result" ]; then
+      for im in $result; do
+        if [[ $im != *"-0" ]]; then
+          ric_subdomain=$(kubectl $KUBECONF get pod $im -n $KUBE_A1SIM_NAMESPACE -o jsonpath='{.spec.subdomain}')
+          rics=$rics" "$im"."$ric_subdomain"."$KUBE_A1SIM_NAMESPACE
+          let ric_cntr=ric_cntr+1
+        fi
+      done
+    fi
+    result=$(kubectl $KUBECONF get pods -n $KUBE_A1SIM_NAMESPACE -o jsonpath='{.items[?(@.metadata.labels.autotest=="RICMEDIATORSIM")].metadata.name}')
+    oranrics=""
+    if [ $? -eq 0 ] && [ ! -z "$result" ]; then
+      for im in $result; do
+        if [[ $im != *"-0" ]]; then
+          ric_subdomain=$(kubectl $KUBECONF get pod $im -n $KUBE_A1SIM_NAMESPACE -o jsonpath='{.spec.subdomain}')
+          rics=$rics" "$im"."$ric_subdomain"."$KUBE_A1SIM_NAMESPACE
+          oranrics=$oranrics" "$im"."$ric_subdomain"."$KUBE_A1SIM_NAMESPACE
+          let ric_cntr=ric_cntr+1
+        fi
+      done
+    fi
+    if [ $ric_cntr -eq 0 ]; then
+      echo $YELLOW"Warning: No rics found for the configuration"$EYELLOW
+    fi
+  else
+    rics=$(docker ps --filter "name=$RIC_SIM_PREFIX" --filter "network=$DOCKER_SIM_NWNAME" --filter "label=a1sim" --filter "status=running" --format {{.Names}})
+    oranrics=$(docker ps --filter "name=$RIC_SIM_PREFIX" --filter "network=$DOCKER_SIM_NWNAME" --filter "label=orana1sim" --filter "status=running" --format {{.Names}})
+
+    rics="$rics $oranrics"
+
+    if [ $? -ne 0 ] || [ -z "$rics" ]; then
+      echo -e $RED" FAIL - the names of the running RIC Simulator or ORAN RIC cannot be retrieved." $ERED
+      ((RES_CONF_FAIL++))
+      exit 1
+    fi
+  fi
+  cntr=0
+  for ric in $rics; do
+    if [ $cntr -gt 0 ]; then
+      config_json=$config_json"\n          ,"
+    fi
+    config_json=$config_json"\n          {"
+    if [ $RUNMODE == "KUBE" ]; then
+      ric_id=${ric%.*.*} #extract pod id from full hosthame
+      ric_id=$(echo "$ric_id" | tr '-' '_')
+    else
+      ric_id=$(echo "$ric" | tr '-' '_') #ric var still needs underscore as it is different from the container name
+    fi
+    echo " Found a1 sim: "$ric
+    config_json=$config_json"\n            \"name\": \"$ric_id\","
+
+    xricfound=0
+    for xric in $oranrics; do
+      if [ $xric == $ric ]; then
+        xricfound=1
+      fi
+    done
+    if [ $xricfound -eq 0 ]; then
+      config_json=$config_json"\n            \"baseUrl\": \"$RIC_SIM_HTTPX://$ric:$RIC_SIM_PORT\","
+    else
+      config_json=$config_json"\n            \"baseUrl\": \"$RICMEDIATOR_SIM_HTTPX://$ric:$RICMEDIATOR_SIM_PORT\","
+    fi
+    if [ ! -z "$3" ]; then
+      if [[ $ric == "$3"* ]]; then
+        config_json=$config_json"\n            \"customAdapterClass\": \"$4\","
+      fi
+    fi
+    if [ $1 == "SDNC" ]; then
+      config_json=$config_json"\n            \"controller\": \"$SDNC_APP_NAME\","
+    fi
+    config_json=$config_json"\n            \"managedElementIds\": ["
+    config_json=$config_json"\n              \"me1_$ric_id\","
+    config_json=$config_json"\n              \"me2_$ric_id\""
+    config_json=$config_json"\n            ]"
+    config_json=$config_json"\n          }"
+    let cntr=cntr+1
+  done
+
+  config_json=$config_json"\n           ]"
+  config_json=$config_json"\n}"
+
+  config_json="{\"config\":"$config_json"}"
+
+  printf "$config_json" >$2
+
+  echo ""
 }
 
 # Load the the appl config for the a1pms into a config map
 a1pms_load_config() {
-       echo -e $BOLD"A1PMS - load config from "$EBOLD$1
-       data_json=$PWD/tmp/$A1PMS_DATA_FILE
-       cp $1 $data_json
-       output_yaml=$PWD/tmp/a1pms-cfd.yaml
-       __kube_create_configmap $A1PMS_APP_NAME"-data" $KUBE_NONRTRIC_NAMESPACE autotest A1PMS $data_json $output_yaml
-       echo ""
+  echo -e $BOLD"A1PMS - load config from "$EBOLD$1
+  data_json=$PWD/tmp/$A1PMS_DATA_FILE
+  cp $1 $data_json
+  output_yaml=$PWD/tmp/a1pms-cfd.yaml
+  __kube_create_configmap $A1PMS_APP_NAME"-data" $KUBE_NONRTRIC_NAMESPACE autotest A1PMS $data_json $output_yaml
+  echo ""
 }
 
-
 # Turn on debug level tracing in the a1pms
 # args: -
 # (Function for test scripts)
 set_a1pms_debug() {
-       echo -e $BOLD"Setting a1pms debug logging"$EBOLD
-       curlString="$A1PMS_SERVICE_PATH$A1PMS_ACTUATOR -X POST  -H Content-Type:application/json -d {\"configuredLevel\":\"debug\"}"
-       result=$(__do_curl "$curlString")
-       if [ $? -ne 0 ]; then
-               __print_err "could not set debug mode" $@
-               ((RES_CONF_FAIL++))
-               return 1
-       fi
-       echo ""
-       return 0
+  echo -e $BOLD"Setting a1pms debug logging"$EBOLD
+  curlString="$A1PMS_SERVICE_PATH$A1PMS_ACTUATOR -X POST  -H Content-Type:application/json -d {\"configuredLevel\":\"debug\"}"
+  result=$(__do_curl "$curlString")
+  if [ $? -ne 0 ]; then
+    __print_err "could not set debug mode" $@
+    ((RES_CONF_FAIL++))
+    return 1
+  fi
+  echo ""
+  return 0
 }
 
 # Turn on trace level tracing in the a1pms
 # args: -
 # (Function for test scripts)
 set_a1pms_trace() {
-       echo -e $BOLD"Setting a1pms trace logging"$EBOLD
-       curlString="$A1PMS_SERVICE_PATH$A1PMS_ACTUATOR -X POST  -H Content-Type:application/json -d {\"configuredLevel\":\"trace\"}"
-       result=$(__do_curl "$curlString")
-       if [ $? -ne 0 ]; then
-               __print_err "could not set trace mode" $@
-               ((RES_CONF_FAIL++))
-               return 1
-       fi
-       echo ""
-       return 0
+  echo -e $BOLD"Setting a1pms trace logging"$EBOLD
+  curlString="$A1PMS_SERVICE_PATH$A1PMS_ACTUATOR -X POST  -H Content-Type:application/json -d {\"configuredLevel\":\"trace\"}"
+  result=$(__do_curl "$curlString")
+  if [ $? -ne 0 ]; then
+    __print_err "could not set trace mode" $@
+    ((RES_CONF_FAIL++))
+    return 1
+  fi
+  echo ""
+  return 0
 }
 
 # Perform curl retries when making direct call to the a1pms for the specified http response codes
 # Speace separated list of http response codes
 # args: [<response-code>]*
 use_a1pms_retries() {
-       echo -e $BOLD"Do curl retries to the a1pms REST inteface for these response codes:$@"$EBOLD
-       AGENT_RETRY_CODES=$@
-       echo ""
-       return
+  echo -e $BOLD"Do curl retries to the a1pms REST inteface for these response codes:$@"$EBOLD
+  AGENT_RETRY_CODES=$@
+  echo ""
+  return
 }
 
 # Check the a1pms logs for WARNINGs and ERRORs
 # args: -
 # (Function for test scripts)
 check_a1pms_logs() {
-       __check_container_logs "A1PMS" $A1PMS_APP_NAME $A1PMS_LOGPATH WARN ERR
+  __check_container_logs "A1PMS" $A1PMS_APP_NAME $A1PMS_LOGPATH WARN ERR
 }
 
 #########################################################
@@ -675,19 +672,22 @@ check_a1pms_logs() {
 # args: json:<url> <target-value> [<timeout-in-seconds]
 # (Function for test scripts)
 a1pms_equal() {
-    echo "(${BASH_LINENO[0]}): ${FUNCNAME[0]}" $@ >> $HTTPLOG
-       if [ $# -eq 2 ] || [ $# -eq 3 ]; then
-               if [[ $1 == "json:"* ]]; then
-                       if [ "$A1PMS_VERSION" == "V2" ]; then
-                               __var_test "A1PMS" $A1PMS_SERVICE_PATH$A1PMS_API_PREFIX"/v2/" $1 "=" $2 $3
-                       else
-                               __var_test "A1PMS" $A1PMS_SERVICE_PATH"/" $1 "=" $2 $3
-                       fi
-                       return 0
-               fi
-       fi
-       __print_err "needs two or three args: json:<json-array-param> <target-value> [ timeout ]" $@
-       return 1
+  echo "(${BASH_LINENO[0]}): ${FUNCNAME[0]}" $@ >>$HTTPLOG
+  if [ $# -eq 2 ] || [ $# -eq 3 ]; then
+    if [[ $1 == "json:"* ]]; then
+      if [ "$A1PMS_VERSION" == "V2" ]; then
+        __var_test "A1PMS" $A1PMS_SERVICE_PATH$A1PMS_API_PREFIX"/v2/" $1 "=" $2 $3
+      elif [ "$A1PMS_VERSION" == "V3" ]; then
+        echo "var test execution for V3"
+        __var_test "A1PMS" $A1PMS_SERVICE_PATH$A1PMS_API_PREFIX"/v1/" $1 "=" $2 $3
+      else
+        __var_test "A1PMS" $A1PMS_SERVICE_PATH"/" $1 "=" $2 $3
+      fi
+      return 0
+    fi
+  fi
+  __print_err "needs two or three args: json:<json-array-param> <target-value> [ timeout ]" $@
+  return 1
 }
 
 # API Test function: GET /policies and V2 GET /v2/policy-instances
@@ -695,255 +695,272 @@ a1pms_equal() {
 # args(V2): <response-code> <ric-id>|NORIC <service-id>|NOSERVICE <policy-type-id>|NOTYPE [ NOID | [<policy-id> <ric-id> <service-id> EMPTY|<policy-type-id> <transient> <notification-url> <template-file>]*]
 # (Function for test scripts)
 a1pms_api_get_policies() {
-       __log_test_start $@
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               paramError=0
-               variableParams=$(($#-4))
-               if [ $# -lt 4 ]; then
-                       paramError=1
-               elif [ $# -eq 5 ] && [ $5 != "NOID" ]; then
-                       paramError=1
-               elif [ $# -gt 5 ] && [ $(($variableParams%7)) -ne 0 ]; then
-                       paramError=1
-               fi
-
-               if [ $paramError -ne 0 ]; then
-                       __print_err "<response-code> <ric-id>|NORIC <service-id>|NOSERVICE <policy-type-id>|NOTYPE [ NOID | [<policy-id> <ric-id> <service-id> EMPTY|<policy-type-id> <transient> <notification-url> <template-file>]*]" $@
-                       return 1
-               fi
-       else
-               paramError=0
-               variableParams=$(($#-4))
-               if [ $# -lt 4 ]; then
-                       paramError=1
-               elif [ $# -eq 5 ] && [ $5 != "NOID" ]; then
-                       paramError=1
-               elif [ $# -gt 5 ] && [ $(($variableParams%5)) -ne 0 ]; then
-                       paramError=1
-               fi
-
-               if [ $paramError -ne 0 ]; then
-                       __print_err "<response-code> <ric-id>|NORIC <service-id>|NOSERVICE <policy-type-id>|NOTYPE [ NOID | [<policy-id> <ric-id> <service-id> EMPTY|<policy-type-id> <template-file>]*]" $@
-                       return 1
-               fi
-       fi
-
-       queryparams=""
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               if [ $2 != "NORIC" ]; then
-                       queryparams="?ric_id="$2
-               fi
-               if [ $3 != "NOSERVICE" ]; then
-                       if [ -z $queryparams ]; then
-                               queryparams="?service_id="$3
-                       else
-                               queryparams=$queryparams"&service_id="$3
-                       fi
-               fi
-               if [ $4 != "NOTYPE" ]; then
-                       if [ -z $queryparams ]; then
-                               queryparams="?policytype_id="$4
-                       else
-                               queryparams=$queryparams"&policytype_id="$4
-                       fi
-               fi
-
-               query="/v2/policy-instances"$queryparams
-               res="$(__do_curl_to_api A1PMS GET $query)"
-               status=${res:${#res}-3}
-
-               if [ $status -ne $1 ]; then
-                       __log_test_fail_status_code $1 $status
-                       return 1
-               fi
-
-               if [ $# -gt 4 ]; then
-                       body=${res:0:${#res}-3}
-                       if [ $# -eq 5 ] && [ $5 == "NOID" ]; then
-                               targetJson="["
-                       else
-                               targetJson="["
-                               arr=(${@:5})
-
-                               for ((i=0; i<$(($#-4)); i=i+7)); do
-
-                                       if [ "$targetJson" != "[" ]; then
-                                               targetJson=$targetJson","
-                                       fi
-                                       targetJson=$targetJson"{\"policy_id\":\"$UUID${arr[$i]}\",\"ric_id\":\"${arr[$i+1]}\",\"service_id\":\"${arr[$i+2]}\",\"policytype_id\":"
-                                       if [ "${arr[$i+3]}" == "EMPTY" ]; then
-                                               targetJson=$targetJson"\"\","
-                                       else
-                                               targetJson=$targetJson"\"${arr[$i+3]}\","
-                                       fi
-                                       targetJson=$targetJson"\"transient\":${arr[$i+4]},\"status_notification_uri\":\"${arr[$i+5]}\","
-                                       file="./tmp/.p.json"
-                                       sed 's/XXX/'${arr[$i]}'/g' ${arr[$i+6]} > $file
-                                       json=$(cat $file)
-                                       targetJson=$targetJson"\"policy_data\":"$json"}"
-                               done
-                       fi
-
-                       targetJson=$targetJson"]"
-                       targetJson="{\"policies\": $targetJson}"
-                       echo "TARGET JSON: $targetJson" >> $HTTPLOG
-                       res=$(python3 ../common/compare_json.py "$targetJson" "$body")
-
-                       if [ $res -ne 0 ]; then
-                               __log_test_fail_body
-                               return 1
-                       fi
-               fi
-       else
-               if [ $2 != "NORIC" ]; then
-                       queryparams="?ric="$2
-               fi
-               if [ $3 != "NOSERVICE" ]; then
-                       if [ -z $queryparams ]; then
-                               queryparams="?service="$3
-                       else
-                               queryparams=$queryparams"&service="$3
-                       fi
-               fi
-               if [ $4 != "NOTYPE" ]; then
-                       if [ -z $queryparams ]; then
-                               queryparams="?type="$4
-                       else
-                               queryparams=$queryparams"&type="$4
-                       fi
-               fi
-
-               query="/policies"$queryparams
-               res="$(__do_curl_to_api A1PMS GET $query)"
-               status=${res:${#res}-3}
-
-               if [ $status -ne $1 ]; then
-                       __log_test_fail_status_code $1 $status
-                       return 1
-               fi
-
-               if [ $# -gt 4 ]; then
-                       if [ $# -eq 5 ] && [ $5 == "NOID" ]; then
-                               targetJson="["
-                       else
-                               body=${res:0:${#res}-3}
-                               targetJson="["
-                               arr=(${@:5})
-
-                               for ((i=0; i<$(($#-4)); i=i+5)); do
-
-                                       if [ "$targetJson" != "[" ]; then
-                                               targetJson=$targetJson","
-                                       fi
-                                       targetJson=$targetJson"{\"id\":\"$UUID${arr[$i]}\",\"lastModified\":\"????\",\"ric\":\"${arr[$i+1]}\",\"service\":\"${arr[$i+2]}\",\"type\":"
-                                       if [ "${arr[$i+3]}" == "EMPTY" ]; then
-                                               targetJson=$targetJson"\"\","
-                                       else
-                                               targetJson=$targetJson"\"${arr[$i+3]}\","
-                                       fi
-                                       file="./tmp/.p.json"
-                                       sed 's/XXX/'${arr[$i]}'/g' ${arr[$i+4]} > $file
-                                       json=$(cat $file)
-                                       targetJson=$targetJson"\"json\":"$json"}"
-                               done
-                       fi
-
-                       targetJson=$targetJson"]"
-                       echo "TARGET JSON: $targetJson" >> $HTTPLOG
-                       res=$(python3 ../common/compare_json.py "$targetJson" "$body")
-
-                       if [ $res -ne 0 ]; then
-                               __log_test_fail_body
-                               return 1
-                       fi
-               fi
-       fi
-       __collect_endpoint_stats "A1PMS" 00 "GET" $A1PMS_API_PREFIX"/v2/policy-instances" $status
-       __log_test_pass
-       return 0
+  __log_test_start $@
 
-}
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    paramError=0
+    variableParams=$(($# - 4))
+    if [ $# -lt 4 ]; then
+      paramError=1
+    elif [ $# -eq 5 ] && [ $5 != "NOID" ]; then
+      paramError=1
+    elif [ $# -gt 5 ] && [ $(($variableParams % 7)) -ne 0 ]; then
+      paramError=1
+    fi
+
+    if [ $paramError -ne 0 ]; then
+      __print_err "<response-code> <ric-id>|NORIC <service-id>|NOSERVICE <policy-type-id>|NOTYPE [ NOID | [<policy-id> <ric-id> <service-id> EMPTY|<policy-type-id> <transient> <notification-url> <template-file>]*]" $@
+      return 1
+    fi
+  else
+    paramError=0
+    variableParams=$(($# - 4))
+    if [ $# -lt 4 ]; then
+      paramError=1
+    elif [ $# -eq 5 ] && [ $5 != "NOID" ]; then
+      paramError=1
+    elif [ $# -gt 5 ] && [ $(($variableParams % 5)) -ne 0 ]; then
+      paramError=1
+    fi
+
+    if [ $paramError -ne 0 ]; then
+      __print_err "<response-code> <ric-id>|NORIC <service-id>|NOSERVICE <policy-type-id>|NOTYPE [ NOID | [<policy-id> <ric-id> <service-id> EMPTY|<policy-type-id> <template-file>]*]" $@
+      return 1
+    fi
+  fi
+
+  queryparams=""
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    if [ $2 != "NORIC" ]; then
+      queryparams="?ric_id="$2
+    fi
+    if [ $3 != "NOSERVICE" ]; then
+      if [ -z $queryparams ]; then
+        queryparams="?service_id="$3
+      else
+        queryparams=$queryparams"&service_id="$3
+      fi
+    fi
+    if [ $4 != "NOTYPE" ]; then
+      if [ -z $queryparams ]; then
+        queryparams="?policytype_id="$4
+      else
+        queryparams=$queryparams"&policytype_id="$4
+      fi
+    fi
+
+    query="/v2/policy-instances"$queryparams
+    res="$(__do_curl_to_api A1PMS GET $query)"
+    status=${res:${#res}-3}
+
+    if [ $status -ne $1 ]; then
+      __log_test_fail_status_code $1 $status
+      return 1
+    fi
 
+    if [ $# -gt 4 ]; then
+      body=${res:0:${#res}-3}
+      if [ $# -eq 5 ] && [ $5 == "NOID" ]; then
+        targetJson="["
+      else
+        targetJson="["
+        arr=(${@:5})
+
+        for ((i = 0; i < $(($# - 4)); i = i + 7)); do
+
+          if [ "$targetJson" != "[" ]; then
+            targetJson=$targetJson","
+          fi
+          targetJson=$targetJson"{\"policy_id\":\"$UUID${arr[$i]}\",\"ric_id\":\"${arr[$i + 1]}\",\"service_id\":\"${arr[$i + 2]}\",\"policytype_id\":"
+          if [ "${arr[$i + 3]}" == "EMPTY" ]; then
+            targetJson=$targetJson"\"\","
+          else
+            targetJson=$targetJson"\"${arr[$i + 3]}\","
+          fi
+          targetJson=$targetJson"\"transient\":${arr[$i + 4]},\"status_notification_uri\":\"${arr[$i + 5]}\","
+          file="./tmp/.p.json"
+          sed 's/XXX/'${arr[$i]}'/g' ${arr[$i + 6]} >$file
+          json=$(cat $file)
+          targetJson=$targetJson"\"policy_data\":"$json"}"
+        done
+      fi
+
+      targetJson=$targetJson"]"
+      targetJson="{\"policies\": $targetJson}"
+      echo "TARGET JSON: $targetJson" >>$HTTPLOG
+      res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+
+      if [ $res -ne 0 ]; then
+        __log_test_fail_body
+        return 1
+      fi
+    fi
+  else
+    if [ $2 != "NORIC" ]; then
+      queryparams="?ric="$2
+    fi
+    if [ $3 != "NOSERVICE" ]; then
+      if [ -z $queryparams ]; then
+        queryparams="?service="$3
+      else
+        queryparams=$queryparams"&service="$3
+      fi
+    fi
+    if [ $4 != "NOTYPE" ]; then
+      if [ -z $queryparams ]; then
+        queryparams="?type="$4
+      else
+        queryparams=$queryparams"&type="$4
+      fi
+    fi
 
-# API Test function: GET /policy and V2 GET /v2/policies/{policy_id}
+    query="/policies"$queryparams
+    res="$(__do_curl_to_api A1PMS GET $query)"
+    status=${res:${#res}-3}
+
+    if [ $status -ne $1 ]; then
+      __log_test_fail_status_code $1 $status
+      return 1
+    fi
+
+    if [ $# -gt 4 ]; then
+      if [ $# -eq 5 ] && [ $5 == "NOID" ]; then
+        targetJson="["
+      else
+        body=${res:0:${#res}-3}
+        targetJson="["
+        arr=(${@:5})
+
+        for ((i = 0; i < $(($# - 4)); i = i + 5)); do
+
+          if [ "$targetJson" != "[" ]; then
+            targetJson=$targetJson","
+          fi
+          targetJson=$targetJson"{\"id\":\"$UUID${arr[$i]}\",\"lastModified\":\"????\",\"ric\":\"${arr[$i + 1]}\",\"service\":\"${arr[$i + 2]}\",\"type\":"
+          if [ "${arr[$i + 3]}" == "EMPTY" ]; then
+            targetJson=$targetJson"\"\","
+          else
+            targetJson=$targetJson"\"${arr[$i + 3]}\","
+          fi
+          file="./tmp/.p.json"
+          sed 's/XXX/'${arr[$i]}'/g' ${arr[$i + 4]} >$file
+          json=$(cat $file)
+          targetJson=$targetJson"\"json\":"$json"}"
+        done
+      fi
+
+      targetJson=$targetJson"]"
+      echo "TARGET JSON: $targetJson" >>$HTTPLOG
+      res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+
+      if [ $res -ne 0 ]; then
+        __log_test_fail_body
+        return 1
+      fi
+    fi
+  fi
+  __collect_endpoint_stats "A1PMS" 00 "GET" $A1PMS_API_PREFIX"/v2/policy-instances" $status
+  __log_test_pass
+  return 0
+
+}
+
+# API Test function: GET /policy, V2 GET /v2/policies/{policy_id} and V3 GET a1policymanagement/v1/policies/{policy_id}
 # args: <response-code>  <policy-id> [<template-file>]
 # args(V2): <response-code> <policy-id> [ <template-file> <service-name> <ric-id> <policytype-id>|NOTYPE <transient> <notification-url>|NOURL ]
-
 # (Function for test scripts)
 a1pms_api_get_policy() {
-       __log_test_start $@
-
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               if [ $# -ne 2 ] && [ $# -ne 8 ]; then
-                       __print_err "<response-code> <policy-id> [ <template-file> <service-name> <ric-id> <policytype-id>|NOTYPE <transient> <notification-url>|NOURL ]" $@
-                       return 1
-               fi
-               query="/v2/policies/$UUID$2"
-       else
-               if [ $# -lt 2 ] || [ $# -gt 3 ]; then
-                       __print_err "<response-code>  <policy-id> [<template-file>] " $@
-                       return 1
-               fi
-               query="/policy?id=$UUID$2"
-       fi
-       res="$(__do_curl_to_api A1PMS GET $query)"
-       status=${res:${#res}-3}
-
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               if [ $# -eq 8 ]; then
-
-                       #Create a policy json to compare with
-                       body=${res:0:${#res}-3}
-
-                       targetJson="\"ric_id\":\"$5\",\"policy_id\":\"$UUID$2\",\"service_id\":\"$4\""
-                       if [ $7 != "NOTRANSIENT" ]; then
-                               targetJson=$targetJson", \"transient\":$7"
-                       fi
-                       if [ $6 != "NOTYPE" ]; then
-                               targetJson=$targetJson", \"policytype_id\":\"$6\""
-                       else
-                               targetJson=$targetJson", \"policytype_id\":\"\""
-                       fi
-                       if [ $8 != "NOURL" ]; then
-                               targetJson=$targetJson", \"status_notification_uri\":\"$8\""
-                       fi
-
-                       data=$(sed 's/XXX/'${2}'/g' $3)
-                       targetJson=$targetJson", \"policy_data\":$data"
-                       targetJson="{$targetJson}"
-
-                       echo "TARGET JSON: $targetJson" >> $HTTPLOG
-                       res=$(python3 ../common/compare_json.py "$targetJson" "$body")
-                       if [ $res -ne 0 ]; then
-                               __log_test_fail_body
-                               return 1
-                       fi
-               fi
-       else
-               if [ $# -eq 3 ]; then
-                       #Create a policy json to compare with
-                       body=${res:0:${#res}-3}
-                       file="./tmp/.p.json"
-                       sed 's/XXX/'${2}'/g' $3 > $file
-                       targetJson=$(< $file)
-                       echo "TARGET JSON: $targetJson" >> $HTTPLOG
-                       res=$(python3 ../common/compare_json.py "$targetJson" "$body")
-                       if [ $res -ne 0 ]; then
-                               __log_test_fail_body
-                       fi
-               fi
-       fi
-
-       __collect_endpoint_stats "A1PMS" 01 "GET" $A1PMS_API_PREFIX"/v2/policies/{policy_id}" $status
-       __log_test_pass
-       return 0
+  __log_test_start $@
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    if [ $# -ne 2 ] && [ $# -ne 8 ]; then
+      __print_err "<response-code> <policy-id> [ <template-file> <service-name> <ric-id> <policytype-id>|NOTYPE <transient> <notification-url>|NOURL ]" $@
+      return 1
+    fi
+    query="/v2/policies/$UUID$2"
+  elif [ "$A1PMS_VERSION" == "V3" ]; then
+    if [ $# -ne 2 ] && [ $# -ne 8 ]; then
+      __print_err "<response-code> <policy-id> [ <template-file> <service-name> <ric-id> <policytype-id>|NOTYPE <transient> <notification-url>|NOURL ]" $@
+      return 1
+    fi
+    query="/v1/policies/$UUID$2"
+  else
+    if [ $# -lt 2 ] || [ $# -gt 3 ]; then
+      __print_err "<response-code>  <policy-id> [<template-file>] " $@
+      return 1
+    fi
+    query="/policy?id=$UUID$2"
+  fi
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    if [ $# -eq 8 ]; then
+
+      #Create a policy json to compare with
+      body=${res:0:${#res}-3}
+
+      targetJson="\"ric_id\":\"$5\",\"policy_id\":\"$UUID$2\",\"service_id\":\"$4\""
+      if [ $7 != "NOTRANSIENT" ]; then
+        targetJson=$targetJson", \"transient\":$7"
+      fi
+      if [ $6 != "NOTYPE" ]; then
+        targetJson=$targetJson", \"policytype_id\":\"$6\""
+      else
+        targetJson=$targetJson", \"policytype_id\":\"\""
+      fi
+      if [ $8 != "NOURL" ]; then
+        targetJson=$targetJson", \"status_notification_uri\":\"$8\""
+      fi
+
+      data=$(sed 's/XXX/'${2}'/g' $3)
+      targetJson=$targetJson", \"policy_data\":$data"
+      targetJson="{$targetJson}"
+
+      echo "TARGET JSON: $targetJson" >>$HTTPLOG
+      res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+      if [ $res -ne 0 ]; then
+        __log_test_fail_body
+        return 1
+      fi
+    fi
+  elif [ "$A1PMS_VERSION" == "V3" ]; then
+    if [ $# -eq 8 ]; then
+      #Create a policy json to compare with
+      body=${res:0:${#res}-3}
+      data=$(sed 's/XXX/'${2}'/g' $3)
+      targetJson=$data
+
+      echo "TARGET JSON: $targetJson" >>$HTTPLOG
+      res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+      if [ $res -ne 0 ]; then
+        __log_test_fail_body
+        return 1
+      fi
+    fi
+  else
+    if [ $# -eq 3 ]; then
+      #Create a policy json to compare with
+      body=${res:0:${#res}-3}
+      file="./tmp/.p.json"
+      sed 's/XXX/'${2}'/g' $3 >$file
+      targetJson=$(<$file)
+      echo "TARGET JSON: $targetJson" >>$HTTPLOG
+      res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+      if [ $res -ne 0 ]; then
+        __log_test_fail_body
+      fi
+    fi
+  fi
+
+  __collect_endpoint_stats "A1PMS" 01 "GET" ${A1PMS_API_PREFIX}${query} ${status}
+  __log_test_pass
+  return 0
 }
 
 # API Test function: PUT /policy and V2 PUT /policies
@@ -951,94 +968,209 @@ a1pms_api_get_policy() {
 # args(V2): <response-code> <service-name> <ric-id> <policytype-id>|NOTYPE <policy-id> <transient>|NOTRANSIENT <notification-url>|NOURL <template-file> [<count>]
 # (Function for test scripts)
 a1pms_api_put_policy() {
-       __log_test_start $@
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               if [ $# -lt 8 ] || [ $# -gt 9 ]; then
-                       __print_err "<response-code> <service-name> <ric-id> <policytype-id>|NOTYPE <policy-id> <transient>|NOTRANSIENT <notification-url>|NOURL <template-file> [<count>]" $@
-                       return 1
-               fi
-       else
-               if [ $# -lt 7 ] || [ $# -gt 8 ]; then
-                       __print_err "<response-code> <service-name> <ric-id> <policytype-id>|NOTYPE <policy-id> <transient>|NOTRANSIENT <template-file> [<count>]" $@
-                       return 1
-               fi
-       fi
-
-       count=0
-       max=1
-       serv=$2
-       ric=$3
-       pt=$4
-       pid=$5
-       trans=$6
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               noti=$7
-               temp=$8
-               if [ $# -eq 9 ]; then
-                       max=$9
-               fi
-       else
-               temp=$7
-               if [ $# -eq 8 ]; then
-                       max=$8
-               fi
-       fi
-
-       while [ $count -lt $max ]; do
-               if [ "$A1PMS_VERSION" == "V2" ]; then
-
-                       query="/v2/policies"
-
-                       inputJson="\"ric_id\":\"$ric\",\"policy_id\":\"$UUID$pid\",\"service_id\":\"$serv\""
-                       if [ $trans != "NOTRANSIENT" ]; then
-                               inputJson=$inputJson", \"transient\":$trans"
-                       fi
-                       if [ $pt != "NOTYPE" ]; then
-                               inputJson=$inputJson", \"policytype_id\":\"$pt\""
-                       else
-                               inputJson=$inputJson", \"policytype_id\":\"\""
-                       fi
-                       if [ $noti != "NOURL" ]; then
-                               inputJson=$inputJson", \"status_notification_uri\":\"$noti\""
-                       fi
-                       file="./tmp/.p.json"
-                       data=$(sed 's/XXX/'${pid}'/g' $temp)
-                       inputJson=$inputJson", \"policy_data\":$data"
-                       inputJson="{$inputJson}"
-                       echo $inputJson > $file
-               else
-                       query="/policy?id=$UUID$pid&ric=$ric&service=$serv"
-
-                       if [ $pt != "NOTYPE" ]; then
-                               query=$query"&type=$pt"
-                       fi
-
-                       if [ $trans != NOTRANSIENT ]; then
-                               query=$query"&transient=$trans"
-                       fi
-
-                       file="./tmp/.p.json"
-                       sed 's/XXX/'${pid}'/g' $temp > $file
-               fi
-       res="$(__do_curl_to_api A1PMS PUT $query $file)"
-       status=${res:${#res}-3}
-               echo -ne " Executing "$count"("$max")${SAMELINE}"
-               if [ $status -ne $1 ]; then
-                       echo " Executed "$count"?("$max")"
-                       __log_test_fail_status_code $1 $status
-                       return 1
-               fi
-               let pid=$pid+1
-               let count=$count+1
-               echo -ne " Executed  "$count"("$max")${SAMELINE}"
-       done
-       __collect_endpoint_stats "A1PMS" 02 "PUT" $A1PMS_API_PREFIX"/v2/policies" $status $max
-       echo ""
-
-       __log_test_pass
-       return 0
+  __log_test_start $@
+
+  if [ "$A1PMS_VERSION" == "V2" ] || [ "$A1PMS_VERSION" == "V3" ]; then
+    if [ $# -lt 8 ] || [ $# -gt 9 ]; then
+      __print_err "<response-code> <service-name> <ric-id> <policytype-id>|NOTYPE <policy-id> <transient>|NOTRANSIENT <notification-url>|NOURL <template-file> [<count>]" $@
+      return 1
+    fi
+  else
+    if [ $# -lt 7 ] || [ $# -gt 8 ]; then
+      __print_err "<response-code> <service-name> <ric-id> <policytype-id>|NOTYPE <policy-id> <transient>|NOTRANSIENT <template-file> [<count>]" $@
+      return 1
+    fi
+  fi
+
+  count=0
+  max=1
+  serv=$2
+  ric=$3
+  pt=$4
+  pid=$5
+  trans=$6
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    noti=$7
+    temp=$8
+    if [ $# -eq 9 ]; then
+      max=$9
+    fi
+  else
+    temp=$7
+    if [ $# -eq 8 ]; then
+      max=$8
+    fi
+  fi
+
+  while [ $count -lt $max ]; do
+    if [ "$A1PMS_VERSION" == "V2" ]; then
+
+      query="/v2/policies"
+
+      inputJson="\"ric_id\":\"$ric\",\"policy_id\":\"$UUID$pid\",\"service_id\":\"$serv\""
+      if [ $trans != "NOTRANSIENT" ]; then
+        inputJson=$inputJson", \"transient\":$trans"
+      fi
+      if [ $pt != "NOTYPE" ]; then
+        inputJson=$inputJson", \"policytype_id\":\"$pt\""
+      else
+        inputJson=$inputJson", \"policytype_id\":\"\""
+      fi
+      if [ $noti != "NOURL" ]; then
+        inputJson=$inputJson", \"status_notification_uri\":\"$noti\""
+      fi
+      file="./tmp/.p.json"
+      data=$(sed 's/XXX/'${pid}'/g' $temp)
+      inputJson=$inputJson", \"policy_data\":$data"
+      inputJson="{$inputJson}"
+      echo $inputJson >$file
+    else
+      query="/policy?id=$UUID$pid&ric=$ric&service=$serv"
+
+      if [ $pt != "NOTYPE" ]; then
+        query=$query"&type=$pt"
+      fi
+
+      if [ $trans != NOTRANSIENT ]; then
+        query=$query"&transient=$trans"
+      fi
+
+      file="./tmp/.p.json"
+      sed 's/XXX/'${pid}'/g' $temp >$file
+    fi
+    res="$(__do_curl_to_api A1PMS PUT $query $file)"
+    status=${res:${#res}-3}
+    echo -ne " Executing "$count"("$max")${SAMELINE}"
+    if [ $status -ne $1 ]; then
+      echo " Executed "$count"?("$max")"
+      __log_test_fail_status_code $1 $status
+      return 1
+    fi
+    let pid=$pid+1
+    let count=$count+1
+    echo -ne " Executed  "$count"("$max")${SAMELINE}"
+  done
+  __collect_endpoint_stats "A1PMS" 02 "PUT" ${A1PMS_API_PREFIX}${query} ${status} ${max}
+  echo ""
+
+  __log_test_pass
+  return 0
+}
+
+# API Test function: V3 PUT a1policymanagement/v1/policies
+# args: <response-code>  <policy-id>  <template-file> [<count>]
+# args(V2): <response-code> <policy-id> <template-file> [<count>]
+# (Function for test scripts)
+a1pms_api_put_policy_v3() {
+  __log_test_start $@
+
+  if [ $# -lt 3 ] || [ $# -gt 4 ]; then
+    __print_err "<response-code> <policy-id> <template-file> [<count>]" $@
+    return 1
+  fi
+
+  count=0
+  max=1
+  pid=$2
+  temp=$3
+
+  if [ $# -eq 4 ]; then
+    max=$4
+  fi
+
+  while [ $count -lt $max ]; do
+    query="/v1/policies/$UUID$pid"
+    file="./tmp/.p_v3.json"
+    let update_value=$pid+300
+    data=$(sed 's/XXX/'${update_value}'/g' $temp)
+    inputJson="$data"
+    echo $inputJson >$file
+    res="$(__do_curl_to_api A1PMS PUT $query $file)"
+    status=${res:${#res}-3}
+    echo -ne " Executing "$count"("$max")${SAMELINE}"
+    if [ $status -ne $1 ]; then
+      echo " Executed "$count"?("$max")"
+      __log_test_fail_status_code $1 $status
+      return 1
+    fi
+    let pid=$pid+1
+    let count=$count+1
+    echo -ne " Executed  "$count"("$max")${SAMELINE}"
+  done
+  __collect_endpoint_stats "A1PMS" 02 "PUT" ${A1PMS_API_PREFIX}${query} ${status} ${max}
+  echo ""
+
+  __log_test_pass
+  return 0
+}
+
+# API Test function: V£ POST a1policymanagement/v1/policies
+# args: <response-code> <service-name> <ric-id> <policytype-id>|NOTYPE <policy-id> <transient>|NOTRANSIENT <template-file> [<count>]
+# args(V2): <response-code> <service-name> <ric-id> <policytype-id>|NOTYPE <policy-id> <transient>|NOTRANSIENT <notification-url>|NOURL <template-file> [<count>]
+# (Function for test scripts)
+a1pms_api_post_policy_v3() {
+  __log_test_start $@
+
+  if [ $# -lt 8 ] || [ $# -gt 9 ]; then
+    __print_err "<response-code> <service-name> <ric-id> <policytype-id>|NOTYPE <policy-id> <transient>|NOTRANSIENT <notification-url>|NOURL <template-file> [<count>]" $@
+    return 1
+  fi
+
+  count=0
+  max=1
+  serv=$2
+  ric=$3
+  pt=$4
+  pid=$5
+  trans=$6
+  noti=$7
+  temp=$8
+  if [ $# -eq 9 ]; then
+    max=$9
+  fi
+
+  while [ $count -lt $max ]; do
+    query="/v1/policies"
+
+    inputJson="\"nearRtRicId\":\"$ric\""
+    if [ $pt != "NOTYPE" ]; then
+      inputJson=$inputJson", \"policyTypeId\":\"$pt\""
+    else
+      inputJson=$inputJson", \"policyTypeId\":\"\""
+    fi
+    if [ $serv != "NOSERVICE" ]; then
+      inputJson=$inputJson", \"serviceId\":\"$serv\""
+    fi
+    if [ $noti != "NONOTIFYURL" ]; then
+      inputJson=$inputJson", \"statusNotificationUri\":\"$noti\""
+    fi
+    if [ $trans != "NOTRANSIENT" ]; then
+      inputJson=$inputJson", \"transient\":\"$trans\""
+    fi
+    file="./tmp/.p.json"
+    data=$(sed 's/XXX/'${pid}'/g' $temp)
+    inputJson=$inputJson", \"policyObject\":$data"
+    inputJson=$inputJson", \"policyId\":\"$UUID$pid\""
+    inputJson="{$inputJson}"
+    echo $inputJson >$file
+    res="$(__do_curl_to_api A1PMS POST $query $file)"
+    status=${res:${#res}-3}
+    echo -ne " Executing "$count"("$max")${SAMELINE}"
+    if [ $status -ne $1 ]; then
+      echo " Executed "$count"?("$max")"
+      __log_test_fail_status_code $1 $status
+      return 1
+    fi
+    let pid=$pid+1
+    let count=$count+1
+    echo -ne " Executed  "$count"("$max")${SAMELINE}"
+  done
+  __collect_endpoint_stats "A1PMS" 02 "PUT" ${A1PMS_API_PREFIX}${A1PMS_VERSION} ${status} ${max}
+  echo ""
+
+  __log_test_pass
+  return 0
 }
 
 # API Test function: PUT /policy and V2 PUT /policies, to run in batch
@@ -1047,114 +1179,114 @@ a1pms_api_put_policy() {
 # (Function for test scripts)
 
 a1pms_api_put_policy_batch() {
-       __log_test_start $@
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               if [ $# -lt 8 ] || [ $# -gt 9 ]; then
-                       __print_err "<response-code> <service-name> <ric-id> <policytype-id>|NOTYPE <policy-id> <transient> <notification-url>|NOURL <template-file> [<count>]" $@
-                       return 1
-               fi
-       else
-               if [ $# -lt 7 ] || [ $# -gt 8 ]; then
-                       __print_err "<response-code> <service-name> <ric-id> <policytype-id>|NOTYPE <policy-id> <transient> <template-file> [<count>]" $@
-                       return 1
-               fi
-       fi
-
-       count=0
-       max=1
-       serv=$2
-       ric=$3
-       pt=$4
-       pid=$5
-       trans=$6
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               noti=$7
-               temp=$8
-               if [ $# -eq 9 ]; then
-                       max=$9
-               fi
-       else
-               temp=$7
-               if [ $# -eq 8 ]; then
-                       max=$8
-               fi
-       fi
-
-       ARR=""
-       while [ $count -lt $max ]; do
-               if [ "$A1PMS_VERSION" == "V2" ]; then
-                       query="/v2/policies"
-
-                       inputJson="\"ric_id\":\"$ric\",\"policy_id\":\"$UUID$pid\",\"service_id\":\"$serv\""
-                       if [ $trans != "NOTRANSIENT" ]; then
-                               inputJson=$inputJson", \"transient\":$trans"
-                       fi
-                       if [ $pt != "NOTYPE" ]; then
-                               inputJson=$inputJson", \"policytype_id\":\"$pt\""
-                       else
-                               inputJson=$inputJson", \"policytype_id\":\"\""
-                       fi
-                       if [ $noti != "NOURL" ]; then
-                               inputJson=$inputJson", \"status_notification_uri\":\"$noti\""
-                       fi
-                       file="./tmp/.p.json"
-                       data=$(sed 's/XXX/'${pid}'/g' $temp)
-                       inputJson=$inputJson", \"policy_data\":$data"
-                       inputJson="{$inputJson}"
-                       echo $inputJson > $file
-               else
-                       query="/policy?id=$UUID$pid&ric=$ric&service=$serv"
-
-                       if [ $pt != "NOTYPE" ]; then
-                               query=$query"&type=$pt"
-                       fi
-
-                       if [ $trans != NOTRANSIENT ]; then
-                               query=$query"&transient=$trans"
-                       fi
-                       file="./tmp/.p.json"
-                       sed 's/XXX/'${pid}'/g' $temp > $file
-               fi
-       res="$(__do_curl_to_api A1PMS PUT_BATCH $query $file)"
-       status=${res:${#res}-3}
-               echo -ne " Requesting(batch) "$count"("$max")${SAMELINE}"
-
-               if [ $status -ne 200 ]; then
-                       echo " Requested(batch) "$count"?("$max")"
-                       __log_test_fail_status_code 200 $status
-                       return 1
-               fi
-               cid=${res:0:${#res}-3}
-               ARR=$ARR" "$cid
-               let pid=$pid+1
-               let count=$count+1
-               echo -ne " Requested(batch)  "$count"("$max")${SAMELINE}"
-       done
-
-       echo ""
-       count=0
-       for cid in $ARR; do
-
-       res="$(__do_curl_to_api A1PMS RESPONSE $cid)"
-       status=${res:${#res}-3}
-               echo -ne " Accepting(batch) "$count"("$max")${SAMELINE}"
-
-               if [ $status -ne $1 ]; then
-                       echo " Accepted(batch) "$count"?("$max")"
-                       __log_test_fail_status_code $1 $status
-                       return 1
-               fi
-
-               let count=$count+1
-               echo -ne " Accepted(batch)  "$count"("$max")${SAMELINE}"
-       done
-       __collect_endpoint_stats "A1PMS" 02 "PUT" $A1PMS_API_PREFIX"/v2/policies" $1 $max
-
-       echo ""
-
-       __log_test_pass
-       return 0
+  __log_test_start $@
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    if [ $# -lt 8 ] || [ $# -gt 9 ]; then
+      __print_err "<response-code> <service-name> <ric-id> <policytype-id>|NOTYPE <policy-id> <transient> <notification-url>|NOURL <template-file> [<count>]" $@
+      return 1
+    fi
+  else
+    if [ $# -lt 7 ] || [ $# -gt 8 ]; then
+      __print_err "<response-code> <service-name> <ric-id> <policytype-id>|NOTYPE <policy-id> <transient> <template-file> [<count>]" $@
+      return 1
+    fi
+  fi
+
+  count=0
+  max=1
+  serv=$2
+  ric=$3
+  pt=$4
+  pid=$5
+  trans=$6
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    noti=$7
+    temp=$8
+    if [ $# -eq 9 ]; then
+      max=$9
+    fi
+  else
+    temp=$7
+    if [ $# -eq 8 ]; then
+      max=$8
+    fi
+  fi
+
+  ARR=""
+  while [ $count -lt $max ]; do
+    if [ "$A1PMS_VERSION" == "V2" ]; then
+      query="/v2/policies"
+
+      inputJson="\"ric_id\":\"$ric\",\"policy_id\":\"$UUID$pid\",\"service_id\":\"$serv\""
+      if [ $trans != "NOTRANSIENT" ]; then
+        inputJson=$inputJson", \"transient\":$trans"
+      fi
+      if [ $pt != "NOTYPE" ]; then
+        inputJson=$inputJson", \"policytype_id\":\"$pt\""
+      else
+        inputJson=$inputJson", \"policytype_id\":\"\""
+      fi
+      if [ $noti != "NOURL" ]; then
+        inputJson=$inputJson", \"status_notification_uri\":\"$noti\""
+      fi
+      file="./tmp/.p.json"
+      data=$(sed 's/XXX/'${pid}'/g' $temp)
+      inputJson=$inputJson", \"policy_data\":$data"
+      inputJson="{$inputJson}"
+      echo $inputJson >$file
+    else
+      query="/policy?id=$UUID$pid&ric=$ric&service=$serv"
+
+      if [ $pt != "NOTYPE" ]; then
+        query=$query"&type=$pt"
+      fi
+
+      if [ $trans != NOTRANSIENT ]; then
+        query=$query"&transient=$trans"
+      fi
+      file="./tmp/.p.json"
+      sed 's/XXX/'${pid}'/g' $temp >$file
+    fi
+    res="$(__do_curl_to_api A1PMS PUT_BATCH $query $file)"
+    status=${res:${#res}-3}
+    echo -ne " Requesting(batch) "$count"("$max")${SAMELINE}"
+
+    if [ $status -ne 200 ]; then
+      echo " Requested(batch) "$count"?("$max")"
+      __log_test_fail_status_code 200 $status
+      return 1
+    fi
+    cid=${res:0:${#res}-3}
+    ARR=$ARR" "$cid
+    let pid=$pid+1
+    let count=$count+1
+    echo -ne " Requested(batch)  "$count"("$max")${SAMELINE}"
+  done
+
+  echo ""
+  count=0
+  for cid in $ARR; do
+
+    res="$(__do_curl_to_api A1PMS RESPONSE $cid)"
+    status=${res:${#res}-3}
+    echo -ne " Accepting(batch) "$count"("$max")${SAMELINE}"
+
+    if [ $status -ne $1 ]; then
+      echo " Accepted(batch) "$count"?("$max")"
+      __log_test_fail_status_code $1 $status
+      return 1
+    fi
+
+    let count=$count+1
+    echo -ne " Accepted(batch)  "$count"("$max")${SAMELINE}"
+  done
+  __collect_endpoint_stats "A1PMS" 02 "PUT" $A1PMS_API_PREFIX"/v2/policies" $1 $max
+
+  echo ""
+
+  __log_test_pass
+  return 0
 }
 
 # API Test function: PUT /policy and V2 PUT /policies, to run in i parallel for a number of rics
@@ -1162,490 +1294,998 @@ a1pms_api_put_policy_batch() {
 # args(V2): <response-code> <service-name> <ric-id-base> <number-of-rics> <policytype-id> <policy-start-id> <transient> <notification-url>|NOURL <template-file> <count-per-ric> <number-of-threads>
 # (Function for test scripts)
 a1pms_api_put_policy_parallel() {
-       __log_test_start $@
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               if [ $# -ne 11 ]; then
-                       __print_err "<response-code> <service-name> <ric-id-base> <number-of-rics> <policytype-id> <policy-start-id> <transient> <notification-url>|NOURL <template-file> <count-per-ric> <number-of-threads>" $@
-                       return 1
-               fi
-       else
-               if [ $# -ne 10 ]; then
-                       __print_err " <response-code> <service-name> <ric-id-base> <number-of-rics> <policytype-id> <policy-start-id> <transient> <template-file> <count-per-ric> <number-of-threads>" $@
-                       return 1
-               fi
-       fi
-       resp_code=$1; shift;
-       serv=$1; shift
-       ric_base=$1; shift;
-       num_rics=$1; shift;
-       type=$1; shift;
-       start_id=$1; shift;
-       transient=$1; shift;
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               noti=$1; shift;
-       else
-               noti=""
-       fi
-       template=$1; shift;
-       count=$1; shift;
-       pids=$1; shift;
-
-       #if [ $A1PMS_ADAPTER != $RESTBASE ] && [ $A1PMS_ADAPTER != $RESTBASE_SECURE ]; then
-       if [ $A1PMS_ADAPTER_TYPE != "REST" ]; then
-               echo " Info - a1pms_api_put_policy_parallel uses only the a1pms REST interface - create over dmaap in parallel is not supported"
-               echo " Info - will execute over a1pms REST"
-       fi
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               if [ $serv == "NOSERVICE" ]; then
-                       serv=""
-               fi
-               query="$A1PMS_API_PREFIX/v2/policies"
-       else
-               if [ $serv == "NOSERVICE" ]; then
-                       serv=""
-               fi
-               query="/policy?service=$serv"
-
-               if [ $type != "NOTYPE" ]; then
-                       query=$query"&type=$type"
-               fi
-
-               if [ $transient != NOTRANSIENT ]; then
-                       query=$query"&transient=$transient"
-               fi
-       fi
-
-       urlbase=${A1PMS_ADAPTER}${query}
-
-       httpproxy="NOPROXY"
-       if [ ! -z "$KUBE_PROXY_PATH" ]; then
-               httpproxy=$KUBE_PROXY_PATH
-       fi
-
-       for ((i=1; i<=$pids; i++))
-       do
-               uuid=$UUID
-               if [ -z "$uuid" ]; then
-                       uuid="NOUUID"
-               fi
-               echo "" > "./tmp/.pid${i}.res.txt"
-               if [ "$A1PMS_VERSION" == "V2" ]; then
-                       echo $resp_code $urlbase $ric_base $num_rics $uuid $start_id $serv $type $transient $noti $template $count $pids $i $httpproxy > "./tmp/.pid${i}.txt"
-               else
-                       echo $resp_code $urlbase $ric_base $num_rics $uuid $start_id $template $count $pids $i $httpproxy > "./tmp/.pid${i}.txt"
-               fi
-               echo $i
-       done  | xargs -n 1 -I{} -P $pids bash -c '{
+  __log_test_start $@
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    if [ $# -ne 11 ]; then
+      __print_err "These all arguments needed <response-code> <service-name> <ric-id-base> <number-of-rics> <policytype-id> <policy-start-id> <transient> <notification-url>|NOURL <template-file> <count-per-ric> <number-of-threads>" $@
+      return 1
+    fi
+  fi
+
+  resp_code=$1
+  shift
+  serv=$1
+  shift
+  ric_base=$1
+  shift
+  num_rics=$1
+  shift
+  type=$1
+  shift
+  start_id=$1
+  shift
+  transient=$1
+  shift
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    noti=$1
+    shift
+  else
+    noti=""
+  fi
+  template=$1
+  shift
+  count=$1
+  shift
+  pids=$1
+  shift
+
+  #if [ $A1PMS_ADAPTER != $RESTBASE ] && [ $A1PMS_ADAPTER != $RESTBASE_SECURE ]; then
+  if [ $A1PMS_ADAPTER_TYPE != "REST" ]; then
+    echo " Info - a1pms_api_put_policy_parallel uses only the a1pms REST interface - create over dmaap in parallel is not supported"
+    echo " Info - will execute over a1pms REST"
+  fi
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    if [ $serv == "NOSERVICE" ]; then
+      serv=""
+    fi
+    query="$A1PMS_API_PREFIX/v2/policies"
+  else
+    if [ $serv == "NOSERVICE" ]; then
+      serv=""
+    fi
+    query="/policy?service=$serv"
+
+    if [ $type != "NOTYPE" ]; then
+      query=$query"&type=$type"
+    fi
+
+    if [ $transient != NOTRANSIENT ]; then
+      query=$query"&transient=$transient"
+    fi
+  fi
+
+  urlbase=${A1PMS_ADAPTER}${query}
+
+  httpproxy="NOPROXY"
+  if [ ! -z "$KUBE_PROXY_PATH" ]; then
+    httpproxy=$KUBE_PROXY_PATH
+  fi
+
+  for ((i = 1; i <= $pids; i++)); do
+    uuid=$UUID
+    if [ -z "$uuid" ]; then
+      uuid="NOUUID"
+    fi
+    echo "" >"./tmp/.pid${i}.res.txt"
+    if [ "$A1PMS_VERSION" == "V2" ]; then
+      echo $resp_code $urlbase $ric_base $num_rics $uuid $start_id $serv $type $transient $noti $template $count $pids $i $httpproxy >"./tmp/.pid${i}.txt"
+    else
+      echo $resp_code $urlbase $ric_base $num_rics $uuid $start_id $template $count $pids $i $httpproxy >"./tmp/.pid${i}.txt"
+    fi
+    echo $i
+  done | xargs -n 1 -I{} -P $pids bash -c '{
                arg=$(echo {})
                echo " Parallel process $arg started"
                tmp=$(< "./tmp/.pid${arg}.txt")
                python3 ../common/create_policies_process.py $tmp > ./tmp/.pid${arg}.res.txt
        }'
-       msg=""
-       for ((i=1; i<=$pids; i++))
-       do
-               file="./tmp/.pid${i}.res.txt"
-               tmp=$(< $file)
-               if [ -z "$tmp" ]; then
-                       echo " Process $i : unknown result (result file empty"
-                       msg="failed"
-               else
-                       res=${tmp:0:1}
-                       if [ $res == "0" ]; then
-                               echo " Process $i : OK - "${tmp:1}
-                       else
-                               echo " Process $i : failed - "${tmp:1}
-                               msg="failed"
-                       fi
-               fi
-       done
-       if [ -z $msg ]; then
-               __collect_endpoint_stats "A1PMS" 02 "PUT" $A1PMS_API_PREFIX"/v2/policies" $resp_code $(($count*$num_rics))
-               __log_test_pass " $(($count*$num_rics)) policy request(s) executed"
-               return 0
-       fi
-
-       __log_test_fail_general "One of more processes failed to execute"
-       return 1
+  msg=""
+  for ((i = 1; i <= $pids; i++)); do
+    file="./tmp/.pid${i}.res.txt"
+    tmp=$(<$file)
+    if [ -z "$tmp" ]; then
+      echo " Process $i : unknown result (result file empty"
+      msg="failed"
+    else
+      res=${tmp:0:1}
+      if [ $res == "0" ]; then
+        echo " Process $i : OK - "${tmp:1}
+      else
+        echo " Process $i : failed - "${tmp:1}
+        msg="failed"
+      fi
+    fi
+  done
+  if [ -z $msg ]; then
+    __collect_endpoint_stats "A1PMS" 02 "PUT" $A1PMS_API_PREFIX"/v2/policies" $resp_code $(($count * $num_rics))
+    __log_test_pass " $(($count * $num_rics)) policy request(s) executed"
+    return 0
+  fi
+  __log_test_fail_general "One of more processes failed to execute"
+  return 1
+}
+
+# API Test function: V3 POST /policies, to run in i parallel for a number of rics
+# args: <response-code> <service-name> <ric-id-base> <number-of-rics> <policytype-id> <policy-start-id> <transient> <template-file> <count-per-ric> <number-of-threads>
+# args(V3): <response-code> <service-name> <ric-id-base> <number-of-rics> <policytype-id> <policy-start-id> <transient> <notification-url>|NOURL <template-file> <count-per-ric> <number-of-threads>
+# (Function for test scripts)
+a1pms_api_post_policy_parallel() {
+  __log_test_start $@
+
+  if [ $# -ne 11 ]; then
+    __print_err "These all arguments needed <response-code> <service-name> <ric-id-base> <number-of-rics> <policytype-id> <policy-start-id> <transient> <notification-url>|NOURL <template-file> <count-per-ric> <number-of-threads>" $@
+    return 1
+  fi
+
+  resp_code=$1
+  shift
+  serv=$1
+  shift
+  ric_base=$1
+  shift
+  num_rics=$1
+  shift
+  type=$1
+  shift
+  start_id=$1
+  shift
+  transient=$1
+  shift
+  noti=$1
+  shift
+  template=$1
+  shift
+  count=$1
+  shift
+  pids=$1
+  shift
+
+  #if [ $A1PMS_ADAPTER != $RESTBASE ] && [ $A1PMS_ADAPTER != $RESTBASE_SECURE ]; then
+  if [ $A1PMS_ADAPTER_TYPE != "REST" ]; then
+    echo " Info - a1pms_api_put_policy_parallel uses only the a1pms REST interface - create over dmaap in parallel is not supported"
+    echo " Info - will execute over a1pms REST"
+  fi
+
+  if [ $serv == "NOSERVICE" ]; then
+    serv=""
+  fi
+  query="$A1PMS_API_PREFIX/v1/policies"
+
+  urlbase=${A1PMS_ADAPTER}${query}
+
+  httpproxy="NOPROXY"
+  if [ ! -z "$KUBE_PROXY_PATH" ]; then
+    httpproxy=$KUBE_PROXY_PATH
+  fi
+
+  for ((i = 1; i <= $pids; i++)); do
+    uuid=$UUID
+    if [ -z "$uuid" ]; then
+      uuid="NOUUID"
+    fi
+    echo "" >"./tmp/.pid${i}.res.txt"
+    echo $resp_code $urlbase $ric_base $num_rics $uuid $start_id $serv $type $transient $noti $template $count $pids $i $httpproxy >"./tmp/.pid${i}.txt"
+    echo $i
+  done | xargs -n 1 -I{} -P $pids bash -c '{
+               arg=$(echo {})
+               echo " Parallel process $arg started"
+               tmp=$(< "./tmp/.pid${arg}.txt")
+               python3 ../common/create_policies_process.py $tmp > ./tmp/.pid${arg}.res.txt
+       }'
+  msg=""
+  for ((i = 1; i <= $pids; i++)); do
+    file="./tmp/.pid${i}.res.txt"
+    tmp=$(<$file)
+    if [ -z "$tmp" ]; then
+      echo " Process $i : unknown result (result file empty"
+      msg="failed"
+    else
+      res=${tmp:0:1}
+      if [ $res == "0" ]; then
+        echo " Process $i : OK - "${tmp:1}
+      else
+        echo " Process $i : failed - "${tmp:1}
+        msg="failed"
+      fi
+    fi
+  done
+  if [ -z $msg ]; then
+    __collect_endpoint_stats "A1PMS" 02 "POST" $A1PMS_API_PREFIX"/v1/policies" $resp_code $(($count * $num_rics))
+    __log_test_pass " $(($count * $num_rics)) policy request(s) executed"
+    return 0
+  fi
+  __log_test_fail_general "One of more processes failed to execute"
+  return 1
+}
+
+# API Test function: V3 PUT /policies, to run in i parallel for a number of rics
+# args: <response-code> <service-name> <ric-id-base> <number-of-rics> <policytype-id> <policy-start-id> <transient> <template-file> <count-per-ric> <number-of-threads> <policy-ids-file-path>
+# args(V3): <response-code> <service-name> <ric-id-base> <number-of-rics> <policytype-id> <policy-start-id> <transient> <notification-url>|NOURL <template-file> <count-per-ric> <number-of-threads> <policy-ids-file-path>
+# (Function for test scripts)
+a1pms_api_update_policy_parallel() {
+  __log_test_start $@
+
+  if [ $# -ne 12 ]; then
+    __print_err "These all arguments needed <response-code> <service-name> <ric-id-base> <number-of-rics> <policytype-id> <policy-start-id> <transient> <notification-url>|NOURL <template-file> <count-per-ric> <number-of-threads> <policy-ids-file-path>" $@
+    return 1
+  fi
+
+  resp_code=$1
+  shift
+  serv=$1
+  shift
+  ric_base=$1
+  shift
+  num_rics=$1
+  shift
+  type=$1
+  shift
+  start_id=$1
+  shift
+  transient=$1
+  shift
+  noti=$1
+  shift
+  template=$1
+  shift
+  count=$1
+  shift
+  pids=$1
+  shift
+  policy_ids_file_path=$1
+  shift
+
+  #if [ $A1PMS_ADAPTER != $RESTBASE ] && [ $A1PMS_ADAPTER != $RESTBASE_SECURE ]; then
+  if [ $A1PMS_ADAPTER_TYPE != "REST" ]; then
+    echo " Info - a1pms_api_put_policy_parallel uses only the a1pms REST interface - create over dmaap in parallel is not supported"
+    echo " Info - will execute over a1pms REST"
+  fi
+
+  if [ $serv == "NOSERVICE" ]; then
+    serv=""
+  fi
+  query="$A1PMS_API_PREFIX/v1/policies"
+
+  urlbase=${A1PMS_ADAPTER}${query}
+
+  httpproxy="NOPROXY"
+  if [ ! -z "$KUBE_PROXY_PATH" ]; then
+    httpproxy=$KUBE_PROXY_PATH
+  fi
+
+  for ((i = 1; i <= $pids; i++)); do
+    uuid=$UUID
+    if [ -z "$uuid" ]; then
+      uuid="NOUUID"
+    fi
+    echo "" >"./tmp/.pid${i}.res.txt"
+    echo $resp_code $urlbase $ric_base $num_rics $uuid $start_id $serv $type $transient $noti $template $count $pids $i $httpproxy $policy_ids_file_path >"./tmp/.pid${i}.txt"
+    echo $i
+  done | xargs -n 1 -I{} -P $pids bash -c '{
+               arg=$(echo {})
+               echo " Parallel process $arg started"
+               tmp=$(< "./tmp/.pid${arg}.txt")
+      python3 ../common/update_policies_process.py $tmp > ./tmp/.pid${arg}.res.txt
+       }'
+  msg=""
+  for ((i = 1; i <= $pids; i++)); do
+    file="./tmp/.pid${i}.res.txt"
+    tmp=$(<$file)
+    if [ -z "$tmp" ]; then
+      echo " Process $i : unknown result (result file empty"
+      msg="failed"
+    else
+      res=${tmp:0:1}
+      if [ $res == "0" ]; then
+        echo " Process $i : OK - "${tmp:1}
+      else
+        echo " Process $i : failed - "${tmp:1}
+        msg="failed"
+      fi
+    fi
+  done
+  if [ -z $msg ]; then
+    __collect_endpoint_stats "A1PMS" 02 "POST" $A1PMS_API_PREFIX"/v1/policies" $resp_code $(($count * $num_rics))
+    __log_test_pass " $(($count * $num_rics)) policy request(s) executed"
+    return 0
+  fi
+  __log_test_fail_general "One of more processes failed to execute"
+  return 1
 }
 
-# API Test function: DELETE /policy and V2 DELETE /v2/policies/{policy_id}
+# API Test function: DELETE /policy, V2 DELETE /v2/policies/{policy_id} and V3 DELETE a1policymanagement/v1/policies/{policy_id}
 # args: <response-code> <policy-id> [count]
 # (Function for test scripts)
 a1pms_api_delete_policy() {
-       __log_test_start $@
+  __log_test_start $@
 
-    if [ $# -lt 2 ] || [ $# -gt 3 ]; then
-        __print_err "<response-code> <policy-id> [count]" $@
-        return 1
+  if [ $# -lt 2 ] || [ $# -gt 3 ]; then
+    __print_err "<response-code> <policy-id> [count]" $@
+    return 1
+  fi
+
+  count=0
+  max=1
+
+  if [ $# -eq 3 ]; then
+    max=$3
+  fi
+
+  pid=$2
+
+  while [ $count -lt $max ]; do
+    if [ "$A1PMS_VERSION" == "V2" ]; then
+      query="/v2/policies/"$UUID$pid
+    elif [ "$A1PMS_VERSION" == "V3" ]; then
+      query="/v1/policies/"$UUID$pid
+    else
+      query="/policy?id="$UUID$pid
+    fi
+    res="$(__do_curl_to_api A1PMS DELETE $query)"
+    status=${res:${#res}-3}
+    echo -ne " Executing "${count}"("${max}")${SAMELINE}"
+
+    if [ $status -ne $1 ]; then
+      echo " Executed "${count}"?("${max}")"
+      __log_test_fail_status_code $1 $status
+      return 1
     fi
 
-       count=0
-       max=1
-
-       if [ $# -eq 3 ]; then
-               max=$3
-       fi
-
-       pid=$2
-
-       while [ $count -lt $max ]; do
-               if [ "$A1PMS_VERSION" == "V2" ]; then
-                       query="/v2/policies/"$UUID$pid
-               else
-                       query="/policy?id="$UUID$pid
-               fi
-               res="$(__do_curl_to_api A1PMS DELETE $query)"
-               status=${res:${#res}-3}
-               echo -ne " Executing "$count"("$max")${SAMELINE}"
-
-               if [ $status -ne $1 ]; then
-                       echo " Executed "$count"?("$max")"
-                       __log_test_fail_status_code $1 $status
-                       return 1
-               fi
-
-               let pid=$pid+1
-               let count=$count+1
-               echo -ne " Executed  "$count"("$max")${SAMELINE}"
-       done
-       __collect_endpoint_stats "A1PMS" 03 "DELETE" $A1PMS_API_PREFIX"/v2/policies/{policy_id}" $status $max
-       echo ""
-
-       __log_test_pass
-       return 0
+    let pid=$pid+1
+    let count=$count+1
+    echo -ne " Executed  "${count}"("${max}")${SAMELINE}"
+  done
+  __collect_endpoint_stats "A1PMS" 03 "DELETE" ${A1PMS_API_PREFIX}${query} ${status} ${max}
+  echo ""
+
+  __log_test_pass
+  return 0
 }
 
 # API Test function: DELETE /policy and V2 DELETE /v2/policies/{policy_id}, to run in batch
 # args: <response-code> <policy-id> [count]
 # (Function for test scripts)
 a1pms_api_delete_policy_batch() {
-       __log_test_start $@
+  __log_test_start $@
+
+  if [ $# -lt 2 ] || [ $# -gt 3 ]; then
+    __print_err "<response-code> <policy-id> [count]" $@
+    return 1
+  fi
+
+  count=0
+  max=1
+
+  if [ $# -eq 3 ]; then
+    max=$3
+  fi
+
+  pid=$2
+  ARR=""
+  while [ $count -lt $max ]; do
+    if [ "$A1PMS_VERSION" == "V2" ]; then
+      query="/v2/policies/"$UUID$pid
+    else
+      query="/policy?id="$UUID$pid
+    fi
+    res="$(__do_curl_to_api A1PMS DELETE_BATCH $query)"
+    status=${res:${#res}-3}
+    echo -ne " Requesting(batch) "$count"("$max")${SAMELINE}"
 
-    if [ $# -lt 2 ] || [ $# -gt 3 ]; then
-        __print_err "<response-code> <policy-id> [count]" $@
-        return 1
+    if [ $status -ne 200 ]; then
+      echo " Requested(batch) "$count"?("$max")"
+      __log_test_fail_status_code 200 $status
+      return 1
+    fi
+    cid=${res:0:${#res}-3}
+    ARR=$ARR" "$cid
+    let pid=$pid+1
+    let count=$count+1
+    echo -ne " Requested(batch)  "$count"("$max")${SAMELINE}"
+  done
+
+  echo ""
+
+  count=0
+  for cid in $ARR; do
+
+    res="$(__do_curl_to_api A1PMS RESPONSE $cid)"
+    status=${res:${#res}-3}
+    echo -ne " Deleting(batch) "$count"("$max")${SAMELINE}"
+
+    if [ $status -ne $1 ]; then
+      echo " Deleted(batch) "$count"?("$max")"
+      __log_test_fail_status_code $1 $status
+      return 1
     fi
 
-       count=0
-       max=1
-
-       if [ $# -eq 3 ]; then
-               max=$3
-       fi
-
-       pid=$2
-       ARR=""
-       while [ $count -lt $max ]; do
-               if [ "$A1PMS_VERSION" == "V2" ]; then
-                       query="/v2/policies/"$UUID$pid
-               else
-                       query="/policy?id="$UUID$pid
-               fi
-               res="$(__do_curl_to_api A1PMS DELETE_BATCH $query)"
-               status=${res:${#res}-3}
-               echo -ne " Requesting(batch) "$count"("$max")${SAMELINE}"
-
-               if [ $status -ne 200 ]; then
-                       echo " Requested(batch) "$count"?("$max")"
-                       __log_test_fail_status_code 200 $status
-                       return 1
-               fi
-               cid=${res:0:${#res}-3}
-               ARR=$ARR" "$cid
-               let pid=$pid+1
-               let count=$count+1
-               echo -ne " Requested(batch)  "$count"("$max")${SAMELINE}"
-       done
-
-       echo ""
-
-       count=0
-       for cid in $ARR; do
-
-       res="$(__do_curl_to_api A1PMS RESPONSE $cid)"
-       status=${res:${#res}-3}
-               echo -ne " Deleting(batch) "$count"("$max")${SAMELINE}"
-
-               if [ $status -ne $1 ]; then
-                       echo " Deleted(batch) "$count"?("$max")"
-                       __log_test_fail_status_code $1 $status
-                       return 1
-               fi
-
-               let count=$count+1
-               echo -ne " Deleted(batch)  "$count"("$max")${SAMELINE}"
-       done
-       __collect_endpoint_stats "A1PMS" 03 "DELETE" $A1PMS_API_PREFIX"/v2/policies/{policy_id}" $1 $max
-
-       echo ""
-
-       __log_test_pass
-       return 0
+    let count=$count+1
+    echo -ne " Deleted(batch)  "$count"("$max")${SAMELINE}"
+  done
+  __collect_endpoint_stats "A1PMS" 03 "DELETE" $A1PMS_API_PREFIX"/v2/policies/{policy_id}" $1 $max
+
+  echo ""
+
+  __log_test_pass
+  return 0
 }
 
 # API Test function: DELETE /policy and V2 DELETE /v2/policies/{policy_id}, to run in i parallel for a number of rics
 # args: <response-code> <number-of-rics> <policy-start-id> <count-per-ric> <number-of-threads>
 # (Function for test scripts)
 a1pms_api_delete_policy_parallel() {
-       __log_test_start $@
-
-    if [ $# -ne 5 ]; then
-        __print_err " <response-code> <ric-id-base> <number-of-rics> <policy-start-id> <count-per-ric> <number-of-threads>" $@
-        return 1
+  __log_test_start $@
+
+  if [ $# -ne 5 ]; then
+    __print_err " <response-code> <ric-id-base> <number-of-rics> <policy-start-id> <count-per-ric> <number-of-threads>" $@
+    return 1
+  fi
+  resp_code=$1
+  shift
+  num_rics=$1
+  shift
+  start_id=$1
+  shift
+  count=$1
+  shift
+  pids=$1
+  shift
+
+  #if [ $A1PMS_ADAPTER != $RESTBASE ] && [ $A1PMS_ADAPTER != $RESTBASE_SECURE ]; then
+  if [ $A1PMS_ADAPTER_TYPE != "REST" ]; then
+    echo " Info - a1pms_api_delete_policy_parallel uses only the a1pms REST interface - delete over dmaap in parallel is not supported"
+    echo " Info - will execute over a1pms REST"
+  fi
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    query="$A1PMS_API_PREFIX/v2/policies/"
+  else
+    query="/policy"
+  fi
+
+  urlbase=${A1PMS_ADAPTER}${query}
+
+  httpproxy="NOPROXY"
+  if [ ! -z "$KUBE_PROXY_PATH" ]; then
+    httpproxy=$KUBE_PROXY_PATH
+  fi
+
+  for ((i = 1; i <= $pids; i++)); do
+    uuid=$UUID
+    if [ -z "$uuid" ]; then
+      uuid="NOUUID"
     fi
-       resp_code=$1; shift;
-       num_rics=$1; shift;
-       start_id=$1; shift;
-       count=$1; shift;
-       pids=$1; shift;
-
-       #if [ $A1PMS_ADAPTER != $RESTBASE ] && [ $A1PMS_ADAPTER != $RESTBASE_SECURE ]; then
-       if [ $A1PMS_ADAPTER_TYPE != "REST" ]; then
-               echo " Info - a1pms_api_delete_policy_parallel uses only the a1pms REST interface - create over dmaap in parallel is not supported"
-               echo " Info - will execute over a1pms REST"
-       fi
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               query="$A1PMS_API_PREFIX/v2/policies/"
-       else
-               query="/policy"
-       fi
-
-       urlbase=${A1PMS_ADAPTER}${query}
-
-       httpproxy="NOPROXY"
-       if [ ! -z "$KUBE_PROXY_PATH" ]; then
-               httpproxy=$KUBE_PROXY_PATH
-       fi
-
-       for ((i=1; i<=$pids; i++))
-       do
-               uuid=$UUID
-               if [ -z "$uuid" ]; then
-                       uuid="NOUUID"
-               fi
-               echo "" > "./tmp/.pid${i}.del.res.txt"
-               echo $resp_code $urlbase $num_rics $uuid $start_id $count $pids $i $httpproxy> "./tmp/.pid${i}.del.txt"
-               echo $i
-       done  | xargs -n 1 -I{} -P $pids bash -c '{
+    echo "" >"./tmp/.pid${i}.del.res.txt"
+    echo $resp_code $urlbase $num_rics $uuid $start_id $count $pids $i $httpproxy >"./tmp/.pid${i}.del.txt"
+    echo $i
+  done | xargs -n 1 -I{} -P $pids bash -c '{
                arg=$(echo {})
                echo " Parallel process $arg started"
                tmp=$(< "./tmp/.pid${arg}.del.txt")
                python3 ../common/delete_policies_process.py $tmp > ./tmp/.pid${arg}.del.res.txt
        }'
-       msg=""
-       for ((i=1; i<=$pids; i++))
-       do
-               file="./tmp/.pid${i}.del.res.txt"
-               tmp=$(< $file)
-               if [ -z "$tmp" ]; then
-                       echo " Process $i : unknown result (result file empty"
-                       msg="failed"
-               else
-                       res=${tmp:0:1}
-                       if [ $res == "0" ]; then
-                               echo " Process $i : OK - "${tmp:1}
-                       else
-                               echo " Process $i : failed - "${tmp:1}
-                               msg="failed"
-                       fi
-               fi
-       done
-       if [ -z $msg ]; then
-               __collect_endpoint_stats "A1PMS" 03 "DELETE" $A1PMS_API_PREFIX"/v2/policies/{policy_id}" $resp_code $(($count*$num_rics))
-               __log_test_pass " $(($count*$num_rics)) policy request(s) executed"
-               return 0
-       fi
-
-       __log_test_fail_general "One of more processes failed to execute"
-       return 1
+  msg=""
+  for ((i = 1; i <= $pids; i++)); do
+    file="./tmp/.pid${i}.del.res.txt"
+    tmp=$(<$file)
+    if [ -z "$tmp" ]; then
+      echo " Process $i : unknown result (result file empty"
+      msg="failed"
+    else
+      res=${tmp:0:1}
+      if [ $res == "0" ]; then
+        echo " Process $i : OK - "${tmp:1}
+      else
+        echo " Process $i : failed - "${tmp:1}
+        msg="failed"
+      fi
+    fi
+  done
+  if [ -z $msg ]; then
+    __collect_endpoint_stats "A1PMS" 03 "DELETE" $A1PMS_API_PREFIX"/v2/policies/{policy_id}" $resp_code $(($count * $num_rics))
+    __log_test_pass " $(($count * $num_rics)) policy request(s) executed"
+    return 0
+  fi
+
+  __log_test_fail_general "One of more processes failed to execute"
+  return 1
+}
+
+# API Test function: V3 DELETE a1policymanagement/v1/policies/{policy_id}, to run in i parallel for a number of rics
+# args: <responseCode> <numberOfRics> <PolicyIdsFilePath> <countPerRic> <numberOfThreads>
+# (Function for test scripts)
+a1pms_api_delete_policy_parallel_v3() {
+  __log_test_start $@
+
+  if [ $# -ne 6 ]; then
+    __print_err " <responseCode> <numberOfRics> <PolicyIdsFilePath> <StartID> <countPerRic> <numberOfThreads>" $@
+    return 1
+  fi
+  resp_code=$1
+  shift
+  num_rics=$1
+  shift
+  policy_ids_file_path=$1
+  shift
+  start_id=$1
+  shift
+  count=$1
+  shift
+  pids=$1
+  shift
+
+  #if [ $A1PMS_ADAPTER != $RESTBASE ] && [ $A1PMS_ADAPTER != $RESTBASE_SECURE ]; then
+  if [ $A1PMS_ADAPTER_TYPE != "REST" ]; then
+    echo " Info - a1pms_api_delete_policy_parallel uses only the a1pms REST interface - delete over dmaap in parallel is not supported"
+    echo " Info - will execute over a1pms REST"
+  fi
+
+  query="$A1PMS_API_PREFIX/v1/policies/"
+  urlbase=${A1PMS_ADAPTER}${query}
+
+  urlbase=${A1PMS_ADAPTER}${query}
+
+  httpproxy="NOPROXY"
+  if [ ! -z "$KUBE_PROXY_PATH" ]; then
+    httpproxy=$KUBE_PROXY_PATH
+  fi
+
+  for ((i = 1; i <= $pids; i++)); do
+    echo "" >"./tmp/.pid${i}.del.res.txt"
+    echo $resp_code $urlbase $policy_ids_file_path $start_id $pids $i $httpproxy >"./tmp/.pid${i}.del.txt"
+    echo $i
+  done | xargs -n 1 -I{} -P $pids bash -c '{
+               arg=$(echo {})
+               echo " Parallel process $arg started"
+               tmp=$(< "./tmp/.pid${arg}.del.txt")
+               python3 ../common/delete_policies_process_v3.py $tmp > ./tmp/.pid${arg}.del.res.txt
+       }'
+  msg=""
+  for ((i = 1; i <= $pids; i++)); do
+    file="./tmp/.pid${i}.del.res.txt"
+    tmp=$(<$file)
+    if [ -z "$tmp" ]; then
+      echo " Process $i : unknown result (result file empty"
+      msg="failed"
+    else
+      res=${tmp:0:1}
+      if [ $res == "0" ]; then
+        echo " Process $i : OK - "${tmp:1}
+      else
+        echo " Process $i : failed - "${tmp:1}
+        msg="failed"
+      fi
+    fi
+  done
+  if [ -z $msg ]; then
+    __collect_endpoint_stats "A1PMS" 03 "DELETE" $A1PMS_API_PREFIX"/v1/policies/{policy_id}" $resp_code $(($count * $num_rics))
+    __log_test_pass " $(($count * $num_rics)) policy request(s) executed"
+    return 0
+  fi
+
+  __log_test_fail_general "One of more processes failed to execute"
+  return 1
+}
+
+# API Test function: GET /policy and V2 GET /v2/policies/{policy_id}, to run in i parallel for a number of rics
+# args: <response-code> <number-of-rics> <policy-start-id> <count-per-ric> <number-of-threads>
+# (Function for test scripts)
+a1pms_api_get_policy_parallel() {
+  __log_test_start $@
+
+  if [ $# -ne 5 ]; then
+    __print_err " <response-code> <ric-id-base> <number-of-rics> <policy-start-id> <count-per-ric> <number-of-threads>" $@
+    return 1
+  fi
+  resp_code=$1
+  shift
+  num_rics=$1
+  shift
+  start_id=$1
+  shift
+  count=$1
+  shift
+  pids=$1
+  shift
+
+  #if [ $A1PMS_ADAPTER != $RESTBASE ] && [ $A1PMS_ADAPTER != $RESTBASE_SECURE ]; then
+  if [ $A1PMS_ADAPTER_TYPE != "REST" ]; then
+    echo " Info - a1pms_api_get_policy_parallel uses only the a1pms REST interface - GET over dmaap in parallel is not supported"
+    echo " Info - will execute over a1pms REST"
+  fi
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    query="$A1PMS_API_PREFIX/v2/policies/"
+  else
+    query="/policy"
+  fi
+
+  urlbase=${A1PMS_ADAPTER}${query}
+
+  httpproxy="NOPROXY"
+  if [ ! -z "$KUBE_PROXY_PATH" ]; then
+    httpproxy=$KUBE_PROXY_PATH
+  fi
+
+  for ((i = 1; i <= $pids; i++)); do
+    uuid=$UUID
+    if [ -z "$uuid" ]; then
+      uuid="NOUUID"
+    fi
+    echo "" >"./tmp/.pid${i}.get.res.txt"
+    echo $resp_code $urlbase $num_rics $uuid $start_id $count $pids $i $httpproxy >"./tmp/.pid${i}.get.txt"
+    echo $i
+  done | xargs -n 1 -I{} -P $pids bash -c '{
+               arg=$(echo {})
+               echo " Parallel process $arg started"
+               tmp=$(< "./tmp/.pid${arg}.get.txt")
+               python3 ../common/get_policies_process.py $tmp > ./tmp/.pid${arg}.get.res.txt
+       }'
+  msg=""
+  for ((i = 1; i <= $pids; i++)); do
+    file="./tmp/.pid${i}.get.res.txt"
+    tmp=$(<$file)
+    if [ -z "$tmp" ]; then
+      echo " Process $i : unknown result (result file empty"
+      msg="failed"
+    else
+      res=${tmp:0:1}
+      if [ $res == "0" ]; then
+        echo " Process $i : OK - "${tmp:1}
+      else
+        echo " Process $i : failed - "${tmp:1}
+        msg="failed"
+      fi
+    fi
+  done
+  if [ -z $msg ]; then
+    __collect_endpoint_stats "A1PMS" 04 "GET" $A1PMS_API_PREFIX"/v2/policies/{policy_id}" $resp_code $(($count * $num_rics))
+    __log_test_pass " $(($count * $num_rics)) policy request(s) executed"
+    return 0
+  fi
+
+  __log_test_fail_general "One of more processes failed to execute"
+  return 1
+}
+
+# API Test function: V3 GET a1policymanagement/v1/policies/{policy_id}, to run in i parallel for a number of rics
+# args: <response-code> <number-of-rics> <policy-start-id> <count-per-ric> <number-of-threads>
+# (Function for test scripts)
+a1pms_api_get_policy_parallel_v3() {
+  __log_test_start $@
+
+  if [ $# -ne 6 ]; then
+    __print_err " <responseCode> <numberOfRics> <PolicyIdsFilePath> <startID> <countPerRic> <numberOfThreads>" $@
+    return 1
+  fi
+  resp_code=$1
+  shift
+  num_rics=$1
+  shift
+  policy_ids_file_path=$1
+  shift
+  start_id=$1
+  shift
+  count=$1
+  shift
+  pids=$1
+  shift
+
+  #if [ $A1PMS_ADAPTER != $RESTBASE ] && [ $A1PMS_ADAPTER != $RESTBASE_SECURE ]; then
+  if [ $A1PMS_ADAPTER_TYPE != "REST" ]; then
+    echo " Info - a1pms_api_get_policy_parallel uses only the a1pms REST interface - GET over dmaap in parallel is not supported"
+    echo " Info - will execute over a1pms REST"
+  fi
+
+  query="$A1PMS_API_PREFIX/v1/policies/"
+  urlbase=${A1PMS_ADAPTER}${query}
+
+  httpproxy="NOPROXY"
+  if [ ! -z "$KUBE_PROXY_PATH" ]; then
+    httpproxy=$KUBE_PROXY_PATH
+  fi
+
+  for ((i = 1; i <= $pids; i++)); do
+    echo "" >"./tmp/.pid${i}.get.res.txt"
+    echo $resp_code $urlbase $policy_ids_file_path $start_id $pids $i $httpproxy >"./tmp/.pid${i}.get.txt"
+    echo $i
+  done | xargs -n 1 -I{} -P $pids bash -c '{
+               arg=$(echo {})
+               echo " Parallel process $arg started"
+               tmp=$(< "./tmp/.pid${arg}.get.txt")
+               python3 ../common/get_policies_process_v3.py $tmp > ./tmp/.pid${arg}.get.res.txt
+       }'
+  msg=""
+  for ((i = 1; i <= $pids; i++)); do
+    file="./tmp/.pid${i}.get.res.txt"
+    tmp=$(<$file)
+    if [ -z "$tmp" ]; then
+      echo " Process $i : unknown result (result file empty"
+      msg="failed"
+    else
+      res=${tmp:0:1}
+      if [ $res == "0" ]; then
+        echo " Process $i : OK - "${tmp:1}
+      else
+        echo " Process $i : failed - "${tmp:1}
+        msg="failed"
+      fi
+    fi
+  done
+  if [ -z $msg ]; then
+    __collect_endpoint_stats "A1PMS" 04 "GET" $A1PMS_API_PREFIX"/v1/policies/{policyId}" $resp_code $(($count * $num_rics))
+    __log_test_pass " $(($count * $num_rics)) policy request(s) executed"
+    return 0
+  fi
+
+  __log_test_fail_general "One of more processes failed to execute"
+  return 1
 }
 
 # API Test function: GET /policy_ids and V2 GET /v2/policies
 # args: <response-code> <ric-id>|NORIC <service-id>|NOSERVICE <type-id>|NOTYPE ([<policy-instance-id]*|NOID)
 # (Function for test scripts)
 a1pms_api_get_policy_ids() {
-       __log_test_start $@
+  __log_test_start $@
 
-    if [ $# -lt 4 ]; then
-               __print_err "<response-code> <ric-id>|NORIC <service-id>|NOSERVICE <type-id>|NOTYPE ([<policy-instance-id]*|NOID)" $@
-               return 1
-       fi
-
-       queryparams=""
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               if [ $2 != "NORIC" ]; then
-                       queryparams="?ric_id="$2
-               fi
-
-               if [ $3 != "NOSERVICE" ]; then
-                       if [ -z $queryparams ]; then
-                               queryparams="?service_id="$3
-                       else
-                               queryparams=$queryparams"&service_id="$3
-                       fi
-               fi
-               if [ $4 != "NOTYPE" ]; then
-                       if [ -z $queryparams ]; then
-                               queryparams="?policytype_id="$4
-                       else
-                               queryparams=$queryparams"&policytype_id="$4
-                       fi
-               fi
-
-               query="/v2/policies"$queryparams
-       else
-               if [ $2 != "NORIC" ]; then
-                       queryparams="?ric="$2
-               fi
-
-               if [ $3 != "NOSERVICE" ]; then
-                       if [ -z $queryparams ]; then
-                               queryparams="?service="$3
-                       else
-                               queryparams=$queryparams"&service="$3
-                       fi
-               fi
-               if [ $4 != "NOTYPE" ]; then
-                       if [ -z $queryparams ]; then
-                               queryparams="?type="$4
-                       else
-                               queryparams=$queryparams"&type="$4
-                       fi
-               fi
-
-               query="/policy_ids"$queryparams
-       fi
+  if [ $# -lt 4 ]; then
+    __print_err "<response-code> <ric-id>|NORIC <service-id>|NOSERVICE <type-id>|NOTYPE ([<policy-instance-id]*|NOID)" $@
+    return 1
+  fi
 
-    res="$(__do_curl_to_api A1PMS GET $query)"
-    status=${res:${#res}-3}
+  queryparams=""
 
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-
-       if [ $# -gt 4 ]; then
-               body=${res:0:${#res}-3}
-               targetJson="["
-
-               for pid in ${@:5} ; do
-                       if [ "$targetJson" != "[" ]; then
-                               targetJson=$targetJson","
-                       fi
-                       if [ $pid != "NOID" ]; then
-                               targetJson=$targetJson"\"$UUID$pid\""
-                       fi
-               done
-
-               targetJson=$targetJson"]"
-               if [ "$A1PMS_VERSION" == "V2" ]; then
-                       targetJson="{\"policy_ids\": $targetJson}"
-               fi
-               echo "TARGET JSON: $targetJson" >> $HTTPLOG
-               res=$(python3 ../common/compare_json.py "$targetJson" "$body")
-
-               if [ $res -ne 0 ]; then
-                       __log_test_fail_body
-                       return 1
-               fi
-       fi
-
-       __collect_endpoint_stats "A1PMS" 04 "GET" $A1PMS_API_PREFIX"/v2/policies" $status
-       __log_test_pass
-       return 0
-}
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    if [ $2 != "NORIC" ]; then
+      queryparams="?ric_id="$2
+    fi
 
-# API Test function: V2 GET /v2/policy-types/{policyTypeId}
-# args(V2): <response-code> <policy-type-id> [<schema-file>]
-# (Function for test scripts)
-a1pms_api_get_policy_type() {
-       __log_test_start $@
+    if [ $3 != "NOSERVICE" ]; then
+      if [ -z $queryparams ]; then
+        queryparams="?service_id="$3
+      else
+        queryparams=$queryparams"&service_id="$3
+      fi
+    fi
+    if [ $4 != "NOTYPE" ]; then
+      if [ -z $queryparams ]; then
+        queryparams="?policytype_id="$4
+      else
+        queryparams=$queryparams"&policytype_id="$4
+      fi
+    fi
 
-       if [ "$A1PMS_VERSION" != "V2" ]; then
-               __log_test_fail_not_supported
-               return 1
-       fi
+    query="/v2/policies"$queryparams
+  else
+    if [ $2 != "NORIC" ]; then
+      queryparams="?ric="$2
+    fi
 
-    if [ $# -lt 2 ] || [ $# -gt 3 ]; then
-        __print_err "<response-code> <policy-type-id> [<schema-file>]" $@
-        return 1
+    if [ $3 != "NOSERVICE" ]; then
+      if [ -z $queryparams ]; then
+        queryparams="?service="$3
+      else
+        queryparams=$queryparams"&service="$3
+      fi
+    fi
+    if [ $4 != "NOTYPE" ]; then
+      if [ -z $queryparams ]; then
+        queryparams="?type="$4
+      else
+        queryparams=$queryparams"&type="$4
+      fi
+    fi
+
+    query="/policy_ids"$queryparams
+  fi
+
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  if [ $# -gt 4 ]; then
+    body=${res:0:${#res}-3}
+    targetJson="["
+
+    for pid in ${@:5}; do
+      if [ "$targetJson" != "[" ]; then
+        targetJson=$targetJson","
+      fi
+      if [ $pid != "NOID" ]; then
+        targetJson=$targetJson"\"$UUID$pid\""
+      fi
+    done
+
+    targetJson=$targetJson"]"
+    if [ "$A1PMS_VERSION" == "V2" ]; then
+      targetJson="{\"policy_ids\": $targetJson}"
+    fi
+    echo "TARGET JSON: $targetJson" >>$HTTPLOG
+    res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+
+    if [ $res -ne 0 ]; then
+      __log_test_fail_body
+      return 1
     fi
-       query="/v2/policy-types/$2"
+  fi
+
+  __collect_endpoint_stats "A1PMS" 04 "GET" $A1PMS_API_PREFIX"/v2/policies" $status
+  __log_test_pass
+  return 0
+}
+
+# API Test function: V3 GET a1policymanagement/v1/policies
+# args: <response-code> <ric-id>|NORIC <service-id>|NOSERVICE <type-id>|NOTYPE ([<policy-instance-id]*|NOID)
+# (Function for test scripts)
+a1pms_api_get_all_policies_v3() {
+  __log_test_start $@
 
-       res="$(__do_curl_to_api A1PMS GET $query)"
-       status=${res:${#res}-3}
+  if [ $# -lt 4 ]; then
+    __print_err "<response-code> <ric-id>|NORIC <service-id>|NOSERVICE <type-id>|NOTYPE ([<policy-instance-id]*|NOID)" $@
+    return 1
+  fi
 
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
+  queryparams=""
 
-       if [ $# -eq 3 ]; then
+  if [ $2 != "NORIC" ]; then
+    queryparams="?nearRtRicId="$2
+  fi
 
-               body=${res:0:${#res}-3}
+  if [ $3 != "NOSERVICE" ]; then
+    if [ -z $queryparams ]; then
+      queryparams="?serviceId="$3
+    else
+      queryparams=$queryparams"&serviceId="$3
+    fi
+  fi
+  if [ $4 != "NOTYPE" ]; then
+    if [ -z $queryparams ]; then
+      queryparams="?policyTypeId="$4
+    else
+      queryparams=$queryparams"&policyTypeId="$4
+    fi
+  fi
+
+  query="/v1/policies"$queryparams
+
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  if [ $# -gt 4 ]; then
+    body=${res:0:${#res}-3}
+    targetJson="["
+
+    for pid in ${@:5}; do
+      if [ "$targetJson" != "[" ]; then
+        targetJson=$targetJson","
+      fi
+      IFS=':' read -r policy_id ric_id <<<"$pid"
+      if [ $policy_id != "NOID" ]; then
+        targetJson=$targetJson"{ \"policyId\": \"${UUID}${policy_id}\", \"nearRtRicId\": \"$ric_id\" }"
+      fi
+    done
+
+    targetJson=$targetJson"]"
+    echo "TARGET JSON: $targetJson" >>$HTTPLOG
+    res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+
+    if [ $res -ne 0 ]; then
+      __log_test_fail_body
+      return 1
+    fi
+  fi
 
-               targetJson=$(< $3)
-               targetJson="{\"policy_schema\":$targetJson}"
-               echo "TARGET JSON: $targetJson" >> $HTTPLOG
-               res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+  __collect_endpoint_stats "A1PMS" 04 "GET" ${A1PMS_API_PREFIX}${query} ${status}
+  __log_test_pass
+  return 0
+}
 
-               if [ $res -ne 0 ]; then
-                       __log_test_fail_body
-                       return 1
-               fi
-       fi
+# API Test function: V2 GET a1-policy/v2/policy-types/{policyTypeId} and V3 GET a1policymanagement/v1/policytypes/{policyTypeId}
+# args(V2): <response-code> <policy-type-id> [<schema-file>]
+# (Function for test scripts)
+a1pms_api_get_policy_type() {
+  __log_test_start $@
+
+  if [ "$A1PMS_VERSION" != "V2" ] && [ "$A1PMS_VERSION" != "V3" ]; then
+    __log_test_fail_not_supported
+    return 1
+  fi
+
+  if [ $# -lt 2 ] || [ $# -gt 3 ]; then
+    __print_err "<response-code> <policy-type-id> [<schema-file>]" $@
+    return 1
+  fi
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    query="/v2/policy-types/$2"
+  fi
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    query="/v1/policytypes/$2"
+  fi
+
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  if [ $# -eq 3 ]; then
+
+    body=${res:0:${#res}-3}
+
+    targetJson=$(<$3)
+    if [ "$A1PMS_VERSION" == "V2" ]; then
+      targetJson="{\"policy_schema\":$targetJson}"
+    elif [ "$A1PMS_VERSION" == "V3" ]; then
+      targetJson="$targetJson"
+    fi
+    echo "TARGET JSON: $targetJson" >>$HTTPLOG
+    res=$(python3 ../common/compare_json.py "$targetJson" "$body")
 
-       __collect_endpoint_stats "A1PMS" 05 "GET" $A1PMS_API_PREFIX"/v2/policy-types/{policyTypeId}" $status
-       __log_test_pass
-       return 0
+    if [ $res -ne 0 ]; then
+      __log_test_fail_body
+      return 1
+    fi
+  fi
+
+  __collect_endpoint_stats "A1PMS" 05 "GET" ${A1PMS_API_PREFIX}${query} ${status}
+  __log_test_pass
+  return 0
 }
 
 # API Test function: GET /policy_schema
 # args: <response-code> <policy-type-id> [<schema-file>]
 # (Function for test scripts)
 a1pms_api_get_policy_schema() {
-       __log_test_start $@
+  __log_test_start $@
 
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               __log_test_fail_not_supported
-               return 1
-       fi
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    __log_test_fail_not_supported
+    return 1
+  fi
 
-    if [ $# -lt 2 ] || [ $# -gt 3 ]; then
-        __print_err "<response-code> <policy-type-id> [<schema-file>]" $@
-        return 1
-    fi
-       query="/policy_schema?id=$2"
-       res="$(__do_curl_to_api A1PMS GET $query)"
-       status=${res:${#res}-3}
+  if [ $# -lt 2 ] || [ $# -gt 3 ]; then
+    __print_err "<response-code> <policy-type-id> [<schema-file>]" $@
+    return 1
+  fi
+  query="/policy_schema?id=$2"
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  status=${res:${#res}-3}
 
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
 
-       if [ $# -eq 3 ]; then
+  if [ $# -eq 3 ]; then
 
-               body=${res:0:${#res}-3}
+    body=${res:0:${#res}-3}
 
-               targetJson=$(< $3)
+    targetJson=$(<$3)
 
-               echo "TARGET JSON: $targetJson" >> $HTTPLOG
-               res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+    echo "TARGET JSON: $targetJson" >>$HTTPLOG
+    res=$(python3 ../common/compare_json.py "$targetJson" "$body")
 
-               if [ $res -ne 0 ]; then
-                       __log_test_fail_body
-                       return 1
-               fi
-       fi
+    if [ $res -ne 0 ]; then
+      __log_test_fail_body
+      return 1
+    fi
+  fi
 
-       __collect_endpoint_stats "A1PMS" 06 "GET" $A1PMS_API_PREFIX"/v2/policy_schema" $status
-       __log_test_pass
-       return 0
+  __collect_endpoint_stats "A1PMS" 06 "GET" $A1PMS_API_PREFIX"/v2/policy_schema" $status
+  __log_test_pass
+  return 0
 }
 
 # API Test function: GET /policy_schemas
@@ -1653,743 +2293,906 @@ a1pms_api_get_policy_schema() {
 # args(V2): <response-code>
 # (Function for test scripts)
 a1pms_api_get_policy_schemas() {
-       __log_test_start $@
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               if [ $# -ne 1 ]; then
-                       __print_err "<response-code>" $@
-                       return 1
-               fi
-       else
-               if [ $# -lt 2 ]; then
-                       __print_err "<response-code> <ric-id>|NORIC [<schema-file>|NOFILE]*" $@
-                       return 1
-               fi
-       fi
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               query="/v2/policy-schemas"
-       else
-               query="/policy_schemas"
-               if [ $2 != "NORIC" ]; then
-                       query=$query"?ric="$2
-               fi
-       fi
-
-       res="$(__do_curl_to_api A1PMS GET $query)"
-       status=${res:${#res}-3}
-
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-
-       if [ $# -gt 2 ]; then
-               body=${res:0:${#res}-3}
-               targetJson="["
-
-               for file in ${@:3} ; do
-                       if [ "$targetJson" != "[" ]; then
-                               targetJson=$targetJson","
-                       fi
-                       if [ $file == "NOFILE" ]; then
-                               targetJson=$targetJson"{}"
-                       else
-                               targetJson=$targetJson$(< $file)
-                       fi
-               done
-
-               targetJson=$targetJson"]"
-               if [ "$A1PMS_VERSION" == "V2" ]; then
-                       targetJson="{\"policy_schemas\": $targetJson }"
-               fi
-               echo "TARGET JSON: $targetJson" >> $HTTPLOG
-               res=$(python3 ../common/compare_json.py "$targetJson" "$body")
-
-               if [ $res -ne 0 ]; then
-                       __log_test_fail_body
-                       return 1
-               fi
-       fi
-
-       __collect_endpoint_stats "A1PMS" 07 "GET" $A1PMS_API_PREFIX"/v2/policy-schemas" $status
-       __log_test_pass
-       return 0
+  __log_test_start $@
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    if [ $# -ne 1 ]; then
+      __print_err "<response-code>" $@
+      return 1
+    fi
+  else
+    if [ $# -lt 2 ]; then
+      __print_err "<response-code> <ric-id>|NORIC [<schema-file>|NOFILE]*" $@
+      return 1
+    fi
+  fi
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    query="/v2/policy-schemas"
+  else
+    query="/policy_schemas"
+    if [ $2 != "NORIC" ]; then
+      query=$query"?ric="$2
+    fi
+  fi
+
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  if [ $# -gt 2 ]; then
+    body=${res:0:${#res}-3}
+    targetJson="["
+
+    for file in ${@:3}; do
+      if [ "$targetJson" != "[" ]; then
+        targetJson=$targetJson","
+      fi
+      if [ $file == "NOFILE" ]; then
+        targetJson=$targetJson"{}"
+      else
+        targetJson=$targetJson$(<$file)
+      fi
+    done
+
+    targetJson=$targetJson"]"
+    if [ "$A1PMS_VERSION" == "V2" ]; then
+      targetJson="{\"policy_schemas\": $targetJson }"
+    fi
+    echo "TARGET JSON: $targetJson" >>$HTTPLOG
+    res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+
+    if [ $res -ne 0 ]; then
+      __log_test_fail_body
+      return 1
+    fi
+  fi
+
+  __collect_endpoint_stats "A1PMS" 07 "GET" $A1PMS_API_PREFIX"/v2/policy-schemas" $status
+  __log_test_pass
+  return 0
 }
 
 # API Test function: GET /policy_status and V2 GET /policies/{policy_id}/status
 # arg: <response-code> <policy-id> [ (STD|STD2 <enforce-status>|EMPTY [<reason>|EMPTY])|(OSC <instance-status> <has-been-deleted>) ]
 # (Function for test scripts)
 a1pms_api_get_policy_status() {
-       __log_test_start $@
-
-    if [ $# -lt 2 ] || [ $# -gt 5 ]; then
-               __print_err "<response-code> <policy-id> [(STD <enforce-status>|EMPTY [<reason>|EMPTY])|(OSC <instance-status> <has-been-deleted>)]" $@
-               return 1
-       fi
-
-       targetJson=""
-       if [ $# -eq 2 ]; then
-               :
-       elif [ "$3" == "STD" ]; then
-               targetJson="{\"enforceStatus\":\"$4\""
-               if [ $# -eq 5 ]; then
-                       targetJson=$targetJson",\"reason\":\"$5\""
-               fi
-               targetJson=$targetJson"}"
-       elif [ "$3" == "STD2" ]; then
-               if [ $4 == "EMPTY" ]; then
-                       targetJson="{\"enforceStatus\":\"\""
-               else
-                       targetJson="{\"enforceStatus\":\"$4\""
-               fi
-               if [ $# -eq 5 ]; then
-                       if [ $5 == "EMPTY" ]; then
-                               targetJson=$targetJson",\"enforceReason\":\"\""
-                       else
-                               targetJson=$targetJson",\"enforceReason\":\"$5\""
-                       fi
-               fi
-               targetJson=$targetJson"}"
-       elif [ "$3" == "OSC" ]; then
-               targetJson="{\"instance_status\":\"$4\""
-               if [ $# -eq 5 ]; then
-                       targetJson=$targetJson",\"has_been_deleted\":\"$5\""
-               fi
-               targetJson=$targetJson",\"created_at\":\"????\"}"
-       else
-               __print_err "<response-code> (STD <enforce-status> [<reason>])|(OSC <instance-status> <has-been-deleted>)" $@
-               return 1
-       fi
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               query="/v2/policies/$UUID$2/status"
-               targetJson="{\"last_modified\":\"????\",\"status\":$targetJson}"
-       else
-               query="/policy_status?id="$UUID$2
-       fi
-
-       res="$(__do_curl_to_api A1PMS GET $query)"
-    status=${res:${#res}-3}
-
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-       if [ $# -gt 2 ]; then
-               echo "TARGET JSON: $targetJson" >> $HTTPLOG
-               body=${res:0:${#res}-3}
-               res=$(python3 ../common/compare_json.py "$targetJson" "$body")
-
-               if [ $res -ne 0 ]; then
-                       __log_test_fail_body
-                       return 1
-               fi
-       fi
-       __collect_endpoint_stats "A1PMS" 08 "GET" $A1PMS_API_PREFIX"/v2/policies/{policy_id}/status" $status
-       __log_test_pass
-       return 0
+  __log_test_start $@
+
+  if [ $# -lt 2 ] || [ $# -gt 5 ]; then
+    __print_err "<response-code> <policy-id> [(STD <enforce-status>|EMPTY [<reason>|EMPTY])|(OSC <instance-status> <has-been-deleted>)]" $@
+    return 1
+  fi
+
+  targetJson=""
+  if [ $# -eq 2 ]; then
+    :
+  elif [ "$3" == "STD" ]; then
+    targetJson="{\"enforceStatus\":\"$4\""
+    if [ $# -eq 5 ]; then
+      targetJson=$targetJson",\"reason\":\"$5\""
+    fi
+    targetJson=$targetJson"}"
+  elif [ "$3" == "STD2" ]; then
+    if [ $4 == "EMPTY" ]; then
+      targetJson="{\"enforceStatus\":\"\""
+    else
+      targetJson="{\"enforceStatus\":\"$4\""
+    fi
+    if [ $# -eq 5 ]; then
+      if [ $5 == "EMPTY" ]; then
+        targetJson=$targetJson",\"enforceReason\":\"\""
+      else
+        targetJson=$targetJson",\"enforceReason\":\"$5\""
+      fi
+    fi
+    targetJson=$targetJson"}"
+  elif [ "$3" == "OSC" ]; then
+    if [[ $TEST_ENV_PROFILE =~ ^ORAN-[A-H] ]] || [[ $TEST_ENV_PROFILE =~ ^ONAP-[A-L] ]]; then
+      targetJson="{\"instance_status\":\"$4\""
+      if [ $# -eq 5 ]; then
+        targetJson=$targetJson",\"has_been_deleted\":\"$5\""
+      fi
+      targetJson=$targetJson",\"created_at\":\"????\"}"
+    else
+      targetJson="{\"enforceStatus\":\"$4\""
+      if [ $# -eq 5 ]; then
+        targetJson=$targetJson",\"enforceReason\":\"$5\"}"
+      fi
+    fi
+  else
+    __print_err "<response-code> (STD <enforce-status> [<reason>])|(OSC <instance-status> <has-been-deleted>)" $@
+    return 1
+  fi
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    query="/v2/policies/$UUID$2/status"
+    targetJson="{\"last_modified\":\"????\",\"status\":$targetJson}"
+  else
+    query="/policy_status?id="$UUID$2
+  fi
+
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+  if [ $# -gt 2 ]; then
+    echo "TARGET JSON: $targetJson" >>$HTTPLOG
+    body=${res:0:${#res}-3}
+    res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+
+    if [ $res -ne 0 ]; then
+      __log_test_fail_body
+      return 1
+    fi
+  fi
+  __collect_endpoint_stats "A1PMS" 08 "GET" $A1PMS_API_PREFIX"/v2/policies/{policy_id}/status" $status
+  __log_test_pass
+  return 0
 }
 
 # API Test function: GET /policy_types and V2 GET /v2/policy-types
 # args: <response-code> [<ric-id>|NORIC [<policy-type-id>|EMPTY [<policy-type-id>]*]]
 # (Function for test scripts)
 a1pms_api_get_policy_types() {
-       __log_test_start $@
-
-    if [ $# -lt 1 ]; then
-               __print_err "<response-code> [<ric-id>|NORIC [<policy-type-id>|EMPTY [<policy-type-id>]*]]" $@
-               return 1
-       fi
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               if [ $# -eq 1 ]; then
-                       query="/v2/policy-types"
-               elif [ $2 == "NORIC" ]; then
-                       query="/v2/policy-types"
-               else
-                       query="/v2/policy-types?ric_id=$2"
-               fi
-       else
-               if [ $# -eq 1 ]; then
-                       query="/policy_types"
-               elif [ $2 == "NORIC" ]; then
-                       query="/policy_types"
-               else
-                       query="/policy_types?ric=$2"
-               fi
-       fi
+  __log_test_start $@
+
+  if [ $# -lt 1 ]; then
+    __print_err "<response-code> [<ric-id>|NORIC [<policy-type-id>|EMPTY [<policy-type-id>]*]]" $@
+    return 1
+  fi
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    if [ $# -eq 1 ]; then
+      query="/v2/policy-types"
+    elif [ $2 == "NORIC" ]; then
+      query="/v2/policy-types"
+    else
+      query="/v2/policy-types?ric_id=$2"
+    fi
+  else
+    if [ $# -eq 1 ]; then
+      query="/policy_types"
+    elif [ $2 == "NORIC" ]; then
+      query="/policy_types"
+    else
+      query="/policy_types?ric=$2"
+    fi
+  fi
+
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  if [ $# -gt 2 ]; then
+    body=${res:0:${#res}-3}
+    targetJson="["
+
+    for pid in ${@:3}; do
+      if [ "$targetJson" != "[" ]; then
+        targetJson=$targetJson","
+      fi
+      if [ $pid == "EMPTY" ]; then
+        pid=""
+      fi
+      targetJson=$targetJson"\"$pid\""
+    done
+
+    targetJson=$targetJson"]"
+    if [ "$A1PMS_VERSION" == "V2" ]; then
+      targetJson="{\"policytype_ids\": $targetJson }"
+    fi
+    echo "TARGET JSON: $targetJson" >>$HTTPLOG
+    res=$(python3 ../common/compare_json.py "$targetJson" "$body")
 
-    res="$(__do_curl_to_api A1PMS GET $query)"
-    status=${res:${#res}-3}
+    if [ $res -ne 0 ]; then
+      __log_test_fail_body
+      return 1
+    fi
+  fi
+
+  __collect_endpoint_stats "A1PMS" 09 "GET" $A1PMS_API_PREFIX"/v2/policy-types" $status
+  __log_test_pass
+  return 0
+}
+
+# API Test function:  V3 GET a1policymanagement/v1/policytypes
+# args: <response-code> [<ric-id>|NORIC [<policy-type-id>|EMPTY [<policy-type-id>]*]]
+# (Function for test scripts)
+a1pms_api_get_policy_types_v3() {
+  __log_test_start $@
+
+  if [ $# -lt 1 ]; then
+    __print_err "<response-code> [<ric-id>|NORIC [<policy-type-id>|EMPTY [<policy-type-id>]*]]" $@
+    return 1
+  fi
+
+  if [ $# -eq 1 ]; then
+    query="/v1/policytypes"
+  elif [ $2 == "NORIC" ]; then
+    query="/v1/policytypes"
+  else
+    query="/v1/policytypes?nearRtRicId=$2"
+  fi
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  if [ $# -gt 2 ]; then
+    body=${res:0:${#res}-3}
+    targetJson="["
+
+    for pid in ${@:3}; do
+      if [ "$targetJson" != "[" ]; then
+        targetJson=$targetJson","
+      fi
+      IFS=':' read -r policy_type_id ric_id <<<"$pid"
+      #                        if [ -n "$policy_type_id" ] && [ -n "$ric_id" ]; then
+      if [ $policy_type_id == "EMPTY" ]; then
+        policy_type_id=""
+      fi
+      targetJson=$targetJson"{ \"policyTypeId\": \"$policy_type_id\", \"nearRtRicId\": \"$ric_id\" }"
+      #                        fi
+    done
+
+    targetJson=$targetJson"]"
+
+    echo "TARGET JSON: $targetJson" >>$HTTPLOG
+    res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+
+    if [ $res -ne 0 ]; then
+      __log_test_fail_body
+      return 1
+    fi
+  fi
 
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-
-       if [ $# -gt 2 ]; then
-               body=${res:0:${#res}-3}
-               targetJson="["
-
-               for pid in ${@:3} ; do
-                       if [ "$targetJson" != "[" ]; then
-                               targetJson=$targetJson","
-                       fi
-                       if [ $pid == "EMPTY" ]; then
-                               pid=""
-                       fi
-                       targetJson=$targetJson"\"$pid\""
-               done
-
-               targetJson=$targetJson"]"
-               if [ "$A1PMS_VERSION" == "V2" ]; then
-                       targetJson="{\"policytype_ids\": $targetJson }"
-               fi
-               echo "TARGET JSON: $targetJson" >> $HTTPLOG
-               res=$(python3 ../common/compare_json.py "$targetJson" "$body")
-
-               if [ $res -ne 0 ]; then
-                       __log_test_fail_body
-                       return 1
-               fi
-       fi
-
-       __collect_endpoint_stats "A1PMS" 09 "GET" $A1PMS_API_PREFIX"/v2/policy-types" $status
-       __log_test_pass
-       return 0
+  __collect_endpoint_stats "A1PMS" 09 "GET" ${A1PMS_API_PREFIX}${query} ${status}
+  __log_test_pass
+  return 0
 }
 
 #########################################################
 #### Test case functions Health check
 #########################################################
 
-# API Test function: GET /status and V2 GET /status
+# API Test function: GET /status and V2 GET /status or (v1/status for a1pmsV3)
 # args: <response-code>
 # (Function for test scripts)
 a1pms_api_get_status() {
-       __log_test_start $@
-    if [ $# -ne 1 ]; then
-               __print_err "<response-code>" $@
-               return 1
-       fi
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               query="/v2/status"
-       else
-               query="/status"
-       fi
-    res="$(__do_curl_to_api A1PMS GET $query)"
-    status=${res:${#res}-3}
-
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-
-       __collect_endpoint_stats "A1PMS" 10 "GET" $A1PMS_API_PREFIX"/v2/status" $status
-       __log_test_pass
-       return 0
+  __log_test_start $@
+  if [ $# -ne 1 ]; then
+    __print_err "<response-code>" $@
+    return 1
+  fi
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    query="/v2/status"
+  elif [ "$A1PMS_VERSION" == "V3" ]; then
+    query="/v1/status"
+  else
+    query="/status"
+  fi
+
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  __collect_endpoint_stats "A1PMS" 10 "GET" $A1PMS_API_PREFIX$query $status
+  __log_test_pass
+  return 0
 }
 
 # API Test function: GET /status (root) without api prefix
 # args: <response-code>
 # (Function for test scripts)
 a1pms_api_get_status_root() {
-       __log_test_start $@
-    if [ $# -ne 1 ]; then
-               __print_err "<response-code>" $@
-               return 1
-       fi
-       query="/status"
-       TMP_PREFIX=$A1PMS_API_PREFIX
-       A1PMS_API_PREFIX=""
-    res="$(__do_curl_to_api A1PMS GET $query)"
-       A1PMS_API_PREFIX=$TMP_PREFIX
-    status=${res:${#res}-3}
-
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-
-       __collect_endpoint_stats "A1PMS" 19 "GET" "/status" $status
-       __log_test_pass
-       return 0
+  __log_test_start $@
+  if [ $# -ne 1 ]; then
+    __print_err "<response-code>" $@
+    return 1
+  fi
+  query="/status"
+  TMP_PREFIX=$A1PMS_API_PREFIX
+  A1PMS_API_PREFIX=""
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  A1PMS_API_PREFIX=$TMP_PREFIX
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  __collect_endpoint_stats "A1PMS" 19 "GET" "/status" $status
+  __log_test_pass
+  return 0
 }
 
 #########################################################
 #### Test case functions RIC Repository
 #########################################################
 
-# API Test function: GET /ric and V2 GET /v2/rics/ric
+# API Test function: GET /ric, V2 GET /v2/rics/ric, and V3 GET a1policymanagement/v1/rics/ric
 # args: <reponse-code> <management-element-id> [<ric-id>]
 # (V2) args: <reponse-code> <management-element-id>|NOME <ric-id>|<NORIC> [<string-of-ricinfo>]
 # (V2) example of <string-of-ricinfo> = "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:1,2,4"
 # (V2) format of ric-info:  <ric-id>:<list-of-mes>:<list-of-policy-type-ids>
 
-
 # (Function for test scripts)
 a1pms_api_get_ric() {
-       __log_test_start $@
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               if [ $# -lt 3 ]; then
-                       __print_err "<reponse-code> <management-element-id>|NOME <ric-id>|<NORIC> [string-of-ricinfo>]" $@
-                       return 1
-               fi
-               search=""
-               if [ $2 != "NOME" ]; then
-                       search="?managed_element_id="$2
-               fi
-               if [ $3 != "NORIC" ]; then
-                       if [ -z $search ]; then
-                               search="?ric_id="$3
-                       else
-                               search=$search"&ric_id="$3
-                       fi
-               fi
-               query="/v2/rics/ric"$search
-
-               res="$(__do_curl_to_api A1PMS GET $query)"
-               status=${res:${#res}-3}
-
-               if [ $status -ne $1 ]; then
-                       __log_test_fail_status_code $1 $status
-                       return 1
-               fi
-
-               if [ $# -gt 3 ]; then
-                       body=${res:0:${#res}-3}
-                       res=$(python3 ../common/create_rics_json.py "./tmp/.tmp_rics.json" "V2" "$4" )
-                       if [ $res -ne 0 ]; then
-                               __log_test_fail_general "Could not create target ric info json"
-                               return 1
-                       fi
-
-                       targetJson=$(<./tmp/.tmp_rics.json)
-                       targetJson=${targetJson:1:${#targetJson}-2} #remove array brackets
-                       echo " TARGET JSON: $targetJson" >> $HTTPLOG
-                       res=$(python3 ../common/compare_json.py "$targetJson" "$body")
-                       if [ $res -ne 0 ]; then
-                               __log_test_fail_body
-                               return 1
-                       fi
-               fi
-       else
-               if [ $# -lt 2 ] || [ $# -gt 3 ]; then
-                       __print_err "<reponse-code> <management-element-id> [<ric-id>]" $@
-                       return 1
-               fi
-
-               query="/ric?managedElementId="$2
-
-               res="$(__do_curl_to_api A1PMS GET $query)"
-               status=${res:${#res}-3}
-
-               if [ $status -ne $1 ]; then
-                       __log_test_fail_status_code $1 $status
-                       return 1
-               fi
-
-               if [ $# -eq 3 ]; then
-                       body=${res:0:${#res}-3}
-                       if [ "$body" != "$3" ]; then
-                               __log_test_fail_body
-                               return 1
-                       fi
-               fi
-       fi
-
-       __collect_endpoint_stats "A1PMS" 11 "GET" $A1PMS_API_PREFIX"/v2/rics/ric" $status
-       __log_test_pass
-       return 0
+  __log_test_start $@
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    if [ $# -lt 3 ]; then
+      __print_err "<reponse-code> <management-element-id>|NOME <ric-id>|<NORIC> [string-of-ricinfo>]" $@
+      return 1
+    fi
+    search=""
+    if [ $2 != "NOME" ]; then
+      search="?managed_element_id="$2
+    fi
+    if [ $3 != "NORIC" ]; then
+      if [ -z $search ]; then
+        search="?ric_id="$3
+      else
+        search=$search"&ric_id="$3
+      fi
+    fi
+    query="/v2/rics/ric"$search
+
+    res="$(__do_curl_to_api A1PMS GET $query)"
+    status=${res:${#res}-3}
+
+    if [ $status -ne $1 ]; then
+      __log_test_fail_status_code $1 $status
+      return 1
+    fi
+
+    if [ $# -gt 3 ]; then
+      body=${res:0:${#res}-3}
+      res=$(python3 ../common/create_rics_json.py "./tmp/.tmp_rics.json" "V2" "$4")
+      if [ $res -ne 0 ]; then
+        __log_test_fail_general "Could not create target ric info json"
+        return 1
+      fi
+
+      targetJson=$(<./tmp/.tmp_rics.json)
+      targetJson=${targetJson:1:${#targetJson}-2} #remove array brackets
+      echo " TARGET JSON: $targetJson" >>$HTTPLOG
+      res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+      if [ $res -ne 0 ]; then
+        __log_test_fail_body
+        return 1
+      fi
+    fi
+  elif [ "$A1PMS_VERSION" == "V3" ]; then
+    if [ $# -lt 3 ]; then
+      __print_err "<reponseCode> <managementElementId>|NOME <ricId>|<NORIC> [stringOfRicInfo>]" $@
+      return 1
+    fi
+    search=""
+    if [ $2 != "NOME" ]; then
+      search="?managedElementId="$2
+    fi
+    if [ $3 != "NORIC" ]; then
+      if [ -z $search ]; then
+        search="?ricId="$3
+      else
+        search=$search"&ricId="$3
+      fi
+    fi
+    query="/v1/rics/ric"$search
+
+    res="$(__do_curl_to_api A1PMS GET $query)"
+    status=${res:${#res}-3}
+
+    if [ $status -ne $1 ]; then
+      __log_test_fail_status_code $1 $status
+      return 1
+    fi
+
+    if [ $# -gt 3 ]; then
+      body=${res:0:${#res}-3}
+      res=$(python3 ../common/create_rics_json.py "./tmp/.tmp_rics.json" "${A1PMS_VERSION}" "$4")
+      if [ $res -ne 0 ]; then
+        __log_test_fail_general "Could not create target ric info json"
+        return 1
+      fi
+
+      targetJson=$(<./tmp/.tmp_rics.json)
+      targetJson=${targetJson:1:${#targetJson}-2} #remove array brackets
+      echo " TARGET JSON: $targetJson" >>$HTTPLOG
+      res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+      if [ $res -ne 0 ]; then
+        __log_test_fail_body
+        return 1
+      fi
+    fi
+  else
+    if [ $# -lt 2 ] || [ $# -gt 3 ]; then
+      __print_err "<reponseCode> <managedElementIds> [<ricId>]" $@
+      return 1
+    fi
+
+    query="/ric?managedElementId="$2
+
+    res="$(__do_curl_to_api A1PMS GET $query)"
+    status=${res:${#res}-3}
+
+    if [ $status -ne $1 ]; then
+      __log_test_fail_status_code $1 $status
+      return 1
+    fi
+
+    if [ $# -eq 3 ]; then
+      body=${res:0:${#res}-3}
+      if [ "$body" != "$3" ]; then
+        __log_test_fail_body
+        return 1
+      fi
+    fi
+  fi
+
+  __collect_endpoint_stats "A1PMS" 11 "GET" ${A1PMS_API_PREFIX}${query} ${status}
+  __log_test_pass
+  return 0
 }
 
-# API test function: GET /rics and V2 GET /v2/rics
+# API test function: GET /rics, V2 GET /v2/rics, and V3 GET /a1policymanagement/v1/rics
 # args: <reponse-code> <policy-type-id>|NOTYPE [<space-separate-string-of-ricinfo>]
 # example of <space-separate-string-of-ricinfo> = "ricsim_g1_1:me1_ricsim_g1_1,me2_ricsim_g1_1:1,2,4 ricsim_g1_1:me2_........."
 # format of ric-info:  <ric-id>:<list-of-mes>:<list-of-policy-type-ids>
 # (Function for test scripts)
 a1pms_api_get_rics() {
-       __log_test_start $@
+  __log_test_start $@
 
-    if [ $# -lt 2 ]; then
-               __print_err "<reponse-code> <policy-type-id>|NOTYPE [<space-separate-string-of-ricinfo>]" $@
-               return 1
-       fi
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               query="/v2/rics"
-               if [ $2 != "NOTYPE" ]; then
-                       query="/v2/rics?policytype_id="$2
-               fi
-       else
-               query="/rics"
-               if [ $2 != "NOTYPE" ]; then
-                       query="/rics?policyType="$2
-               fi
-       fi
+  if [ $# -lt 2 ]; then
+    __print_err "<reponse-code> <policy-type-id>|NOTYPE [<space-separate-string-of-ricinfo>]" $@
+    return 1
+  fi
 
-    res="$(__do_curl_to_api A1PMS GET $query)"
-    status=${res:${#res}-3}
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    query="/v2/rics"
+    if [ $2 != "NOTYPE" ]; then
+      query="/v2/rics?policytype_id="$2
+    fi
+  elif [ "$A1PMS_VERSION" == "V3" ]; then
+    query="/v1/rics"
+    if [ $2 != "NOTYPE" ]; then
+      query=${query}"?policyTypeId="$2
+    fi
+  else
+    query="/rics"
+    if [ $2 != "NOTYPE" ]; then
+      query="/rics?policyType="$2
+    fi
+  fi
+
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  if [ $# -gt 2 ]; then
+    body=${res:0:${#res}-3}
+    res=$(python3 ../common/create_rics_json.py "./tmp/.tmp_rics.json" "${A1PMS_VERSION}" "$3")
+    if [ $res -ne 0 ]; then
+      __log_test_fail_general "Could not create target ric info json"
+      return 1
+    fi
 
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-
-       if [ $# -gt 2 ]; then
-               body=${res:0:${#res}-3}
-               if [ "$A1PMS_VERSION" == "V2" ]; then
-                       res=$(python3 ../common/create_rics_json.py "./tmp/.tmp_rics.json" "V2" "$3" )
-               else
-                       res=$(python3 ../common/create_rics_json.py "./tmp/.tmp_rics.json" "V1" "$3" )
-               fi
-               if [ $res -ne 0 ]; then
-                       __log_test_fail_general "Could not create target ric info json"
-                       return 1
-               fi
-
-               targetJson=$(<./tmp/.tmp_rics.json)
-               if [ "$A1PMS_VERSION" == "V2" ]; then
-                       targetJson="{\"rics\": $targetJson }"
-               fi
-       echo "TARGET JSON: $targetJson" >> $HTTPLOG
-               res=$(python3 ../common/compare_json.py "$targetJson" "$body")
-               if [ $res -ne 0 ]; then
-                       __log_test_fail_body
-                       return 1
-               fi
-       fi
-
-       __collect_endpoint_stats "A1PMS" 12 "GET" $A1PMS_API_PREFIX"/v2/rics" $status
-       __log_test_pass
-       return 0
+    targetJson=$(<./tmp/.tmp_rics.json)
+    if [ "$A1PMS_VERSION" == "V2" ] || [ "$A1PMS_VERSION" == "V3" ]; then
+      targetJson="{\"rics\": $targetJson }"
+    fi
+    echo "TARGET JSON: $targetJson" >>$HTTPLOG
+    res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+    if [ $res -ne 0 ]; then
+      __log_test_fail_body
+      return 1
+    fi
+  fi
+
+  __collect_endpoint_stats "A1PMS" 12 "GET" ${A1PMS_API_PREFIX}${query} ${status}
+  __log_test_pass
+  return 0
 }
 
 ##################################################################
 #### API Test case functions Service registry and supervision ####
 ##################################################################
 
-# API test function: PUT /service and V2 PUT /service
+# API test function: PUT /service, V2 PUT /service and V3 PUT a1policymanagement/v1/services
 # args: <response-code>  <service-name> <keepalive-timeout> <callbackurl>
 # (Function for test scripts)
 a1pms_api_put_service() {
-       __log_test_start $@
-    if [ $# -ne 4 ]; then
-        __print_err "<response-code>  <service-name> <keepalive-timeout> <callbackurl>" $@
-        return 1
-    fi
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               query="/v2/services"
-               json="{\"callback_url\": \""$4"\",\"keep_alive_interval_seconds\": \""$3"\",\"service_id\": \""$2"\"}"
-       else
-               query="/service"
-               json="{\"callbackUrl\": \""$4"\",\"keepAliveIntervalSeconds\": \""$3"\",\"serviceName\": \""$2"\"}"
-       fi
-    file="./tmp/.tmp.json"
-       echo "$json" > $file
-
-    res="$(__do_curl_to_api A1PMS PUT $query $file)"
-    status=${res:${#res}-3}
-
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-
-       __collect_endpoint_stats "A1PMS" 13 "PUT" $A1PMS_API_PREFIX"/v2/service" $status
-       __log_test_pass
-       return 0
+  __log_test_start $@
+  if [ $# -ne 4 ]; then
+    __print_err "<response-code>  <service-name> <keepalive-timeout> <callbackurl>" $@
+    return 1
+  fi
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    query="/v2/services"
+    json="{\"callback_url\": \""$4"\",\"keep_alive_interval_seconds\": \""$3"\",\"service_id\": \""$2"\"}"
+  elif [ "$A1PMS_VERSION" == "V3" ]; then
+    query="/v1/services"
+    json="{\"callbackUrl\": \""$4"\",\"keepAliveIntervalSeconds\": \""$3"\",\"serviceId\": \""$2"\"}"
+  else
+    query="/service"
+    json="{\"callbackUrl\": \""$4"\",\"keepAliveIntervalSeconds\": \""$3"\",\"serviceName\": \""$2"\"}"
+  fi
+  file="./tmp/.tmp.json"
+  echo "$json" >$file
+
+  res="$(__do_curl_to_api A1PMS PUT $query $file)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  __collect_endpoint_stats "A1PMS" 13 "PUT" $A1PMS_API_PREFIX$query $status
+  __log_test_pass
+  return 0
 }
 
-# API test function: GET /services and V2 GET /v2/services
+# API test function: GET /services, V2 GET /v2/services and V3 /a1policymanagement/v1/services
 #args: <response-code> [ (<query-service-name> <target-service-name> <keepalive-timeout> <callbackurl>) | (NOSERVICE <target-service-name> <keepalive-timeout> <callbackurl> [<target-service-name> <keepalive-timeout> <callbackurl>]* )]
 # (Function for test scripts)
 a1pms_api_get_services() {
-       __log_test_start $@
-       #Number of accepted parameters: 1, 2, 4, 7, 10, 13,...
-       paramError=1
-       if [ $# -eq 1 ]; then
-               paramError=0
-       elif [ $# -eq 2 ] && [ $2 != "NOSERVICE" ]; then
-               paramError=0
-       elif [ $# -eq 5 ]; then
-               paramError=0
-       elif [ $# -gt 5 ] && [ $2 == "NOSERVICE" ]; then
-               argLen=$(($#-2))
-               if [ $(($argLen%3)) -eq 0 ]; then
-                       paramError=0
-               fi
-       fi
+  __log_test_start $@
+  #Number of accepted parameters: 1, 2, 4, 7, 10, 13,...
+  paramError=1
+  if [ $# -eq 1 ]; then
+    paramError=0
+  elif [ $# -eq 2 ] && [ $2 != "NOSERVICE" ]; then
+    paramError=0
+  elif [ $# -eq 5 ]; then
+    paramError=0
+  elif [ $# -gt 5 ] && [ $2 == "NOSERVICE" ]; then
+    argLen=$(($# - 2))
+    if [ $(($argLen % 3)) -eq 0 ]; then
+      paramError=0
+    fi
+  fi
 
-    if [ $paramError -ne 0 ]; then
-               __print_err "<response-code> [ (<query-service-name> <target-service-name> <keepalive-timeout> <callbackurl>) | (NOSERVICE <target-service-name> <keepalive-timeout> <callbackurl> [<target-service-name> <keepalive-timeout> <callbackurl>]* )]" $@
-               return 1
-       fi
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               query="/v2/services"
-
-               if [ $# -gt 1 ] && [ $2 != "NOSERVICE" ]; then
-                       query="/v2/services?service_id="$2
-               fi
-       else
-               query="/services"
-
-               if [ $# -gt 1 ] && [ $2 != "NOSERVICE" ]; then
-                       query="/services?name="$2
-               fi
-       fi
-    res="$(__do_curl_to_api A1PMS GET $query)"
-    status=${res:${#res}-3}
+  if [ $paramError -ne 0 ]; then
+    __print_err "<response-code> [ (<query-service-name> <target-service-name> <keepalive-timeout> <callbackurl>) | (NOSERVICE <target-service-name> <keepalive-timeout> <callbackurl> [<target-service-name> <keepalive-timeout> <callbackurl>]* )]" $@
+    return 1
+  fi
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    query="/v2/services"
+    if [ $# -gt 1 ] && [ $2 != "NOSERVICE" ]; then
+      query="/v2/services?service_id="$2
+    fi
+  elif [ "$A1PMS_VERSION" == "V3" ]; then
+    query="/v1/services"
+    if [ $# -gt 1 ] && [ $2 != "NOSERVICE" ]; then
+      query="/v1/services?serviceId="$2
+    fi
+  else
+    query="/services"
+
+    if [ $# -gt 1 ] && [ $2 != "NOSERVICE" ]; then
+      query="/services?name="$2
+    fi
+  fi
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  if [ $# -gt 2 ]; then
+    variableArgCount=$(($# - 2))
+    body=${res:0:${#res}-3}
+    targetJson="["
+    shift
+    shift
+    cntr=0
+    while [ $cntr -lt $variableArgCount ]; do
+      servicename=$1
+      shift
+      timeout=$1
+      shift
+      callback=$1
+      shift
+      if [ $cntr -gt 0 ]; then
+        targetJson=$targetJson","
+      fi
+      # timeSinceLastActivitySeconds value cannot be checked since value varies
+      if [ "$A1PMS_VERSION" == "V2" ]; then
+        targetJson=$targetJson"{\"service_id\": \""$servicename"\",\"keep_alive_interval_seconds\": "$timeout",\"time_since_last_activity_seconds\":\"????\",\"callback_url\": \""$callback"\"}"
+      elif [ "$A1PMS_VERSION" == "V3" ]; then
+        targetJson=$targetJson"{\"serviceId\": \""$servicename"\",\"keepAliveIntervalSeconds\": "$timeout",\"timeSinceLastActivitySeconds\":\"????\",\"callbackUrl\": \""$callback"\"}"
+      else
+        targetJson=$targetJson"{\"serviceName\": \""$servicename"\",\"keepAliveIntervalSeconds\": "$timeout",\"timeSinceLastActivitySeconds\":\"????\",\"callbackUrl\": \""$callback"\"}"
+      fi
+      let cntr=cntr+3
+    done
+    targetJson=$targetJson"]"
+    if [ "$A1PMS_VERSION" == "V2" ]; then
+      targetJson="{\"service_list\": $targetJson }"
+      URL_for_Collect_End_Point="/v2/services"
+    elif [ "$A1PMS_VERSION" == "V3" ]; then
+      targetJson="{\"serviceList\": $targetJson }"
+      URL_for_Collect_End_Point="/v1/services"
+    fi
+    echo "TARGET JSON: $targetJson" >>$HTTPLOG
+    res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+    if [ $res -ne 0 ]; then
+      __log_test_fail_body
+      return 1
+    fi
+  fi
 
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-
-       if [ $# -gt 2 ]; then
-               variableArgCount=$(($#-2))
-               body=${res:0:${#res}-3}
-       targetJson="["
-               shift; shift;
-               cntr=0
-               while [ $cntr -lt $variableArgCount ]; do
-                       servicename=$1; shift;
-                       timeout=$1; shift;
-                       callback=$1; shift;
-                       if [ $cntr -gt 0 ]; then
-                               targetJson=$targetJson","
-                       fi
-                       # timeSinceLastActivitySeconds value cannot be checked since value varies
-                       if [ "$A1PMS_VERSION" == "V2" ]; then
-                               targetJson=$targetJson"{\"service_id\": \""$servicename"\",\"keep_alive_interval_seconds\": "$timeout",\"time_since_last_activity_seconds\":\"????\",\"callback_url\": \""$callback"\"}"
-                       else
-                               targetJson=$targetJson"{\"serviceName\": \""$servicename"\",\"keepAliveIntervalSeconds\": "$timeout",\"timeSinceLastActivitySeconds\":\"????\",\"callbackUrl\": \""$callback"\"}"
-                       fi
-                       let cntr=cntr+3
-               done
-               targetJson=$targetJson"]"
-               if [ "$A1PMS_VERSION" == "V2" ]; then
-                       targetJson="{\"service_list\": $targetJson }"
-               fi
-               echo "TARGET JSON: $targetJson" >> $HTTPLOG
-               res=$(python3 ../common/compare_json.py "$targetJson" "$body")
-               if [ $res -ne 0 ]; then
-                       __log_test_fail_body
-                       return 1
-               fi
-       fi
-
-       __collect_endpoint_stats "A1PMS" 14 "GET" $A1PMS_API_PREFIX"/v2/services" $status
-       __log_test_pass
-       return 0
+  __collect_endpoint_stats "A1PMS" 14 "GET" $A1PMS_API_PREFIX$URL_for_Collect_End_Point $status
+  __log_test_pass
+  return 0
 }
 
-# API test function: GET /services V2 GET /v2/services -  (only checking service names)
+# API test function: GET /services, V2 GET /v2/services and V3 /a1policymanagement/v1/services -  (only checking service names)
 # args: <response-code> [<service-name>]*"
 # (Function for test scripts)
 a1pms_api_get_service_ids() {
-       __log_test_start $@
-
-    if [ $# -lt 1 ]; then
-               __print_err "<response-code> [<service-name>]*" $@
-               return 1
-       fi
-
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-           query="/v2/services"
-       else
-       query="/services"
-       fi
-    res="$(__do_curl_to_api A1PMS GET $query)"
-    status=${res:${#res}-3}
-
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-
-       body=${res:0:${#res}-3}
-       targetJson="["
-       for rapp in ${@:2} ; do
-               if [ "$targetJson" != "[" ]; then
-                       targetJson=$targetJson","
-               fi
-               if [ "$A1PMS_VERSION" == "V2" ]; then
-                       targetJson=$targetJson"{\"callback_url\":\"????\",\"keep_alive_interval_seconds\":\"????\",\"service_id\":\""$rapp"\",\"time_since_last_activity_seconds\":\"????\"}"
-               else
-                       targetJson=$targetJson"{\"callbackUrl\":\"????\",\"keepAliveIntervalSeconds\":\"????\",\"serviceName\":\""$rapp"\",\"timeSinceLastActivitySeconds\":\"????\"}"
-               fi
-       done
-
-       targetJson=$targetJson"]"
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               targetJson="{\"service_list\": $targetJson }"
-       fi
-       echo "TARGET JSON: $targetJson" >> $HTTPLOG
-       res=$(python3 ../common/compare_json.py "$targetJson" "$body")
-
-       if [ $res -ne 0 ]; then
-               __log_test_fail_body
-               return 1
-       fi
-
-       __collect_endpoint_stats "A1PMS" 14 "GET" $A1PMS_API_PREFIX"/v2/services" $status
-       __log_test_pass
-       return 0
+  __log_test_start $@
+
+  if [ $# -lt 1 ]; then
+    __print_err "<response-code> [<service-name>]*" $@
+    return 1
+  fi
+
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    query="/v2/services"
+  elif [ "$A1PMS_VERSION" == "V3" ]; then
+    query="/v1/services"
+  else
+    query="/services"
+  fi
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  body=${res:0:${#res}-3}
+  targetJson="["
+  for rapp in ${@:2}; do
+    if [ "$targetJson" != "[" ]; then
+      targetJson=$targetJson","
+    fi
+    if [ "$A1PMS_VERSION" == "V2" ]; then
+      targetJson=$targetJson"{\"callback_url\":\"????\",\"keep_alive_interval_seconds\":\"????\",\"service_id\":\""$rapp"\",\"time_since_last_activity_seconds\":\"????\"}"
+    elif [ "$A1PMS_VERSION" == "V3" ]; then
+      targetJson=$targetJson"{\"callbackUrl\":\"????\",\"keepAliveIntervalSeconds\":\"????\",\"serviceId\":\""$rapp"\",\"timeSinceLastActivitySeconds\":\"????\"}"
+    else
+      targetJson=$targetJson"{\"callbackUrl\":\"????\",\"keepAliveIntervalSeconds\":\"????\",\"serviceName\":\""$rapp"\",\"timeSinceLastActivitySeconds\":\"????\"}"
+    fi
+  done
+
+  targetJson=$targetJson"]"
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    targetJson="{\"service_list\": $targetJson }"
+    URL_for_Collect_End_Point="/v2/services"
+  elif [ "$A1PMS_VERSION" == "V3" ]; then
+    targetJson="{\"serviceList\": $targetJson }"
+    URL_for_Collect_End_Point="/v1/services"
+  fi
+  echo "TARGET JSON: $targetJson" >>$HTTPLOG
+  res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+
+  if [ $res -ne 0 ]; then
+    __log_test_fail_body
+    return 1
+  fi
+
+  __collect_endpoint_stats "A1PMS" 14 "GET" $A1PMS_API_PREFIX$URL_for_Collect_End_Point $status
+  __log_test_pass
+  return 0
 }
 
-# API test function: DELETE /services and V2 DELETE /v2/services/{serviceId}
+# API test function: DELETE /services, V2 DELETE /v2/services/{serviceId} and V3 DELETE a1policymanagement/v1/services/{serviceId}
 # args: <response-code> <service-name>
 # (Function for test scripts)
 a1pms_api_delete_services() {
-       __log_test_start $@
-
-    if [ $# -ne 2 ]; then
-               __print_err "<response-code> <service-name>" $@
-               return 1
-       fi
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               query="/v2/services/"$2
-       else
-               query="/services?name="$2
-       fi
-    res="$(__do_curl_to_api A1PMS DELETE $query)"
-    status=${res:${#res}-3}
-
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-
-       __collect_endpoint_stats "A1PMS" 15 "DELETE" $A1PMS_API_PREFIX"/v2/services/{serviceId}" $status
-       __log_test_pass
-       return 0
+  __log_test_start $@
+
+  if [ $# -ne 2 ]; then
+    __print_err "<response-code> <service-name>" $@
+    return 1
+  fi
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    url_part="/v2/services/"
+    query=${url_part}${2}
+  elif [ "$A1PMS_VERSION" == "V3" ]; then
+    url_part="/v1/services/"
+    query=${url_part}${2}
+  else
+    query="/services?name="$2
+  fi
+  res="$(__do_curl_to_api A1PMS DELETE $query)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  __collect_endpoint_stats "A1PMS" 15 "DELETE" ${A1PMS_API_PREFIX}${url_part}"{serviceId}" $status
+  __log_test_pass
+  return 0
 }
 
-# API test function: PUT /services/keepalive and V2 PUT /v2/services/{service_id}/keepalive
+# API test function: PUT /services/keepalive, V2 PUT /v2/services/{service_id}/keepalive and V3 DELETE a1policymanagement/v1/services/{serviceId}
 # args: <response-code> <service-name>
 # (Function for test scripts)
 a1pms_api_put_services_keepalive() {
-       __log_test_start $@
-
-    if [ $# -ne 2 ]; then
-               __print_err "<response-code> <service-name>" $@
-               return 1
-       fi
-       if [ "$A1PMS_VERSION" == "V2" ]; then
-               query="/v2/services/$2/keepalive"
-       else
-       query="/services/keepalive?name="$2
-       fi
-
-    res="$(__do_curl_to_api A1PMS PUT $query)"
-    status=${res:${#res}-3}
-
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-
-       __collect_endpoint_stats "A1PMS" 16 "PUT" $A1PMS_API_PREFIX"/v2/services/{service_id}/keepalive" $status
-       __log_test_pass
-       return 0
+  __log_test_start $@
+
+  if [ $# -ne 2 ]; then
+    __print_err "<response-code> <service-name>" $@
+    return 1
+  fi
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    query="/v2/services/$2/keepalive"
+  elif [ "$A1PMS_VERSION" == "V3" ]; then
+    query="/v1/services/$2/keepalive"
+  else
+    query="/services/keepalive?name="$2
+  fi
+
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    empty_json_body={}
+    res="$(__do_curl_to_api A1PMS PUT ${query} ${empty_json_body})"
+  else
+    res="$(__do_curl_to_api A1PMS PUT ${query})"
+  fi
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code ${1} ${status}
+    return 1
+  fi
+
+  __collect_endpoint_stats "A1PMS" 16 "PUT" ${A1PMS_API_PREFIX}${query} ${status}
+  __log_test_pass
+  return 0
 }
 
 ##################################################################
 #### API Test case functions Configuration                    ####
 ##################################################################
 
-# API Test function: PUT /v2/configuration
+# API Test function: PUT "/v2/configuration" or V3 PUT "a1policymanagement/v1/configuration"
 # args: <response-code> <config-file>
 # (Function for test scripts)
 a1pms_api_put_configuration() {
-       __log_test_start $@
-
-       if [ "$A1PMS_VERSION" != "V2" ]; then
-               __log_test_fail_not_supported
-               return 1
-       fi
-
-    if [ $# -ne 2 ]; then
-        __print_err "<response-code> <config-file>" $@
-        return 1
-    fi
-       if [ ! -f $2 ]; then
-               __log_test_fail_general "Config file "$2", does not exist"
-               return 1
-       fi
-       inputJson=$(< $2)
-       # if [ $RUNMODE == "DOCKER" ]; then  #In kube the file already has a header
-       #       inputJson="{\"config\":"$inputJson"}"
-       # fi
-       file="./tmp/.config.json"
-       echo $inputJson > $file
-       query="/v2/configuration"
-       res="$(__do_curl_to_api A1PMS PUT $query $file)"
-       status=${res:${#res}-3}
-
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-
-       __collect_endpoint_stats "A1PMS" 17 "PUT" $A1PMS_API_PREFIX"/v2/configuration" $status
-       __log_test_pass
-       return 0
+  __log_test_start $@
+
+  if [ "$A1PMS_VERSION" != "V2" ] && [ "$A1PMS_VERSION" != "V3" ]; then
+    __log_test_fail_not_supported
+    return 1
+  fi
+
+  if [ $# -ne 2 ]; then
+    __print_err "<response-code> <config-file>" $@
+    return 1
+  fi
+  if [ ! -f $2 ]; then
+    __log_test_fail_general "Config file "$2", does not exist"
+    return 1
+  fi
+  inputJson=$(<$2)
+  # if [ $RUNMODE == "DOCKER" ]; then  #In kube the file already has a header
+  #    inputJson="{\"config\":"$inputJson"}"
+  # fi
+  file="./tmp/.config.json"
+  echo $inputJson >$file
+  if [ "$A1PMS_VERSION" == "V2" ]; then
+    query="/v2/configuration"
+  elif [ "$A1PMS_VERSION" == "V3" ]; then
+    #V3 has baseurl changes 'a1-policy/v2' to 'a1policymanagement/v1'
+    query="/v1/configuration"
+  fi
+  res="$(__do_curl_to_api A1PMS PUT $query $file)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  __collect_endpoint_stats "A1PMS" 17 "PUT" $A1PMS_API_PREFIX$query $status
+  __log_test_pass
+  return 0
 }
 
-# API Test function: GET /v2/configuration
+# API Test function: GET /v2/configuration and V3 GET a1policymanagement/v1/configuration
 # args: <response-code> [<config-file>]
 # (Function for test scripts)
 a1pms_api_get_configuration() {
-       __log_test_start $@
-
-       if [ "$A1PMS_VERSION" != "V2" ]; then
-               __log_test_fail_not_supported
-               return 1
-       fi
-
-    if [ $# -lt 1 ] || [ $# -gt 2 ]; then
-        __print_err "<response-code> [<config-file>]" $@
-        return 1
+  __log_test_start $@
+
+  if [ "$A1PMS_VERSION" != "V2" ] && [ "$A1PMS_VERSION" != "V3" ]; then
+    __log_test_fail_not_supported
+    return 1
+  fi
+
+  if [ $# -lt 1 ] || [ $# -gt 2 ]; then
+    __print_err "<response-code> [<config-file>]" $@
+    return 1
+  fi
+  if [ ! -f $2 ]; then
+    __log_test_fail_general "Config file "$2" for comparison, does not exist"
+    return 1
+  fi
+
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    #The V3 of a1-pms URL is a1policymanagement/v1 and the v2 is a1-policy/v2
+    query="/v1/configuration"
+  else
+    query="/v2/configuration"
+  fi
+  res="$(__do_curl_to_api A1PMS GET $query)"
+  status=${res:${#res}-3}
+
+  if [ $status -ne $1 ]; then
+    __log_test_fail_status_code $1 $status
+    return 1
+  fi
+
+  if [ $# -eq 2 ]; then
+
+    body=${res:0:${#res}-3}
+
+    targetJson=$(<$2)
+    # if [ $RUNMODE == "DOCKER" ]; then  #In kube the file already has a header
+    #  inputJson="{\"config\":"$inputJson"}"
+    # fi
+    echo "TARGET JSON: $targetJson" >>$HTTPLOG
+    res=$(python3 ../common/compare_json.py "$targetJson" "$body")
+
+    if [ $res -ne 0 ]; then
+      __log_test_fail_body
+      return 1
     fi
-       if [ ! -f $2 ]; then
-               __log_test_fail_general "Config file "$2" for comparison, does not exist"
-               return 1
-       fi
-
-       query="/v2/configuration"
-       res="$(__do_curl_to_api A1PMS GET $query)"
-       status=${res:${#res}-3}
-
-       if [ $status -ne $1 ]; then
-               __log_test_fail_status_code $1 $status
-               return 1
-       fi
-
-       if [ $# -eq 2 ]; then
-
-               body=${res:0:${#res}-3}
-
-               targetJson=$(< $2)
-               # if [ $RUNMODE == "DOCKER" ]; then  #In kube the file already has a header
-               #       inputJson="{\"config\":"$inputJson"}"
-               # fi
-               echo "TARGET JSON: $targetJson" >> $HTTPLOG
-               res=$(python3 ../common/compare_json.py "$targetJson" "$body")
-
-               if [ $res -ne 0 ]; then
-                       __log_test_fail_body
-                       return 1
-               fi
-       fi
-
-       __collect_endpoint_stats "A1PMS" 18 "GET" $A1PMS_API_PREFIX"/v2/configuration" $status
-       __log_test_pass
-       return 0
+  fi
+
+  if [ "$A1PMS_VERSION" == "V3" ]; then
+    __collect_endpoint_stats "A1PMS" 18 "GET" $A1PMS_API_PREFIX"/v1/configuration" $status
+  else
+    __collect_endpoint_stats "A1PMS" 18 "GET" $A1PMS_API_PREFIX"/v2/configuration" $status
+  fi
+  __log_test_pass
+  return 0
 }
 
 ##########################################
@@ -2403,28 +3206,28 @@ a1pms_api_get_configuration() {
 # (Function for test scripts)
 
 a1pms_kube_pvc_reset() {
-       __log_test_start $@
+  __log_test_start $@
 
-       pvc_name=$(kubectl $KUBECONF get pvc -n $KUBE_NONRTRIC_NAMESPACE  --no-headers -o custom-columns=":metadata.name" | grep policy)
-       if [ -z "$pvc_name" ]; then
-               pvc_name=policymanagementservice-vardata-pvc
-       fi
-       echo " Trying to reset pvc: "$pvc_name
-       __kube_clean_pvc $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE $pvc_name $A1PMS_CONTAINER_MNT_DIR
+  pvc_name=$(kubectl $KUBECONF get pvc -n $KUBE_NONRTRIC_NAMESPACE --no-headers -o custom-columns=":metadata.name" | grep policy)
+  if [ -z "$pvc_name" ]; then
+    pvc_name=policymanagementservice-vardata-pvc
+  fi
+  echo " Trying to reset pvc: "$pvc_name
+  __kube_clean_pvc $A1PMS_APP_NAME $KUBE_NONRTRIC_NAMESPACE $pvc_name $A1PMS_CONTAINER_MNT_DIR
 
-       __log_test_pass
-       return 0
+  __log_test_pass
+  return 0
 }
 
 # args: <realm> <client-name> <client-secret>
 a1pms_configure_sec() {
-       export A1PMS_CREDS_GRANT_TYPE="client_credentials"
-       export A1PMS_CREDS_CLIENT_SECRET=$3
-       export A1PMS_CREDS_CLIENT_ID=$2
-       export A1PMS_AUTH_SERVICE_URL=$KEYCLOAK_SERVICE_PATH$KEYCLOAK_TOKEN_URL_PREFIX/$1/protocol/openid-connect/token
-       export A1PMS_SIDECAR_MOUNT="/token-cache"
-       export A1PMS_SIDECAR_JWT_FILE=$A1PMS_SIDECAR_MOUNT"/jwt.txt"
-
-       export AUTHSIDECAR_APP_NAME
-       export AUTHSIDECAR_DISPLAY_NAME
-}
\ No newline at end of file
+  export A1PMS_CREDS_GRANT_TYPE="client_credentials"
+  export A1PMS_CREDS_CLIENT_SECRET=$3
+  export A1PMS_CREDS_CLIENT_ID=$2
+  export A1PMS_AUTH_SERVICE_URL=$KEYCLOAK_SERVICE_PATH$KEYCLOAK_TOKEN_URL_PREFIX/$1/protocol/openid-connect/token
+  export A1PMS_SIDECAR_MOUNT="/token-cache"
+  export A1PMS_SIDECAR_JWT_FILE=$A1PMS_SIDECAR_MOUNT"/jwt.txt"
+
+  export AUTHSIDECAR_APP_NAME
+  export AUTHSIDECAR_DISPLAY_NAME
+}
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 4fad4c4..e7d1ba7
@@ -444,7 +444,7 @@ cr_delay_callback() {
 cr_api_check_all_sync_events() {
        __log_test_start $@
 
-       if [ "$A1PMS_VERSION" != "V2" ]; then
+       if [ "$A1PMS_VERSION" != "V2" ] && [ "$A1PMS_VERSION" != "V3" ]; then
                __log_test_fail_not_supported
                return 1
        fi
index 480d5cb..d81ec74 100644 (file)
@@ -47,7 +47,7 @@ try:
     uuid=str(sys.argv[5])
     start=int(sys.argv[6])
     httpproxy="NOPROXY"
-    if ("/v2/" in baseurl):
+    if ("/v2/" in baseurl) or ("a1policymanagement/v1/" in baseurl):
         if len(sys.argv) != 16:
             print("1Expected 15 args, got "+str(len(sys.argv)-1)+ ". Args: responsecode baseurl ric_base num_rics uuid startid service type transient notification-url templatepath count pids pid_id proxy")
             print (sys.argv[1:])
@@ -116,20 +116,45 @@ try:
                                 data["policytype_id"]=pt
                             else:
                                 data["policytype_id"]=""
-                            if (noti != "NOURL"):
-                                data["status_notification_uri"]=noti
                             data["policy_data"]=json.loads(payload)
 
                             url_out=url
                             data_out=json.dumps(data)
+                            if proxydict is None:
+                                resp=requests.put(url, data_out, headers=headers, verify=False, timeout=90)
+                            else:
+                                resp=requests.put(url, data_out, headers=headers, verify=False, timeout=90, proxies=proxydict)
+
+                        elif ("a1policymanagement/v1/" in baseurl):
+                            url=baseurl
+
+                            data={}
+                            data["nearRtRicId"]=ric
+                            data["serviceId"]=serv
+                            if (trans != "NOTRANSIENT"):
+                                data["transient"]=trans
+                            if (pt != "NOTYPE"):
+                                data["policyTypeId"]=pt
+                            else:
+                                data["policyTypeId"]=""
+                            if (noti != "NOURL"):
+                                data["statusNotificationUri"]=noti
+                            data["policyObject"]=json.loads(payload)
+
+                            url_out=url
+                            data_out=json.dumps(data)
+                            if proxydict is None:
+                                resp=requests.post(url, data_out, headers=headers, verify=False, timeout=90)
+                            else:
+                                resp=requests.post(url, data_out, headers=headers, verify=False, timeout=90, proxies=proxydict)
                         else:
                             url=baseurl+"&id="+uuid+str(i)+"&ric="+str(ric)
                             url_out=url
                             data_out=json.dumps(json.loads(payload))
-                        if proxydict is None:
-                            resp=requests.put(url, data_out, headers=headers, verify=False, timeout=90)
-                        else:
-                            resp=requests.put(url, data_out, headers=headers, verify=False, timeout=90, proxies=proxydict)
+                            if proxydict is None:
+                                resp=requests.put(url, data_out, headers=headers, verify=False, timeout=90)
+                            else:
+                                resp=requests.put(url, data_out, headers=headers, verify=False, timeout=90, proxies=proxydict)
                         connect_ok=True
                     except Exception as e1:
                         if (retry_cnt > 1):
index 5f2fe69..9edd31c 100644 (file)
@@ -42,6 +42,11 @@ try:
         param_me='managed_element_ids'
         param_policy_type='policytype_ids'
         param_state='state'
+    elif (api_version == "V3"):
+        param_ric='ricId'
+        param_me='managedElementIds'
+        param_policy_type='policyTypeIds'
+        param_state='state'
     else:
         param_ric='ricName'
         param_me='managedElementIds'
diff --git a/test/common/delete_policies_process_v3.py b/test/common/delete_policies_process_v3.py
new file mode 100644 (file)
index 0000000..82b37db
--- /dev/null
@@ -0,0 +1,100 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2024 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=================================================
+#
+
+# This script delete policies spread over a number rics
+# Intended for parallel processing
+# Returns a string with result, either "0" for ok, or "1<fault description>"
+
+import sys
+import requests
+import traceback
+from time import sleep
+
+# disable warning about unverified https requests
+from requests.packages import urllib3
+
+urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+
+#arg responsecode baseurl num_rics uuid startid count pids pid_id proxy
+
+try:
+    if len(sys.argv) != 8:
+        print("1Expected 7 args, got "+str(len(sys.argv)-1)+ ". Args: responseCode baseurl policyIdsFilePath startId pids pidID proxy")
+        sys.exit()
+
+    responseCode=int(sys.argv[1])
+    baseurl=str(sys.argv[2])
+    policyIdsFilePath=str(sys.argv[3])
+    startId=int(sys.argv[4])
+    pids=int(sys.argv[5])
+    pidId=int(sys.argv[6])
+    httpproxy=str(sys.argv[7])
+
+    proxydict=None
+    if httpproxy != "NOPROXY":
+        proxydict = {
+            "http" : httpproxy,
+            "https" : httpproxy
+        }
+
+    http_retry_count=0
+    connect_retry_count=0
+
+    with open(str(policyIdsFilePath)) as file:
+        for policyId in file:
+            if startId%pids == (pidId - 1):
+                connect_ok=False
+                retry_cnt=5
+                while(retry_cnt>0):
+                    url=str(baseurl+policyId.strip())
+                    try:
+                        if proxydict is None:
+                            resp=requests.delete(url, verify=False, timeout=90)
+                        else:
+                            resp=requests.delete(url, verify=False, timeout=90, proxies=proxydict)
+                        connect_ok=True
+                    except Exception as e1:
+                        if (retry_cnt > 1):
+                            sleep(0.1)
+                            retry_cnt -= 1
+                            connect_retry_count += 1
+                        else:
+                            print("1DELETE failed for id:"+policyId.strip()+ ", "+str(e1) + " "+traceback.format_exc())
+                            sys.exit()
+
+                    if (connect_ok == True):
+                        if (resp.status_code == None):
+                            print("1DELETE failed for id:"+policyId.strip()+ ", expected response code: "+str(responseCode)+", got: None")
+                            sys.exit()
+                        if (resp.status_code != responseCode):
+                            if (resp.status_code >= 500) and (http_retry_count < 600 ) and (retry_cnt > 1):
+                                sleep(0.1)
+                                retry_cnt -= 1
+                                http_retry_count += 1
+                            else:
+                                print("1DELETE failed for id:"+policyId.strip()+ ", expected response code: "+str(responseCode)+", got: "+str(resp.status_code)+str(resp.raw))
+                                sys.exit()
+                        else:
+                            retry_cnt=-1
+            startId  += 1
+    print("0 http retries:"+str(http_retry_count) + ", connect retries: "+str(connect_retry_count))
+    sys.exit()
+
+except Exception as e:
+    print("1"+str(e))
+    traceback.print_exc()
+sys.exit()
\ No newline at end of file
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/test/common/get_policies_process.py b/test/common/get_policies_process.py
new file mode 100644 (file)
index 0000000..3afd819
--- /dev/null
@@ -0,0 +1,109 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2024 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=================================================
+#
+
+# This script gets policies spread over a number rics
+# Intended for parallel processing
+# Returns a string with result, either "0" for ok, or "1<fault description>"
+
+import os
+import json
+import sys
+import requests
+import traceback
+
+# disable warning about unverified https requests
+from requests.packages import urllib3
+
+urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+
+#arg responsecode baseurl num_rics uuid startid count pids pid_id proxy
+
+try:
+    if len(sys.argv) != 10:
+        print("1Expected 9 args, got "+str(len(sys.argv)-1)+ ". Args: responsecode baseurl num_rics uuid startid count pids pid_id proxy")
+        sys.exit()
+
+    responsecode=int(sys.argv[1])
+    baseurl=str(sys.argv[2])
+    num_rics=int(sys.argv[3])
+    uuid=str(sys.argv[4])
+    start=int(sys.argv[5])
+    count=int(sys.argv[6])
+    pids=int(sys.argv[7])
+    pid_id=int(sys.argv[8])
+    httpproxy=str(sys.argv[9])
+
+    proxydict=None
+    if httpproxy != "NOPROXY":
+        proxydict = {
+            "http" : httpproxy,
+            "https" : httpproxy
+        }
+    if uuid == "NOUUID":
+        uuid=""
+
+    http_retry_count=0
+    connect_retry_count=0
+
+    stop=count*num_rics+start
+    for i in range(start,stop):
+        if (i%pids == (pid_id-1)):
+            connect_ok=False
+            retry_cnt=5
+            while(retry_cnt>0):
+                if ("/v2/policies/" in baseurl):
+                    url=str(baseurl+uuid+str(i))
+                else:
+                    url=str(baseurl+"?id="+uuid+str(i))
+                try:
+                    if proxydict is None:
+                        resp=requests.get(url, verify=False, timeout=90)
+                    else:
+                        resp=requests.get(url, verify=False, timeout=90, proxies=proxydict)
+                    cconnect_ok=True
+                except Exception as e1:
+                    if (retry_cnt > 1):
+                        sleep(0.1)
+                        retry_cnt -= 1
+                        connect_retry_count += 1
+                    else:
+                        print("1Get failed for id:"+uuid+str(i)+ ", "+str(e1) + " "+traceback.format_exc())
+                        sys.exit()
+
+                if (cconnect_ok == True):
+                    if (resp.status_code == None):
+                        print("1Get failed for id:"+uuid+str(i)+ ", expected response code: "+str(responsecode)+", got: None")
+                        sys.exit()
+                    if (resp.status_code != responsecode):
+                        if (resp.status_code >= 500) and (http_retry_count < 600 ) and (retry_cnt > 1):
+                            sleep(0.1)
+                            retry_cnt -= 1
+                            http_retry_count += 1
+                        else:
+                            print("1Get failed for id:"+uuid+str(i)+ ", expected response code: "+str(responsecode)+", got: "+str(resp.status_code)+str(resp.raw))
+                            sys.exit()
+                    else:
+                        retry_cnt=-1
+
+    print("0 http retries:"+str(http_retry_count) + ", connect retries: "+str(connect_retry_count))
+    sys.exit()
+
+except Exception as e:
+    print("1"+str(e))
+    traceback.print_exc()
+sys.exit()
\ No newline at end of file
diff --git a/test/common/get_policies_process_v3.py b/test/common/get_policies_process_v3.py
new file mode 100644 (file)
index 0000000..b62adf5
--- /dev/null
@@ -0,0 +1,101 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2024 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=================================================
+#
+
+# This script gets policies spread over a number rics
+# Intended for parallel processing
+# Returns a string with result, either "0" for ok, or "1<fault description>"
+
+import sys
+import requests
+import traceback
+from time import sleep
+
+# disable warning about unverified https requests
+from requests.packages import urllib3
+
+urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+
+#arg responseCode baseurl policyIdsFilePath proxy
+
+try:
+    if len(sys.argv) != 8:
+        print("1Expected 7 args, got "+str(len(sys.argv)-1)+ ". Args: responseCode baseurl policyIdsFilePath startId pids pidID proxy")
+        sys.exit()
+
+    responseCode=int(sys.argv[1])
+    baseurl=str(sys.argv[2])
+    policyIdsFilePath=str(sys.argv[3])
+    startId=int(sys.argv[4])
+    pids=int(sys.argv[5])
+    pidId=int(sys.argv[6])
+    httpproxy=str(sys.argv[7])
+
+    proxydict=None
+    if httpproxy != "NOPROXY":
+        proxydict = {
+            "http" : httpproxy,
+            "https" : httpproxy
+        }
+
+    http_retry_count=0
+    connect_retry_count=0
+
+    with open(str(policyIdsFilePath)) as file:
+        for policyId in file:
+            if startId%pids == (pidId - 1):
+                connect_ok=False
+                retry_cnt=5
+                while(retry_cnt>0):
+                    url=str(baseurl+policyId.strip())
+                    try:
+                        if proxydict is None:
+                            resp=requests.get(url, verify=False, timeout=90)
+                        else:
+                            resp=requests.get(url, verify=False, timeout=90, proxies=proxydict)
+                        connect_ok=True
+                    except Exception as e1:
+                        if (retry_cnt > 1):
+                            sleep(0.1)
+                            retry_cnt -= 1
+                            connect_retry_count += 1
+                        else:
+                            print("1Get failed for id:"+policyId.strip()+ ", "+str(e1) + " "+traceback.format_exc())
+                            sys.exit()
+
+                    if (connect_ok == True):
+                        if (resp.status_code == None):
+                            print("1Get failed for id:"+policyId.strip()+ ", expected response code: "+str(responseCode)+", got: None")
+                            sys.exit()
+                        if (resp.status_code != responseCode):
+                            if (resp.status_code >= 500) and (http_retry_count < 600 ) and (retry_cnt > 1):
+                                sleep(0.1)
+                                retry_cnt -= 1
+                                http_retry_count += 1
+                            else:
+                                print("1Get failed for id:"+policyId.strip()+ ", expected response code: "+str(responseCode)+", got: "+str(resp.status_code)+str(resp.raw))
+                                sys.exit()
+                        else:
+                            retry_cnt=-1
+            startId  += 1
+    print("0 http retries:"+str(http_retry_count) + ", connect retries: "+str(connect_retry_count))
+    sys.exit()
+
+except Exception as e:
+    print("1"+str(e))
+    traceback.print_exc()
+sys.exit()
\ No newline at end of file
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index aef32cb..25cb414
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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.
@@ -433,7 +434,7 @@ ricmediatorsim_put_policy_type() {
                return 1
        fi
        host=$(__find_ricmediatorsim_host $2)
-    curlString="curl -X PUT -skw %{http_code} "$host"/a1-p/policytypes/"$3" -H Content-Type:application/json --data-binary @"$4
+    curlString="curl -X PUT -skw %{http_code} "$host"/A1-P/v2/policytypes/"$3" -H Content-Type:application/json --data-binary @"$4
        __execute_curl_to_ricmediatorsim $1 "$curlString"
        return $?
 }
@@ -448,7 +449,7 @@ ricmediatorsim_delete_policy_type() {
                return 1
        fi
        host=$(__find_ricmediatorsim_host $2)
-    curlString="curl -X DELETE -skw %{http_code} "$host"/a1-p/policytypes/"$3
+    curlString="curl -X DELETE -skw %{http_code} "$host"/A1-P/v2/policytypes/"$3
     __execute_curl_to_ricmediatorsim $1 "$curlString"
        return $?
 }
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 4fd9de4..a18afe3
@@ -588,8 +588,14 @@ controller_api_get_A1_policy_status() {
     if [ $# -ge 5 ] && [ $2 == "OSC" ]; then
         url="$ric_id/a1-p/policytypes/$4/policies/$UUID$5/status"
         if [ $# -gt 5 ]; then
-            targetJson="{\"enforceStatus\":\"$6\""
-            targetJson=$targetJson",\"enforceReason\":\"$7\"}"
+            if [[ $TEST_ENV_PROFILE =~ ^ORAN-[A-H] ]] || [[ $TEST_ENV_PROFILE =~ ^ONAP-[A-L] ]]; then
+              targetJson="{\"instance_status\":\"$6\""
+              targetJson=$targetJson",\"has_been_deleted\":\"$7\""
+              targetJson=$targetJson",\"created_at\":\"????\"}"
+            else
+              targetJson="{\"enforceStatus\":\"$6\""
+              targetJson=$targetJson",\"enforceReason\":\"$7\"}"
+            fi
         fi
                paramError=0
     elif [ $# -ge 4 ] && [ $2 == "STD" ]; then
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index c7d6094..3266c1d
@@ -86,27 +86,27 @@ SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_RELEASE="2.5.1"
 SDNC_DB_IMAGE_BASE="mariadb"
 SDNC_DB_IMAGE_TAG_REMOTE_PROXY="10.5"
 
-# ICS image and tag - using g release
+# ICS image and tag - using h release
 ICS_IMAGE_BASE="o-ran-sc/nonrtric-plt-informationcoordinatorservice"
-ICS_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.4.1"
+ICS_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.5.0"
 #Note: Update var ICS_FEATURE_LEVEL if image version is changed
 
-# Control Panel image and tag - using g release
+# Control Panel image and tag - using h release
 CONTROL_PANEL_IMAGE_BASE="o-ran-sc/nonrtric-controlpanel"
-CONTROL_PANEL_IMAGE_TAG_REMOTE_RELEASE_ORAN="2.4.0"
+CONTROL_PANEL_IMAGE_TAG_REMOTE_RELEASE_ORAN="2.5.0"
 
-# Gateway image and tags - used g release
+# Gateway image and tags - used h release
 NRT_GATEWAY_IMAGE_BASE="o-ran-sc/nonrtric-gateway"
-NRT_GATEWAY_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.0.0"
+NRT_GATEWAY_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.2.0"
 
-# RAPP Catalogue image and tags - used g release
+# RAPP Catalogue image and tags - used h release
 RAPP_CAT_IMAGE_BASE="o-ran-sc/nonrtric-plt-rappcatalogue"
-RAPP_CAT_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.1.0"
+RAPP_CAT_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.2.0"
 
 
-# Near RT RIC Simulator image and tags - used g release
+# Near RT RIC Simulator image and tags - used h release
 RIC_SIM_IMAGE_BASE="o-ran-sc/a1-simulator"
-RIC_SIM_IMAGE_TAG_REMOTE_RELEASE_ORAN="2.4.0"
+RIC_SIM_IMAGE_TAG_REMOTE_RELEASE_ORAN="2.5.0"
 
 #MR stub image and tag
 MRSTUB_IMAGE_BASE="mrstub"
old mode 100644 (file)
new mode 100755 (executable)
similarity index 92%
rename from test/common/test_env-onap-jakarta.sh
rename to test/common/test_env-onap-montreal.sh
index 49c4ec6..6970eb4
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2021-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023 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.
@@ -17,7 +18,7 @@
 #  ============LICENSE_END=================================================
 #
 #Profile for ONAP honolulu release
-TEST_ENV_PROFILE="ONAP-JAKARTA"
+TEST_ENV_PROFILE="ONAP-MONTREAL"
 FLAVOUR="ONAP"
 
 ########################################
@@ -69,44 +70,44 @@ NEXUS_RELEASE_REPO_ONAP=$NEXUS_RELEASE_REPO
 
 # A1PMS image and tags
 A1PMS_IMAGE_BASE="onap/ccsdk-oran-a1policymanagementservice"
-A1PMS_IMAGE_TAG_LOCAL="1.3.3-SNAPSHOT"
-A1PMS_IMAGE_TAG_REMOTE_SNAPSHOT="1.3.3-SNAPSHOT"
-A1PMS_IMAGE_TAG_REMOTE="1.3.3-STAGING-latest" #Will use snapshot repo
-A1PMS_IMAGE_TAG_REMOTE_RELEASE="1.3.3"
+A1PMS_IMAGE_TAG_LOCAL="1.6.1-SNAPSHOT"
+A1PMS_IMAGE_TAG_REMOTE_SNAPSHOT="1.6.1-SNAPSHOT"
+A1PMS_IMAGE_TAG_REMOTE="1.6.1-STAGING-latest" #Will use snapshot repo
+A1PMS_IMAGE_TAG_REMOTE_RELEASE="1.6.1"
 
 # SDNC A1 Controller remote image and tag
 SDNC_A1_CONTROLLER_IMAGE_BASE="onap/sdnc-image"
-SDNC_A1_CONTROLLER_IMAGE_TAG_LOCAL="2.3.3-SNAPSHOT" ###CHECK THIS
-SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_SNAPSHOT="2.3.3-STAGING-latest"
-SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE="2.3.3-STAGING-latest"  #Will use snapshot repo
-SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_RELEASE="2.3.2"
+SDNC_A1_CONTROLLER_IMAGE_TAG_LOCAL="2.5.1-SNAPSHOT" ###CHECK THIS
+SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_SNAPSHOT="2.5.1-STAGING-latest"
+SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE="2.5.1-STAGING-latest"  #Will use snapshot repo
+SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_RELEASE="2.5.1"
 
 #SDNC DB remote image and tag
 #The DB is part of SDNC so handled in the same way as SDNC
 SDNC_DB_IMAGE_BASE="mariadb"
 SDNC_DB_IMAGE_TAG_REMOTE_PROXY="10.5"
 
-# ICS image and tag - using e release
-ICS_IMAGE_BASE="o-ran-sc/nonrtric-information-coordinator-service"
-ICS_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.2.1"
+# ICS image and tag - using i release
+ICS_IMAGE_BASE="o-ran-sc/nonrtric-plt-informationcoordinatorservice"
+ICS_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.6.0"
 #Note: Update var ICS_FEATURE_LEVEL if image version is changed
 
-# Control Panel image and tag - using e release
+# Control Panel image and tag - using i release
 CONTROL_PANEL_IMAGE_BASE="o-ran-sc/nonrtric-controlpanel"
-CONTROL_PANEL_IMAGE_TAG_REMOTE_RELEASE_ORAN="2.3.0"
+CONTROL_PANEL_IMAGE_TAG_REMOTE_RELEASE_ORAN="2.5.0"
 
-# Gateway image and tags - used e release
+# Gateway image and tags - used i release
 NRT_GATEWAY_IMAGE_BASE="o-ran-sc/nonrtric-gateway"
-NRT_GATEWAY_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.0.0"
+NRT_GATEWAY_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.2.0"
 
-# RAPP Catalogue image and tags - used e release
-RAPP_CAT_IMAGE_BASE="o-ran-sc/nonrtric-r-app-catalogue"
-RAPP_CAT_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.0.2"
+# RAPP Catalogue image and tags - used i release
+RAPP_CAT_IMAGE_BASE="o-ran-sc/nonrtric-plt-rappcatalogue"
+RAPP_CAT_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.2.0"
 
 
-# Near RT RIC Simulator image and tags - used e release
+# Near RT RIC Simulator image and tags - used i release
 RIC_SIM_IMAGE_BASE="o-ran-sc/a1-simulator"
-RIC_SIM_IMAGE_TAG_REMOTE_RELEASE_ORAN="2.2.0"
+RIC_SIM_IMAGE_TAG_REMOTE_RELEASE_ORAN="2.6.1"
 
 #MR stub image and tag
 MRSTUB_IMAGE_BASE="mrstub"
@@ -185,7 +186,10 @@ A1PMS_EXTERNAL_SECURE_PORT=8433                            # A1PMS container ext
 A1PMS_INTERNAL_SECURE_PORT=8433                            # A1PMS container internal secure port (container -> container)
 A1PMS_APIS="V1 V2"                                         # Supported northbound api versions
 A1PMS_VERSION="V2"                                         # Tested version of northbound API
+# A1PMS_V3="V3"                                            # To be used this property in further env releases
 A1PMS_API_PREFIX="/a1-policy"                              # api url prefix, only for V2. Shall contain leading "/"
+# A1PMS_API_PREFIX_V3="/a1policymanagement"                # To be used this property in further env releases
+# A1PMS_V3_FLAG="true"                                       # To be used this property in further env releases
 
 A1PMS_APP_NAME="policymanagementservice"                   # Name for A1PMS container
 A1PMS_DISPLAY_NAME="Policy Management Service"
@@ -196,13 +200,16 @@ A1PMS_CONFIG_KEY="policy-agent"                            # Key for consul conf
 A1PMS_PKG_NAME="org.onap.ccsdk.oran.a1policymanagementservice"  # Java base package name
 A1PMS_ACTUATOR="/actuator/loggers/$A1PMS_PKG_NAME"           # Url for trace/debug
 A1PMS_ALIVE_URL="$A1PMS_API_PREFIX/v2/status"                # Base path for alive check
+# A1PMS_ALIVE_URL_V3=/v1/status                            # To be used this property in further env releases
 A1PMS_COMPOSE_DIR="a1pms"                                    # Dir in simulator_group for docker-compose
 A1PMS_CONFIG_MOUNT_PATH="/opt/app/policy-agent/config"     # Path in container for config file
 A1PMS_DATA_MOUNT_PATH="/opt/app/policy-agent/data"         # Path in container for data file
 A1PMS_CONFIG_FILE="application.yaml"                       # Container config file name
 A1PMS_DATA_FILE="application_configuration.json"           # Container data file name
 A1PMS_CONTAINER_MNT_DIR="/var/policy-management-service"   # Mounted dir in the container
-A1PMS_FEATURE_LEVEL=""                                     # Space separated list of features
+A1PMS_FEATURE_LEVEL="NO-DMAAP ADAPTER-CLASS"               # Space separated list of features
+A1PMS_ADAPTER_CLASS=""                                     # Class name set by override file
+A1PMS_ADAPTER_POLICY_NAME=""                               # Policy name set by override file
 
 ICS_APP_NAME="informationservice"                        # Name for ICS container
 ICS_DISPLAY_NAME="Enrichment Coordinator Service"        # Display name for ICS container
@@ -311,7 +318,7 @@ SDNC_KUBE_APP_FILE="app2.yaml"
 SDNC_KARAF_LOG="/opt/opendaylight/data/log/karaf.log"    # Path to karaf log
 SDNC_RESPONSE_JSON_KEY="A1-ADAPTER-API:output"           # Key name for output json in replies from sdnc (for upgraded sdnc)
 #SDNC_RESPONSE_JSON_KEY="output"                          # Key name for output json in replies from sdnc
-SDNC_FEATURE_LEVEL="TRANS_RESP_CODE"                     # Space separated list of features
+SDNC_FEATURE_LEVEL="TRANS_RESP_CODE NO_NB_HTTPS"         # Space separated list of features
                                                          # TRANS_RESP_CODE: SDNC return southbound response code
 
 RAPP_CAT_APP_NAME="rappcatalogueservice"                 # Name for the RAPP Catalogue
@@ -396,4 +403,4 @@ PVC_CLEANER_COMPOSE_DIR="pvc-cleaner"                   # Dir in simulator_group
 ########################################
 
 UUID=""                                                  # UUID used as prefix to the policy id to simulate a real UUID
-                                                         # Test script need to set the UUID to use other this empty prefix is used
+                                                         # Testscript need to set the UUID to use other this empty prefix is used
index cc41c49..dc8ee22 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023-2024 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.
@@ -131,7 +132,7 @@ RIC_SIM_IMAGE_TAG_REMOTE_RELEASE="2.5.0"
 
 # ORAN Near RT RIC Simulator image and tags
 RICMEDIATOR_SIM_IMAGE_BASE="o-ran-sc/ric-plt-a1"
-RICMEDIATOR_SIM_IMAGE_TAG_REMOTE_RELEASE_ORAN="3.0.1"
+RICMEDIATOR_SIM_IMAGE_TAG_REMOTE_RELEASE_ORAN="3.1.1"
 
 # ORAN Near RT RIC Simulator DB image and tags
 RICMEDIATOR_SIM_DB_IMAGE_BASE="o-ran-sc/ric-plt-dbaas"
@@ -288,7 +289,7 @@ A1PMS_DATA_FILE="application_configuration.json"           # Container data file
 A1PMS_CONTAINER_MNT_DIR="/var/policy-management-service"   # Mounted dir in the container
 A1PMS_FEATURE_LEVEL="NO-DMAAP ADAPTER-CLASS"               # Space separated list of features
 A1PMS_ADAPTER_CLASS=""                                     # Class name set by override file
-A1PMS_ADAPTER_POLICY_NAME=""                               # Policy name set by override file
+A1PMS_ADAPTER_POLICY_TYPE=""                               # Policy type set by override file
 
 ICS_APP_NAME="informationservice"                        # Name for ICS container
 ICS_DISPLAY_NAME="Information Coordinator Service"       # Display name for ICS container
similarity index 87%
rename from test/common/test_env-oran-f-release.sh
rename to test/common/test_env-oran-i-release.sh
index 1cb8def..d35ea1e 100755 (executable)
@@ -2,6 +2,7 @@
 
 #  ============LICENSE_START===============================================
 #  Copyright (C) 2020-2023 Nordix Foundation. All rights reserved.
+#  Copyright (C) 2023-2024 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.
@@ -16,8 +17,8 @@
 #  limitations under the License.
 #  ============LICENSE_END=================================================
 #
-#Profile for ORAN Cherry
-TEST_ENV_PROFILE="ORAN-F-RELEASE"
+#Profile for ORAN H release
+TEST_ENV_PROFILE="ORAN-I-RELEASE"
 FLAVOUR="ORAN"
 
 ########################################
@@ -60,38 +61,38 @@ NEXUS_RELEASE_REPO_ORAN=$NEXUS_RELEASE_REPO
 
 # A1PMS base image and tags
 A1PMS_IMAGE_BASE="o-ran-sc/nonrtric-plt-a1policymanagementservice"
-A1PMS_IMAGE_TAG_LOCAL="2.4.1-SNAPSHOT"
-A1PMS_IMAGE_TAG_REMOTE_SNAPSHOT="2.4.1-SNAPSHOT"
-A1PMS_IMAGE_TAG_REMOTE="2.4.1"
-A1PMS_IMAGE_TAG_REMOTE_RELEASE="2.4.1"
+A1PMS_IMAGE_TAG_LOCAL="2.7.0-SNAPSHOT"
+A1PMS_IMAGE_TAG_REMOTE_SNAPSHOT="2.7.0-SNAPSHOT"
+A1PMS_IMAGE_TAG_REMOTE="2.7.0"
+A1PMS_IMAGE_TAG_REMOTE_RELEASE="2.7.0"
 
 # ICS image and tags
 ICS_IMAGE_BASE="o-ran-sc/nonrtric-plt-informationcoordinatorservice"
-ICS_IMAGE_TAG_LOCAL="1.3.2-SNAPSHOT"
-ICS_IMAGE_TAG_REMOTE_SNAPSHOT="1.3.2-SNAPSHOT"
-ICS_IMAGE_TAG_REMOTE="1.3.2"
-ICS_IMAGE_TAG_REMOTE_RELEASE="1.3.1"
+ICS_IMAGE_TAG_LOCAL="1.6.0-SNAPSHOT"
+ICS_IMAGE_TAG_REMOTE_SNAPSHOT="1.6.0-SNAPSHOT"
+ICS_IMAGE_TAG_REMOTE="1.6.0"
+ICS_IMAGE_TAG_REMOTE_RELEASE="1.6.0"
 #Note: Update var ICS_FEATURE_LEVEL if image version is changed
 
 #Control Panel image and tags
 CONTROL_PANEL_IMAGE_BASE="o-ran-sc/nonrtric-controlpanel"
-CONTROL_PANEL_IMAGE_TAG_LOCAL="2.3.0-SNAPSHOT"
-CONTROL_PANEL_IMAGE_TAG_REMOTE_SNAPSHOT="2.3.0-SNAPSHOT"
-CONTROL_PANEL_IMAGE_TAG_REMOTE="2.3.0"
-CONTROL_PANEL_IMAGE_TAG_REMOTE_RELEASE="2.3.0"
+CONTROL_PANEL_IMAGE_TAG_LOCAL="2.5.0-SNAPSHOT"
+CONTROL_PANEL_IMAGE_TAG_REMOTE_SNAPSHOT="2.5.0-SNAPSHOT"
+CONTROL_PANEL_IMAGE_TAG_REMOTE="2.5.0"
+CONTROL_PANEL_IMAGE_TAG_REMOTE_RELEASE="2.5.0"
 
 
 # Gateway image and tags
 NRT_GATEWAY_IMAGE_BASE="o-ran-sc/nonrtric-gateway"
-NRT_GATEWAY_IMAGE_TAG_LOCAL="1.1.0-SNAPSHOT"
-NRT_GATEWAY_IMAGE_TAG_REMOTE_SNAPSHOT="1.1.0-SNAPSHOT"
-NRT_GATEWAY_IMAGE_TAG_REMOTE="1.1.0"
-NRT_GATEWAY_IMAGE_TAG_REMOTE_RELEASE="1.0.0"
+NRT_GATEWAY_IMAGE_TAG_LOCAL="1.2.0-SNAPSHOT"
+NRT_GATEWAY_IMAGE_TAG_REMOTE_SNAPSHOT="1.2.0-SNAPSHOT"
+NRT_GATEWAY_IMAGE_TAG_REMOTE="1.2.0"
+NRT_GATEWAY_IMAGE_TAG_REMOTE_RELEASE="1.2.0"
 
 
-# SDNC A1 Controller image and tags - Note using released ONAP image
+# SDNC A1 Controller image and tags - Note using released honolulu ONAP image
 SDNC_A1_CONTROLLER_IMAGE_BASE="onap/sdnc-image"
-SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_RELEASE_ONAP="2.2.5"
+SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_RELEASE_ONAP="2.5.1"
 #No local image for ONAP SDNC, remote release image always used
 
 # ORAN SDNC adapter kept as reference
@@ -116,46 +117,54 @@ SDNC_DB_IMAGE_TAG_REMOTE_PROXY="10.5"
 
 # RAPP Catalogue image and tags
 RAPP_CAT_IMAGE_BASE="o-ran-sc/nonrtric-plt-rappcatalogue"
-RAPP_CAT_IMAGE_TAG_LOCAL="1.1.0-SNAPSHOT"
-RAPP_CAT_IMAGE_TAG_REMOTE_SNAPSHOT="1.1.0-SNAPSHOT"
-RAPP_CAT_IMAGE_TAG_REMOTE="1.1.0"
-RAPP_CAT_IMAGE_TAG_REMOTE_RELEASE="1.1.0"
+RAPP_CAT_IMAGE_TAG_LOCAL="1.2.0-SNAPSHOT"
+RAPP_CAT_IMAGE_TAG_REMOTE_SNAPSHOT="1.2.0-SNAPSHOT"
+RAPP_CAT_IMAGE_TAG_REMOTE="1.2.0"
+RAPP_CAT_IMAGE_TAG_REMOTE_RELEASE="1.2.0"
 
 
-# Near RT RIC Simulator image and tags - same version as cherry
+# Near RT RIC Simulator image and tags
 RIC_SIM_IMAGE_BASE="o-ran-sc/a1-simulator"
 RIC_SIM_IMAGE_TAG_LOCAL="latest"
-RIC_SIM_IMAGE_TAG_REMOTE_SNAPSHOT="2.3.2-SNAPSHOT"
-RIC_SIM_IMAGE_TAG_REMOTE="2.3.2"
-RIC_SIM_IMAGE_TAG_REMOTE_RELEASE="2.3.1"
+RIC_SIM_IMAGE_TAG_REMOTE_SNAPSHOT="2.6.1-SNAPSHOT"
+RIC_SIM_IMAGE_TAG_REMOTE="2.6.1"
+RIC_SIM_IMAGE_TAG_REMOTE_RELEASE="2.6.1"
+
+# ORAN Near RT RIC Simulator image and tags
+RICMEDIATOR_SIM_IMAGE_BASE="o-ran-sc/ric-plt-a1"
+RICMEDIATOR_SIM_IMAGE_TAG_REMOTE_RELEASE_ORAN="3.2.1"
+
+# ORAN Near RT RIC Simulator DB image and tags
+RICMEDIATOR_SIM_DB_IMAGE_BASE="o-ran-sc/ric-plt-dbaas"
+RICMEDIATOR_SIM_DB_IMAGE_TAG_REMOTE_RELEASE_ORAN="0.6.2"
 
 # DMAAP Mediator Service
 DMAAP_MED_IMAGE_BASE="o-ran-sc/nonrtric-plt-dmaapmediatorproducer"
-DMAAP_MED_IMAGE_TAG_LOCAL="1.1.0-SNAPSHOT"
-DMAAP_MED_IMAGE_TAG_REMOTE_SNAPSHOT="1.1.0-SNAPSHOT"
-DMAAP_MED_IMAGE_TAG_REMOTE="1.1.0"
-DMAAP_MED_IMAGE_TAG_REMOTE_RELEASE="1.1.0"
+DMAAP_MED_IMAGE_TAG_LOCAL="1.2.0-SNAPSHOT"
+DMAAP_MED_IMAGE_TAG_REMOTE_SNAPSHOT="1.2.0-SNAPSHOT"
+DMAAP_MED_IMAGE_TAG_REMOTE="1.2.0"
+DMAAP_MED_IMAGE_TAG_REMOTE_RELEASE="1.2.0"
 
 # DMAAP Adapter Service
 DMAAP_ADP_IMAGE_BASE="o-ran-sc/nonrtric-plt-dmaapadapter"
-DMAAP_ADP_IMAGE_TAG_LOCAL="1.1.1-SNAPSHOT"
-DMAAP_ADP_IMAGE_TAG_REMOTE_SNAPSHOT="1.1.1-SNAPSHOT"
-DMAAP_ADP_IMAGE_TAG_REMOTE="1.1.1"
-DMAAP_ADP_IMAGE_TAG_REMOTE_RELEASE="1.1.1"
+DMAAP_ADP_IMAGE_TAG_LOCAL="1.3.0-SNAPSHOT"
+DMAAP_ADP_IMAGE_TAG_REMOTE_SNAPSHOT="1.3.0-SNAPSHOT"
+DMAAP_ADP_IMAGE_TAG_REMOTE="1.3.0"
+DMAAP_ADP_IMAGE_TAG_REMOTE_RELEASE="1.3.0"
 
 # Helm Manager
 HELM_MANAGER_IMAGE_BASE="o-ran-sc/nonrtric-plt-helmmanager"
-HELM_MANAGER_IMAGE_TAG_LOCAL="1.2.0-SNAPSHOT"
-HELM_MANAGER_IMAGE_TAG_REMOTE_SNAPSHOT="1.2.0-SNAPSHOT"
-HELM_MANAGER_IMAGE_TAG_REMOTE="1.2.0"
-HELM_MANAGER_IMAGE_TAG_REMOTE_RELEASE="1.2.0"
+HELM_MANAGER_IMAGE_TAG_LOCAL="1.3.0-SNAPSHOT"
+HELM_MANAGER_IMAGE_TAG_REMOTE_SNAPSHOT="1.3.0-SNAPSHOT"
+HELM_MANAGER_IMAGE_TAG_REMOTE="1.3.0"
+HELM_MANAGER_IMAGE_TAG_REMOTE_RELEASE="1.3.0"
 
 # Auth sidecar
 AUTHSIDECAR_IMAGE_BASE="o-ran-sc/nonrtric-auth-token-fetch"
-AUTHSIDECAR_IMAGE_TAG_LOCAL="1.0.0-SNAPSHOT"
-AUTHSIDECAR_IMAGE_TAG_REMOTE_SNAPSHOT="1.0.0-SNAPSHOT"
-AUTHSIDECAR_IMAGE_TAG_REMOTE="1.0.0"
-AUTHSIDECAR_IMAGE_TAG_REMOTE_RELEASE="1.0.0"
+AUTHSIDECAR_IMAGE_TAG_LOCAL="1.1.1-SNAPSHOT"
+AUTHSIDECAR_IMAGE_TAG_REMOTE_SNAPSHOT="1.1.1-SNAPSHOT"
+AUTHSIDECAR_IMAGE_TAG_REMOTE="1.1.1"
+AUTHSIDECAR_IMAGE_TAG_REMOTE_RELEASE="1.1.1"
 
 #MR stub image and tag
 MRSTUB_IMAGE_BASE="mrstub"
@@ -278,7 +287,11 @@ A1PMS_DATA_MOUNT_PATH="/opt/app/policy-agent/data"         # Path in container f
 A1PMS_CONFIG_FILE="application.yaml"                       # Container config file name
 A1PMS_DATA_FILE="application_configuration.json"           # Container data file name
 A1PMS_CONTAINER_MNT_DIR="/var/policy-management-service"   # Mounted dir in the container
-A1PMS_FEATURE_LEVEL=""                                     # Space separated list of features
+A1PMS_FEATURE_LEVEL="NO-DMAAP ADAPTER-CLASS"               # Space separated list of features
+A1PMS_ADAPTER_CLASS=""                                     # Class name set by override file
+A1PMS_ADAPTER_POLICY_TYPE=""                               # Policy type set by override file
+A1PMS_NOSDNC_ADAPTER_CLASS=""                              # Class name set by override file
+A1PMS_SDNC_ADAPTER_CLASS=""                                # Class name set by override file
 
 ICS_APP_NAME="informationservice"                        # Name for ICS container
 ICS_DISPLAY_NAME="Information Coordinator Service"       # Display name for ICS container
@@ -359,7 +372,7 @@ RIC_SIM_PREFIX="ricsim"                                  # Prefix added to ric c
                                                          # This prefix can be changed from the command line
 RIC_SIM_INTERNAL_PORT=8085                               # RIC Simulator container internal port (container -> container).
                                                          # (external ports allocated by docker)
-RIC_SIM_INTERNAL_SECURE_PORT=8185                        # RIC Simulator container internal secure port (container -> container).
+RIC_SIM_INTERNAL_SECURE_PORT=8185                       # RIC Simulator container internal secure port (container -> container).
                                                          # (external ports allocated by docker)
 RIC_SIM_CERT_MOUNT_DIR="./cert"
 
@@ -367,6 +380,24 @@ RIC_SIM_COMPOSE_DIR="ric"                                # Dir in simulator grou
 RIC_SIM_ALIVE_URL="/"                                    # Base path for alive check
 RIC_SIM_COMMON_SVC_NAME=""                               # Name of svc if one common svc is used for all ric sim groups (stateful sets)
 
+RICMEDIATOR_SIM_DISPLAY_NAME="ORAN Near-RT RIC A1 Simulator"
+RICMEDIATOR_SIM_DB_DISPLAY_NAME="ORAN Near-RT RIC A1 Simulator DB"
+RICMEDIATOR_SIM_BASE="g"                                     # Base name of the RIC Simulator container, shall be the group code
+                                                         # Note, a prefix is added to each container name by the .env file in the 'ric' dir
+RICMEDIATOR_SIM_PREFIX="ricsim"                              # Prefix added to ric container name, added in the .env file in the 'ric' dir
+                                                         # This prefix can be changed from the command line
+RICMEDIATOR_SIM_INTERNAL_PORT=10000                      # RIC Simulator container internal port (container -> container).
+                                                         # (external ports allocated by docker)
+RICMEDIATOR_SIM_INTERNAL_SECURE_PORT=10001               # RIC Simulator container internal secure port (container -> container).
+                                                         # (external ports allocated by docker)
+                                                         # This port number is not supported by app, kept only for consistency with other ric sims
+RICMEDIATOR_SIM_CERT_MOUNT_DIR="./cert"
+
+RICMEDIATOR_SIM_COMPOSE_DIR="ricmediator"                # Dir in simulator group for docker compose
+RICMEDIATOR_SIM_ALIVE_URL="/A1-P/v2/healthcheck"         # Base path for alive check
+RICMEDIATOR_SIM_COMMON_SVC_NAME=""                       # Name of svc if one common svc is used for all ric sim groups (stateful sets)
+
+
 # For ONAP sdnc
 SDNC_APP_NAME="a1controller"                             # Name of the SNDC A1 Controller container
 SDNC_DISPLAY_NAME="SDNC A1 Controller"
@@ -381,7 +412,7 @@ SDNC_PWD="admin"                                         # SNDC PWD
 SDNC_PWD="Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U"   # SNDC PWD
 #SDNC_API_URL="/rests/operations/A1-ADAPTER-API:"         # Base url path for SNDC API (for upgraded sdnc)
 SDNC_API_URL="/restconf/operations/A1-ADAPTER-API:"      # Base url path for SNDC API
-SDNC_ALIVE_URL="/apidoc/explorer/"                       # Base url path for SNDC API docs (for alive check)
+SDNC_ALIVE_URL="/apidoc/explorer/index.html"                       # Base url path for SNDC API docs (for alive check)
 SDNC_COMPOSE_DIR="sdnc"
 SDNC_COMPOSE_FILE="docker-compose-2.yml"
 SDNC_KUBE_APP_FILE="app2.yaml"
@@ -487,9 +518,9 @@ DMAAP_ADP_CONFIG_MOUNT_PATH="/opt/app/dmaap-adapter-service/config" # Internal c
 DMAAP_ADP_DATA_MOUNT_PATH="/opt/app/dmaap-adapter-service/data" # Path in container for data file
 DMAAP_ADP_DATA_FILE="application_configuration.json"  # Container data file name
 DMAAP_ADP_CONFIG_FILE=application.yaml                   # Config file name
-DMAAP_ADP_CONFIG_FILE_TEMPLATE=application1.yaml         # Template config file name
-DMAAP_ADP_FEATURE_LEVEL="GENERATED_PROD_NAME"            # Space separated list of features
-
+DMAAP_ADP_CONFIG_FILE_TEMPLATE=application2.yaml         # Template config file name
+DMAAP_ADP_FEATURE_LEVEL="GENERATED_PROD_NAME FILTERSPEC FILTERSCHEMA"            # Space separated list of features
+                                                         # FILTERSCHEMA corrected type schema from rel h
 DMAAP_MED_APP_NAME="dmaapmediatorservice"                # Name for Dmaap Mediator container
 DMAAP_MED_DISPLAY_NAME="Dmaap Mediator Service"          # Display name for Dmaap Mediator container
 DMAAP_MED_EXTERNAL_PORT=8085                             # Dmaap Mediator container external port (host -> container)
@@ -503,8 +534,10 @@ DMAAP_MED_COMPOSE_DIR="dmaapmed"                         # Dir in simulator_grou
 DMAAP_MED_DATA_MOUNT_PATH="/configs"                     # Path in container for data file
 DMAAP_MED_HOST_DATA_FILE="type_config_1.json"            # Host data file name
 DMAAP_MED_CONTR_DATA_FILE="type_config.json"             # Container data file name
-DMAAP_MED_FEATURE_LEVEL="KAFKATYPES"                     # Space separated list of features
+DMAAP_MED_FEATURE_LEVEL="KAFKATYPES FILTERSCHEMA"        # Space separated list of features
                                                          # KAFKATYPES support for kafka type from rel f
+                                                         # FILTERSCHEMA corrected kafka type schema from rel h
+
 KAFKAPC_APP_NAME="kafka-procon"                          # Name for the Kafka procon
 KAFKAPC_DISPLAY_NAME="Kafka Producer/Consumer"
 KAFKAPC_EXTERNAL_PORT=8096                               # Kafka procon container external port (host -> container)
index 3f5970c..336bd8f 100755 (executable)
@@ -2863,15 +2863,15 @@ clean_environment() {
        if [ $RUNMODE == "KUBE" ]; then
                __clean_kube
                if [ $PRE_CLEAN -eq 1 ]; then
-                       echo " Cleaning docker resouces to free up resources, may take time..."
-                       ../common/clean_docker.sh 2>&1 > /dev/null
+                       echo " Cleaning kubernetes resources to free up resources, may take time..."
+                       ../common/clean_kube.sh $KUBECONF 2>&1 > /dev/null
                        echo ""
                fi
        else
                __clean_containers
                if [ $PRE_CLEAN -eq 1 ]; then
-                       echo " Cleaning kubernetes resouces to free up resources, may take time..."
-                       ../common/clean_kube.sh $KUBECONF 2>&1 > /dev/null
+                       echo " Cleaning docker resources to free up resources, may take time..."
+                       ../common/clean_docker.sh 2>&1 > /dev/null
                        echo ""
                fi
        fi
@@ -3055,7 +3055,7 @@ __check_service_start() {
                                #If response is too long, truncate
                                result="...response text too long, omitted"
                        fi
-                       echo -ne " Waiting for {ENTITY} $BOLD${appname}$EBOLD service status on ${3}, result: $result${SAMELINE}"
+                       echo -ne " Waiting for ${ENTITY} $BOLD${appname}$EBOLD service status on ${url}, result: $result${SAMELINE}"
                        echo -ne " The ${ENTITY} $BOLD${appname}$EBOLD$GREEN is alive$EGREEN, responds to service status:$GREEN $result $EGREEN on ${url} after $(($SECONDS-$TSTART)) seconds"
                        a1pmsst=true
                        break
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 4117cdb..5728510
@@ -94,8 +94,8 @@ suite_complete() {
 
     total=$((TCSUITE_PASS_CTR+TCSUITE_FAIL_CTR))
     if [ $TCSUITE_CTR -eq 0 ]; then
-               echo -e "\033[1mNo test cases seem to have executed. Check the script....\033[0m"
-       elif [ $total != $TCSUITE_CTR ]; then
+                   echo -e "\033[1mNo test cases seem to have executed. Check the script....\033[0m"
+         elif [ $total != $TCSUITE_CTR ]; then
         echo -e "\033[1mTotal number of test cases does not match the sum of passed and failed test cases. Check the script....\033[0m"
     fi
     echo "Number of test cases : " $TCSUITE_CTR
@@ -108,7 +108,13 @@ suite_complete() {
     echo "FAIL test cases"
     cat .tmp_tcsuite_fail
     echo ""
+    if [ $TCSUITE_FAIL_CTR -ne 0 ]; then
+      echo "###################################      Test suite completed with Tests FAIL     ##############################"
+      echo "#################################################################################################"
+    else
+      echo "###################################      Test suite completed      ##############################"
+      echo "#################################################################################################"
+    fi
 
-    echo "###################################      Test suite completed      ##############################"
-    echo "#################################################################################################"
+    exit $TCSUITE_FAIL_CTR
 }
\ No newline at end of file
diff --git a/test/common/update_policies_process.py b/test/common/update_policies_process.py
new file mode 100644 (file)
index 0000000..11767a8
--- /dev/null
@@ -0,0 +1,127 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2024 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=================================================
+#
+
+# This script create/update policies spread over a number rics
+# Intended for parallel processing
+# Returns a string with result, either "0" for ok, or "1<fault description>"
+
+import json
+import sys
+import requests
+import traceback
+from time import sleep
+
+# disable warning about unverified https requests
+from requests.packages import urllib3
+
+urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+
+#arg responsecode baseurl ric_base num_rics uuid startid service type transient notification-url templatepath count pids pid_id proxy policy-ids-file-path
+data_out=""
+url_out=""
+try:
+
+    if len(sys.argv) != 17:
+        print("1Expected 16 args, got "+str(len(sys.argv)-1)+ ". Args: responsecode baseurl ric_base num_rics uuid startid service type transient notification-url templatepath count pids pid_id proxy policy-ids-file-path")
+        print (sys.argv[1:])
+        sys.exit()
+    responsecode=int(sys.argv[1])
+    baseurl=str(sys.argv[2])
+    ric_base=str(sys.argv[3])
+    num_rics=int(sys.argv[4])
+    uuid=str(sys.argv[5])
+    start=int(sys.argv[6])
+    serv=str(sys.argv[7])
+    pt=str(sys.argv[8])
+    trans=str(sys.argv[9])
+    noti=str(sys.argv[10])
+    templatepath=str(sys.argv[11])
+    count=int(sys.argv[12])
+    pids=int(sys.argv[13])
+    pid_id=int(sys.argv[14])
+    httpproxy=str(sys.argv[15])
+    policy_ids_file_path=str(sys.argv[16])
+
+    proxydict=None
+    if httpproxy != "NOPROXY":
+        proxydict = {
+            "http" : httpproxy,
+            "https" : httpproxy
+        }
+    if uuid == "NOUUID":
+        uuid=""
+
+    with open(templatepath, 'r') as file:
+        template = file.read()
+
+        start=start
+        stop=count*num_rics+start
+
+        http_retry_count=0
+        connect_retry_count=0
+
+        with open(str(policy_ids_file_path)) as file:
+            for policyId in file:
+                if start%pids == (pid_id-1):
+                    payload=template.replace("XXX",str(start))
+                    connect_ok=False
+                    retry_cnt=5
+                    while(retry_cnt>0):
+                        try:
+                            headers = {'Content-type': 'application/json'}
+                            url=baseurl+"/"+str(policyId.strip())
+                            url_out=url
+                            if proxydict is None:
+                                resp=requests.put(url, payload, headers=headers, verify=False, timeout=90)
+                            else:
+                                resp=requests.put(url, payload, headers=headers, verify=False, timeout=90, proxies=proxydict)
+                            connect_ok=True
+                        except Exception as e1:
+                            if (retry_cnt > 1):
+                                sleep(0.1)
+                                retry_cnt -= 1
+                                connect_retry_count += 1
+                            else:
+                                print("1Put failed for id:"+policyId.strip()+ ", "+str(e1) + " "+traceback.format_exc())
+                                sys.exit()
+
+                        if (connect_ok == True):
+                            if (resp.status_code == None):
+                                print("1Put failed for id:"+policyId.strip()+ ", expected response code: "+str(responsecode)+", got: None")
+                                sys.exit()
+
+                            if (resp.status_code != responsecode):
+                                if (resp.status_code >= 500) and (http_retry_count < 600 ) and (retry_cnt > 1):
+                                    sleep(0.1)
+                                    retry_cnt -= 1
+                                    http_retry_count += 1
+                                else:
+                                    print("1Put failed for id:"+policyId.strip()+ ", expected response code: "+str(responsecode)+", got: "+str(resp.status_code))
+                                    print(url_out)
+                                    print(json.loads(payload))
+                                    sys.exit()
+                            else:
+                                retry_cnt=-1
+                start  += 1
+    print("0 http retries:"+str(http_retry_count) + ", connect retries: "+str(connect_retry_count))
+    sys.exit()
+
+except Exception as e:
+    print("1"+str(e))
+    traceback.print_exc()
+    print(str(data_out))
+sys.exit()
\ No newline at end of file
diff --git a/test/servicestub/hello-world-chart/templates/_helpers.tpl b/test/servicestub/hello-world-chart/templates/_helpers.tpl
deleted file mode 100644 (file)
index 5759827..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-{{/*
-Expand the name of the chart.
-*/}}
-{{- define "hello-world-chart.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 "hello-world-chart.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 "hello-world-chart.chart" -}}
-{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
-{{- end }}
-
-{{/*
-Common labels
-*/}}
-{{- define "hello-world-chart.labels" -}}
-helm.sh/chart: {{ include "hello-world-chart.chart" . }}
-{{ include "hello-world-chart.selectorLabels" . }}
-{{- if .Chart.AppVersion }}
-app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
-{{- end }}
-app.kubernetes.io/managed-by: {{ .Release.Service }}
-{{- end }}
-
-{{/*
-Selector labels
-*/}}
-{{- define "hello-world-chart.selectorLabels" -}}
-app.kubernetes.io/name: {{ include "hello-world-chart.name" . }}
-app.kubernetes.io/instance: {{ .Release.Name }}
-{{- end }}
-
-{{/*
-Create the name of the service account to use
-*/}}
-{{- define "hello-world-chart.serviceAccountName" -}}
-{{- if .Values.serviceAccount.create }}
-{{- default (include "hello-world-chart.fullname" .) .Values.serviceAccount.name }}
-{{- else }}
-{{- default "default" .Values.serviceAccount.name }}
-{{- end }}
-{{- end }}
diff --git a/test/servicestub/src/test/java/org/oran/helloworld/rest/HelloWorldControllerTest.java b/test/servicestub/src/test/java/org/oran/helloworld/rest/HelloWorldControllerTest.java
deleted file mode 100644 (file)
index 0d29c8b..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*-\r
- * ========================LICENSE_START=================================\r
- * O-RAN-SC\r
- * %%\r
- * Copyright (C) 2023 OpenInfra Foundation Europe.\r
- * %%\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * ========================LICENSE_END===================================\r
- */\r
-\r
-package org.oran.helloworld.rest;\r
-\r
-import org.junit.jupiter.api.Test;\r
-import org.springframework.beans.factory.annotation.Autowired;\r
-import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;\r
-import org.springframework.boot.test.mock.mockito.MockBean;\r
-import org.springframework.test.web.servlet.MockMvc;\r
-\r
-import static org.mockito.Mockito.when;\r
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;\r
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;\r
-\r
-@WebMvcTest(HelloWorldController.class)\r
-public class HelloWorldControllerTest {\r
-\r
-    @Autowired\r
-    private MockMvc mockMvc;\r
-\r
-    @MockBean\r
-    private HelloWorldController helloWorldController;\r
-\r
-    @Test\r
-    public void testHelloWorldEndpoint() throws Exception {\r
-        when(helloWorldController.helloWorld()).thenReturn("Hello World from service stub\n");\r
-\r
-        mockMvc.perform(get("/helloworld"))\r
-            .andExpect(status().isOk())\r
-            .andExpect(content().string("Hello World from service stub\n"));\r
-    }\r
-\r
-    @Test\r
-    public void testHelloWorldSmeEndpoint() throws Exception {\r
-        when(helloWorldController.helloWorldSme()).thenReturn("Hello World from SME\n");\r
-\r
-        mockMvc.perform(get("/helloworld/sme"))\r
-            .andExpect(status().isOk())\r
-            .andExpect(content().string("Hello World from SME\n"));\r
-    }\r
-}\r