Add A1 PMS participant 49/132449/4
authoraravind.est <aravindhan.a@est.tech>
Mon, 21 Nov 2022 15:26:58 +0000 (15:26 +0000)
committeraravind.est <aravindhan.a@est.tech>
Mon, 28 Nov 2022 14:44:15 +0000 (14:44 +0000)
Issue-ID: CCSDK-3816
Signed-off-by: aravind.est <aravindhan.a@est.tech>
Change-Id: I00c04542f5ec4672b1c3a29ca32477bf5d2ca336

32 files changed:
examples/src/main/resources/clamp/acm/test/participant-a1pms.yaml [new file with mode: 0755]
packages/policy-clamp-docker/pom.xml
packages/policy-clamp-docker/src/main/docker/A1pmsParticipant-Suse.Dockerfile [new file with mode: 0755]
packages/policy-clamp-docker/src/main/docker/A1pmsParticipant.Dockerfile [new file with mode: 0755]
packages/policy-clamp-docker/src/main/docker/a1pms-participant.sh [new file with mode: 0755]
packages/policy-clamp-tarball/pom.xml
packages/policy-clamp-tarball/src/main/resources/etc/A1pmsParticipantParameters.yaml [new file with mode: 0755]
packages/pom.xml
participant/participant-impl/participant-impl-a1pms/pom.xml [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/Application.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/config/MicrometerConfig.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/config/ParticipantConfig.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/config/SecurityConfig.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/exception/A1PolicyServiceException.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/handler/AutomationCompositionElementHandler.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/models/A1PolicyServiceEntity.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/models/ConfigurationEntity.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/parameters/A1PmsParameters.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/parameters/A1PmsParticipantParameters.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/webclient/AcA1PmsClient.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/main/resources/config/application.yaml [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/handler/AcElementHandlerTest.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/rest/ActuatorControllerTest.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/CommonActuatorController.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/CommonTestData.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/MockRestEndpoint.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/MockServerRest.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/ToscaUtils.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/webclient/AcA1PmsClientTest.java [new file with mode: 0755]
participant/participant-impl/participant-impl-a1pms/src/test/resources/application-test.yaml [new file with mode: 0755]
participant/participant-impl/pom.xml
pom.xml

diff --git a/examples/src/main/resources/clamp/acm/test/participant-a1pms.yaml b/examples/src/main/resources/clamp/acm/test/participant-a1pms.yaml
new file mode 100755 (executable)
index 0000000..9e3f20c
--- /dev/null
@@ -0,0 +1,146 @@
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+tosca_definitions_version: tosca_simple_yaml_1_3
+data_types:
+  onap.datatypes.ToscaConceptIdentifier:
+    derived_from: tosca.datatypes.Root
+    properties:
+      name:
+        type: string
+        required: true
+      version:
+        type: string
+        required: true
+  org.onap.datatypes.policy.clamp.acm.a1PmsAutomationCompositionElement.A1PolicyServiceEntity:
+    version: 1.0.0
+    derived_from: tosca.datatypes.Root
+    properties:
+      a1PolicyServiceEntityId:
+        type: onap.datatypes.ToscaConceptIdentifier
+        type_version: 0.0.0
+        required: true
+        description: The name and version of a Configuration Entity to be handled by the A1 PMS Automation Composition Element
+      clientId:
+        type: string
+        required: true
+        description: Client Id to be created
+      callbackUrl:
+        type: string
+        required: true
+        description: The callback URL to get registered
+      keepAliveIntervalSeconds:
+        type: integer
+        required: true
+        description: Keep alive interval time for the callback URL
+
+node_types:
+  org.onap.policy.clamp.acm.Participant:
+    version: 1.0.1
+    derived_from: tosca.nodetypes.Root
+    properties:
+      provider:
+        type: string
+        required: false
+  org.onap.policy.clamp.acm.AutomationCompositionElement:
+    version: 1.0.1
+    derived_from: tosca.nodetypes.Root
+    properties:
+      provider:
+        type: string
+        required: false
+      participantType:
+        type: onap.datatypes.ToscaConceptIdentifier
+        required: true
+      startPhase:
+        type: integer
+        required: false
+        constraints:
+        - greater-or-equal: 0
+        metadata:
+            common: true
+        description: A value indicating the start phase in which this automation composition element will be started, the
+                     first start phase is zero. Automation Composition Elements are started in their start_phase order and stopped
+                     in reverse start phase order. Automation Composition Elements with the same start phase are started and
+                     stopped simultaneously
+  org.onap.policy.clamp.acm.AutomationComposition:
+    version: 1.0.1
+    derived_from: tosca.nodetypes.Root
+    properties:
+      provider:
+        type: string
+        required: false
+      elements:
+        type: list
+        required: true
+        entry_schema:
+          type: onap.datatypes.ToscaConceptIdentifier
+  org.onap.policy.clamp.acm.A1PMSAutomationCompositionElement:
+    version: 1.0.1
+    derived_from: org.onap.policy.clamp.acm.AutomationCompositionElement
+    properties:
+      policyServiceEntities:
+        type: list
+        required: true
+        entry_schema:
+          type: org.onap.datatypes.policy.clamp.acm.a1pmsAutomationCompositionElement.A1PolicyServiceEntity
+          type_version: 1.0.0
+        description: The configuration entities of A1 policy services
+topology_template:
+  node_templates:
+    org.onap.k8s.acm.A1PMSAutomationCompositionParticipant:
+      version: 2.3.4
+      type: org.onap.policy.clamp.acm.Participant
+      type_version: 1.0.1
+      description: Participant for A1 PMS requests
+      properties:
+        provider: ONAP
+
+    org.onap.domain.database.A1PMSAutomationCompositionElement:
+      version: 1.2.3
+      type: org.onap.policy.clamp.acm.A1PMSAutomationCompositionElement
+      type_version: 1.0.1
+      description: Automation composition element for the A1 PMS Requests
+      properties:
+        provider: ONAP
+        participantType:
+          name: org.onap.policy.clamp.acm.A1PMSParticipant
+          version: 2.3.4
+        policyServiceEntities:
+          - a1PolicyServiceEntityId:
+              name: entity1
+              version: 1.0.1
+            clientId: firstService
+            callbackUrl: http://localhost
+            keepAliveIntervalSeconds: 0
+          - a1PolicyServiceEntityId:
+              name: entity2
+              version: 1.0.1
+            clientId: secondService
+            callbackUrl: http://127.0.0.1
+            keepAliveIntervalSeconds: 0
+
+    org.onap.domain.sample.A1PMSAutomationCompositionDefinition:
+      version: 1.2.3
+      type: org.onap.policy.clamp.acm.AutomationComposition
+      type_version: 1.0.0
+      description: Automation composition for A1PMS request
+      properties:
+        provider: ONAP
+        elements:
+          - name: org.onap.domain.database.A1PMSAutomationCompositionElement
+            version: 1.2.3
index 57fe51b..f4e863d 100644 (file)
@@ -51,6 +51,8 @@
         <docker.clamp-ac-k8s-ppnt.contextDir>${project.basedir}/src/main/docker</docker.clamp-ac-k8s-ppnt.contextDir>
         <docker.clamp-ac-http-ppnt.dockerFile>HttpParticipant.Dockerfile</docker.clamp-ac-http-ppnt.dockerFile>
         <docker.clamp-ac-http-ppnt.contextDir>${project.basedir}/src/main/docker</docker.clamp-ac-http-ppnt.contextDir>
+        <docker.clamp-ac-a1pms-ppnt.dockerFile>A1pmsParticipant.Dockerfile</docker.clamp-ac-a1pms-ppnt.dockerFile>
+        <docker.clamp-ac-a1pms-ppnt.contextDir>${project.basedir}/src/main/docker</docker.clamp-ac-a1pms-ppnt.contextDir>
         <docker.clamp-acm-element-impl.dockerFile>ElementParticipant.Dockerfile</docker.clamp-acm-element-impl.dockerFile>
         <docker.clamp-acm-element-impl.contextDir>${project.basedir}/src/main/docker</docker.clamp-acm-element-impl.contextDir>
         <maven.build.timestamp.format>yyyyMMdd'T'HHmm</maven.build.timestamp.format>
             <artifactId>policy-clamp-participant-impl-http</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.onap.policy.clamp.participant</groupId>
+            <artifactId>policy-clamp-participant-impl-a1pms</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.onap.policy.clamp.participant</groupId>
             <artifactId>policy-clamp-acm-element-impl</artifactId>
                                 </assembly>
                             </build>
                         </image>
+                        <image>
+                            <name>onap/policy-clamp-ac-a1pms-ppnt</name>
+                            <alias>onap-policy-clamp-ac-a1pms-ppnt</alias>
+                            <build>
+                                <cleanup>try</cleanup>
+                                <dockerFile>${docker.clamp-ac-a1pms-ppnt.dockerFile}</dockerFile>
+                                <contextDir>${docker.clamp-ac-a1pms-ppnt.contextDir}</contextDir>
+                                <tags>
+                                    <tag>${project.version}</tag>
+                                    <tag>${project.version}-${maven.build.timestamp}</tag>
+                                    <tag>${project.docker.latest.minmax.tag.version}</tag>
+                                </tags>
+                                <assembly>
+                                    <inline>
+                                        <dependencySets>
+                                            <dependencySet>
+                                                <includes>
+                                                    <include>org.onap.policy.clamp:policy-clamp-tarball</include>
+                                                </includes>
+                                                <outputDirectory>/lib</outputDirectory>
+                                                <outputFileNameMapping>a1pms-participant.tar.gz</outputFileNameMapping>
+                                            </dependencySet>
+                                            <dependencySet>
+                                                <includes>
+                                                    <include>org.onap.policy.clamp.participant:policy-clamp-participant-impl-a1pms</include>
+                                                </includes>
+                                                <outputFileNameMapping>policy-clamp-participant-impl-a1pms.jar</outputFileNameMapping>
+                                            </dependencySet>
+                                        </dependencySets>
+                                    </inline>
+                                </assembly>
+                            </build>
+                        </image>
                         <image>
                             <name>onap/policy-clamp-acm-element-impl</name>
                             <alias>onap-policy-clamp-acm-element-impl</alias>
diff --git a/packages/policy-clamp-docker/src/main/docker/A1pmsParticipant-Suse.Dockerfile b/packages/policy-clamp-docker/src/main/docker/A1pmsParticipant-Suse.Dockerfile
new file mode 100755 (executable)
index 0000000..33d66da
--- /dev/null
@@ -0,0 +1,64 @@
+#-------------------------------------------------------------------------------
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2022 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#-------------------------------------------------------------------------------
+
+FROM busybox AS tarball
+RUN mkdir /packages /extracted
+COPY /maven/lib/a1pms-participant.tar.gz /packages/
+RUN tar xvzf /packages/a1pms-participant.tar.gz --directory /extracted/
+
+FROM opensuse/leap:15.4
+
+LABEL maintainer="Policy Team"
+LABEL org.opencontainers.image.title="Policy CLAMP ACM A1 PMS Participant"
+LABEL org.opencontainers.image.description="Policy CLAMP ACM A1 PMS Participant image based on OpenSuse"
+LABEL org.opencontainers.image.url="https://github.com/onap/policy-clamp"
+LABEL org.opencontainers.image.vendor="ONAP Policy Team"
+LABEL org.opencontainers.image.licenses="Apache-2.0"
+LABEL org.opencontainers.image.created="${git.build.time}"
+LABEL org.opencontainers.image.version="${git.build.version}"
+LABEL org.opencontainers.image.revision="${git.commit.id.abbrev}"
+
+ARG POLICY_LOGS=/var/log/onap/policy/a1pms-participant
+
+ENV POLICY_LOGS=$POLICY_LOGS
+ENV POLICY_HOME=/opt/app/policy/clamp
+ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
+ENV JAVA_HOME=/usr/lib64/jvm/java-11-openjdk-11
+
+RUN zypper -n -q install --no-recommends java-11-openjdk-headless netcat-openbsd && \
+    zypper -n -q update && zypper -n -q clean --all && \
+    groupadd --system policy && \
+    useradd --system --shell /bin/sh -G policy policy && \
+    mkdir -p $POLICY_HOME $POLICY_LOGS && \
+    chown -R policy:policy $POLICY_HOME $POLICY_LOGS
+
+COPY --chown=policy:policy --from=tarball /extracted $POLICY_HOME
+
+WORKDIR $POLICY_HOME
+COPY --chown=policy:policy a1pms-participant.sh bin/
+COPY --chown=policy:policy /maven/policy-clamp-participant-impl-a1.jar /app/app.jar
+
+RUN chmod 755 bin/*.sh
+
+EXPOSE 8086
+
+USER policy
+WORKDIR $POLICY_HOME/bin
+ENTRYPOINT [ "./a1pms-participant.sh" ]
diff --git a/packages/policy-clamp-docker/src/main/docker/A1pmsParticipant.Dockerfile b/packages/policy-clamp-docker/src/main/docker/A1pmsParticipant.Dockerfile
new file mode 100755 (executable)
index 0000000..fc2ef78
--- /dev/null
@@ -0,0 +1,58 @@
+#-------------------------------------------------------------------------------
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2021-2022 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#-------------------------------------------------------------------------------
+
+FROM busybox AS tarball
+RUN mkdir /packages /extracted
+COPY /maven/lib/a1pms-participant.tar.gz /packages/
+RUN tar xvzf /packages/a1pms-participant.tar.gz --directory /extracted/
+
+FROM onap/policy-jre-alpine:2.6.0-SNAPSHOT
+
+LABEL maintainer="Policy Team"
+LABEL org.opencontainers.image.title="Policy CLAMP ACM A1 PMS Participant"
+LABEL org.opencontainers.image.description="Policy CLAMP ACM A1 PMS Participant image based on Alpine"
+LABEL org.opencontainers.image.url="https://github.com/onap/policy-clamp"
+LABEL org.opencontainers.image.vendor="ONAP Policy Team"
+LABEL org.opencontainers.image.licenses="Apache-2.0"
+LABEL org.opencontainers.image.created="${git.build.time}"
+LABEL org.opencontainers.image.version="${git.build.version}"
+LABEL org.opencontainers.image.revision="${git.commit.id.abbrev}"
+
+ARG POLICY_LOGS=/var/log/onap/policy/a1pms-participant
+
+ENV POLICY_LOGS=$POLICY_LOGS
+ENV POLICY_HOME=$POLICY_HOME/clamp
+
+RUN mkdir -p $POLICY_LOGS $POLICY_HOME && \
+    chown -R policy:policy $POLICY_HOME $POLICY_LOGS
+
+COPY --chown=policy:policy --from=tarball /extracted $POLICY_HOME
+
+WORKDIR $POLICY_HOME
+COPY --chown=policy:policy a1pms-participant.sh bin/
+COPY --chown=policy:policy /maven/policy-clamp-participant-impl-a1pms.jar /app/app.jar
+
+RUN chmod 755 bin/*.sh
+
+EXPOSE 8086
+
+USER policy
+WORKDIR $POLICY_HOME/bin
+ENTRYPOINT [ "./a1pms-participant.sh" ]
diff --git a/packages/policy-clamp-docker/src/main/docker/a1pms-participant.sh b/packages/policy-clamp-docker/src/main/docker/a1pms-participant.sh
new file mode 100755 (executable)
index 0000000..72aae5e
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/env sh
+#
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2021-2022 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+
+KEYSTORE="${KEYSTORE:-$POLICY_HOME/etc/ssl/policy-keystore}"
+TRUSTSTORE="${TRUSTSTORE:-$POLICY_HOME/etc/ssl/policy-truststore}"
+KEYSTORE_PASSWD="${KEYSTORE_PASSWD:-Pol1cy_0nap}"
+TRUSTSTORE_PASSWD="${TRUSTSTORE_PASSWD:-Pol1cy_0nap}"
+
+if [ "$#" -eq 1 ]; then
+    CONFIG_FILE=$1
+fi
+
+if [ -z "$CONFIG_FILE" ]; then
+    CONFIG_FILE="${POLICY_HOME}/etc/A1pmsParticipantParameters.yaml"
+fi
+
+echo "Policy clamp A1 Pms participant config file: $CONFIG_FILE"
+
+if [ -f "${POLICY_HOME}/etc/mounted/policy-truststore" ]; then
+    echo "overriding policy-truststore"
+    cp -f "${POLICY_HOME}"/etc/mounted/policy-truststore "${TRUSTSTORE}"
+fi
+
+if [ -f "${POLICY_HOME}/etc/mounted/policy-keystore" ]; then
+    echo "overriding policy-keystore"
+    cp -f "${POLICY_HOME}"/etc/mounted/policy-keystore "${KEYSTORE}"
+fi
+
+if [ -f "${POLICY_HOME}/etc/mounted/logback.xml" ]; then
+    echo "overriding logback xml file"
+    cp -f "${POLICY_HOME}"/etc/mounted/logback.xml "${POLICY_HOME}"/etc/
+fi
+
+$JAVA_HOME/bin/java \
+    -Dlogging.config="${POLICY_HOME}/etc/logback.xml" \
+    -Dserver.ssl.keyStore="${KEYSTORE}" \
+    -Dserver.ssl.keyStorePassword="${KEYSTORE_PASSWD}" \
+    -Djavax.net.ssl.trustStore="${TRUSTSTORE}" \
+    -Djavax.net.ssl.trustStorePassword="${TRUSTSTORE_PASSWD}" \
+    -jar /app/app.jar \
+    --spring.config.location="${CONFIG_FILE}"
index 1d3c67f..769813a 100644 (file)
             <artifactId>policy-clamp-participant-impl-http</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.onap.policy.clamp.participant</groupId>
+            <artifactId>policy-clamp-participant-impl-a1pms</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.onap.policy.clamp.participant</groupId>
             <artifactId>policy-clamp-acm-element-impl</artifactId>
diff --git a/packages/policy-clamp-tarball/src/main/resources/etc/A1pmsParticipantParameters.yaml b/packages/policy-clamp-tarball/src/main/resources/etc/A1pmsParticipantParameters.yaml
new file mode 100755 (executable)
index 0000000..54a5924
--- /dev/null
@@ -0,0 +1,57 @@
+spring:
+  security:
+    user:
+      name: participantUser
+      password: zb!XztG34
+  autoconfigure:
+    exclude:
+      - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
+      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
+      - org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
+      - org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration
+security:
+  enable-csrf: false
+
+a1pms:
+  baseUrl: http://a1policymanagement.onap:8081
+  headers:
+    content-type: application/json
+  endpoints:
+    health: /a1-policy/v2/rics
+    services: /a1-policy/v2/services
+    service: /a1-policy/v2/services/{service_id}
+
+participant:
+  intermediaryParameters:
+    reportingTimeIntervalMs: 120000
+    description: Participant Description
+    participantId:
+      name: A1PMSParticipant0
+      version: 1.0.0
+    participantType:
+      name: org.onap.policy.clamp.acm.A1PMSParticipant
+      version: 2.3.4
+    clampAutomationCompositionTopics:
+      topicSources:
+        - topic: POLICY-ACRUNTIME-PARTICIPANT
+          servers:
+            - ${topicServer:localhost}
+          topicCommInfrastructure: dmaap
+          fetchTimeout: 15000
+      topicSinks:
+        - topic: POLICY-ACRUNTIME-PARTICIPANT
+          servers:
+            - ${topicServer:localhost}
+          topicCommInfrastructure: dmaap
+
+
+management:
+  endpoints:
+    web:
+      base-path: /
+      exposure:
+        include: health, metrics, prometheus
+server:
+  port: 8086
+  servlet:
+    context-path: /onap/policy/clamp/acm/a1pmsparticipant
\ No newline at end of file
index 847b5bc..56f9974 100644 (file)
@@ -68,6 +68,7 @@
                 <docker.clamp-ac-pf-ppnt.dockerFile>PolicyParticipant-Suse.Dockerfile</docker.clamp-ac-pf-ppnt.dockerFile>
                 <docker.clamp-ac-k8s-ppnt.dockerFile>KubernetesParticipant-Suse.Dockerfile</docker.clamp-ac-k8s-ppnt.dockerFile>
                 <docker.clamp-ac-http-ppnt.dockerFile>HttpParticipant-Suse.Dockerfile</docker.clamp-ac-http-ppnt.dockerFile>
+                <docker.clamp-ac-a1pms-ppnt.dockerFile>A1pmsParticipant-Suse.Dockerfile</docker.clamp-ac-a1pms-ppnt.dockerFile>
                 <docker.clamp-acm-element-impl.dockerFile>ElementParticipant-Suse.Dockerfile</docker.clamp-acm-element-impl.dockerFile>
             </properties>
         </profile>
diff --git a/participant/participant-impl/participant-impl-a1pms/pom.xml b/participant/participant-impl/participant-impl-a1pms/pom.xml
new file mode 100755 (executable)
index 0000000..c8566a1
--- /dev/null
@@ -0,0 +1,50 @@
+<!--
+  ============LICENSE_START=======================================================
+  Copyright (C) 2022 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.
+
+  SPDX-License-Identifier: Apache-2.0
+  ============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.onap.policy.clamp.participant</groupId>
+        <artifactId>policy-clamp-participant-impl</artifactId>
+        <version>6.4.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>policy-clamp-participant-impl-a1pms</artifactId>
+    <name>${project.artifactId}</name>
+    <description>A1 PMS participant, that performs operations related to access the A1 Policy Management Service to perform A1 Policy Operations</description>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                        <phase>package</phase>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/Application.java b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/Application.java
new file mode 100755 (executable)
index 0000000..1adf5cd
--- /dev/null
@@ -0,0 +1,48 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
+import org.springframework.context.annotation.ComponentScan;
+
+/**
+ * Starter.
+ */
+// @formatter:off
+@SpringBootApplication
+@ComponentScan({
+    "org.onap.policy.clamp.acm.participant.a1pms",
+    "org.onap.policy.clamp.acm.participant.intermediary"
+})
+@ConfigurationPropertiesScan("org.onap.policy.clamp.acm.participant.a1pms.parameters")
+//@formatter:on
+public class Application {
+    /**
+     * Main class.
+     *
+     * @param args args
+     */
+    public static void main(String[] args) {
+        SpringApplication.run(Application.class, args);
+    }
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/config/MicrometerConfig.java b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/config/MicrometerConfig.java
new file mode 100755 (executable)
index 0000000..5e3441d
--- /dev/null
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.config;
+
+import io.micrometer.core.aop.TimedAspect;
+import io.micrometer.core.instrument.MeterRegistry;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MicrometerConfig {
+
+    /**
+     * Load up the metrics registry.
+     */
+    @Bean
+    public InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor,
+            MeterRegistry registry) {
+        return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, "");
+    }
+
+    @Bean
+    public TimedAspect timedAspect(MeterRegistry registry) {
+        return new TimedAspect(registry);
+    }
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/config/ParticipantConfig.java b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/config/ParticipantConfig.java
new file mode 100755 (executable)
index 0000000..7158b5d
--- /dev/null
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.config;
+
+import org.onap.policy.clamp.acm.participant.a1pms.handler.AutomationCompositionElementHandler;
+import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ParticipantConfig {
+
+    /**
+     * Register AutomationCompositionElementListener.
+     *
+     * @param intermediaryApi the ParticipantIntermediaryApi
+     * @param acElementHandler the AutomationComposition Element Handler
+     */
+    @Autowired
+    public void registerAutomationCompositionElementListener(ParticipantIntermediaryApi intermediaryApi,
+            AutomationCompositionElementHandler acElementHandler) {
+        intermediaryApi.registerAutomationCompositionElementListener(acElementHandler);
+        acElementHandler.setIntermediaryApi(intermediaryApi);
+    }
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/config/SecurityConfig.java b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/config/SecurityConfig.java
new file mode 100755 (executable)
index 0000000..fdbbc45
--- /dev/null
@@ -0,0 +1,45 @@
+/*-
+ * ========================LICENSE_START=================================
+ * Copyright (C) 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===================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+
+@Configuration
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+    @Value("${security.enable-csrf:true}")
+    private boolean csrfEnabled = true;
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        // @formatter:off
+        http.authorizeRequests()
+            .antMatchers().authenticated()
+            .anyRequest().authenticated()
+            .and().httpBasic();
+        // @formatter:on
+
+        if (!csrfEnabled) {
+            http.csrf().disable();
+        }
+    }
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/exception/A1PolicyServiceException.java b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/exception/A1PolicyServiceException.java
new file mode 100755 (executable)
index 0000000..3a7ac7d
--- /dev/null
@@ -0,0 +1,35 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.exception;
+
+import javax.ws.rs.core.Response;
+import org.onap.policy.models.base.PfModelException;
+
+public class A1PolicyServiceException extends PfModelException {
+
+    public A1PolicyServiceException(int statusCode, String message) {
+        super(Response.Status.fromStatusCode(statusCode), message);
+    }
+
+    public A1PolicyServiceException(int statusCode, String message, Exception e) {
+        super(Response.Status.fromStatusCode(statusCode), message, e);
+    }
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/handler/AutomationCompositionElementHandler.java b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/handler/AutomationCompositionElementHandler.java
new file mode 100755 (executable)
index 0000000..072d144
--- /dev/null
@@ -0,0 +1,156 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.handler;
+
+import java.lang.invoke.MethodHandles;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.ValidationException;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import org.apache.http.HttpStatus;
+import org.onap.policy.clamp.acm.participant.a1pms.exception.A1PolicyServiceException;
+import org.onap.policy.clamp.acm.participant.a1pms.models.ConfigurationEntity;
+import org.onap.policy.clamp.acm.participant.a1pms.webclient.AcA1PmsClient;
+import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener;
+import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionOrderedState;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionState;
+import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantMessageType;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+/**
+ * This class handles implementation of automationCompositionElement updates.
+ */
+@Component
+@RequiredArgsConstructor
+public class AutomationCompositionElementHandler implements AutomationCompositionElementListener {
+
+    private static final Coder CODER = new StandardCoder();
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    @Setter
+    private ParticipantIntermediaryApi intermediaryApi;
+
+    private final AcA1PmsClient acA1PmsClient;
+
+    // Map of acElement Id and A1PMS services
+    @Getter(AccessLevel.PACKAGE)
+    private final Map<UUID, ConfigurationEntity> configRequestMap = new HashMap<>();
+
+    /**
+     * Handle a automation composition element state change.
+     *
+     * @param automationCompositionElementId the ID of the automation composition element
+     * @param currentState                   the current state of the automation composition element
+     * @param newState                       the state to which the automation composition element is changing to
+     * @throws PfModelException in case of a model exception
+     */
+    @Override
+    public void automationCompositionElementStateChange(ToscaConceptIdentifier automationCompositionId,
+            UUID automationCompositionElementId, AutomationCompositionState currentState,
+            AutomationCompositionOrderedState newState) throws A1PolicyServiceException {
+        switch (newState) {
+            case UNINITIALISED:
+                ConfigurationEntity configurationEntity = configRequestMap.get(automationCompositionElementId);
+                if (configurationEntity != null && acA1PmsClient.isPmsHealthy()) {
+                    acA1PmsClient.deleteService(configurationEntity.getPolicyServiceEntities());
+                    configRequestMap.remove(automationCompositionElementId);
+                    intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
+                            automationCompositionElementId, newState, AutomationCompositionState.UNINITIALISED,
+                            ParticipantMessageType.AUTOMATION_COMPOSITION_STATE_CHANGE);
+                } else {
+                    LOGGER.warn("Failed to connect with A1PMS. Service configuration is: {}", configurationEntity);
+                    throw new A1PolicyServiceException(HttpStatus.SC_SERVICE_UNAVAILABLE,
+                            "Unable to connect with A1PMS");
+                }
+                break;
+            case PASSIVE:
+                intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
+                        automationCompositionElementId, newState, AutomationCompositionState.PASSIVE,
+                        ParticipantMessageType.AUTOMATION_COMPOSITION_STATE_CHANGE);
+                break;
+            case RUNNING:
+                intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
+                        automationCompositionElementId, newState, AutomationCompositionState.RUNNING,
+                        ParticipantMessageType.AUTOMATION_COMPOSITION_STATE_CHANGE);
+                break;
+            default:
+                LOGGER.warn("Cannot transition from state {} to state {}", currentState, newState);
+                break;
+        }
+    }
+
+    /**
+     * Callback method to handle an update on an automation composition element.
+     *
+     * @param element      the information on the automation composition element
+     * @param nodeTemplate toscaNodeTemplate
+     */
+    @Override
+    public void automationCompositionElementUpdate(ToscaConceptIdentifier automationCompositionId,
+            AutomationCompositionElement element, ToscaNodeTemplate nodeTemplate) throws A1PolicyServiceException {
+        try {
+            var configurationEntity = CODER.convert(nodeTemplate.getProperties(), ConfigurationEntity.class);
+            Set<ConstraintViolation<ConfigurationEntity>> violations =
+                    Validation.buildDefaultValidatorFactory().getValidator().validate(configurationEntity);
+            if (violations.isEmpty()) {
+                if (acA1PmsClient.isPmsHealthy()) {
+                    acA1PmsClient.createService(configurationEntity.getPolicyServiceEntities());
+                    configRequestMap.put(element.getId(), configurationEntity);
+
+                    intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
+                            AutomationCompositionOrderedState.PASSIVE, AutomationCompositionState.PASSIVE,
+                            ParticipantMessageType.AUTOMATION_COMPOSITION_STATE_CHANGE);
+                } else {
+                    LOGGER.error("Failed to connect with A1PMS");
+                    throw new A1PolicyServiceException(HttpStatus.SC_SERVICE_UNAVAILABLE,
+                            "Unable to connect with A1PMS");
+                }
+            } else {
+                LOGGER.error("Violations found in the config request parameters: {}", violations);
+                throw new ValidationException("Constraint violations in the config request");
+            }
+        } catch (ValidationException | CoderException e) {
+            LOGGER.error("Error invoking the A1PMS request for the config ", e);
+            throw new A1PolicyServiceException(HttpStatus.SC_BAD_REQUEST, "Invalid Configuration", e);
+        } catch (A1PolicyServiceException e) {
+            LOGGER.error("Error invoking the A1PMS request for the config ", e);
+            throw e;
+        }
+    }
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/models/A1PolicyServiceEntity.java b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/models/A1PolicyServiceEntity.java
new file mode 100755 (executable)
index 0000000..991cb92
--- /dev/null
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.models;
+
+import com.fasterxml.jackson.annotation.JsonGetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.databind.PropertyNamingStrategies;
+import com.fasterxml.jackson.databind.annotation.JsonNaming;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.DefaultValue;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.Getter;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+@Data
+@AllArgsConstructor
+@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
+public class A1PolicyServiceEntity {
+
+    @NotNull
+    @JsonIgnore
+    private ToscaConceptIdentifier a1PolicyServiceEntityId;
+
+    @NotNull
+    @Getter(onMethod_ = {@JsonGetter(value = "service_id")})
+    private String clientId;
+
+    @NotNull
+    private String callbackUrl;
+
+    @NotNull
+    @DefaultValue("0")
+    private int keepAliveIntervalSeconds;
+
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/models/ConfigurationEntity.java b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/models/ConfigurationEntity.java
new file mode 100755 (executable)
index 0000000..80715c2
--- /dev/null
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.models;
+
+import java.util.List;
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class ConfigurationEntity {
+
+    @NotNull
+    @Valid
+    private List<A1PolicyServiceEntity> policyServiceEntities;
+
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/parameters/A1PmsParameters.java b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/parameters/A1PmsParameters.java
new file mode 100755 (executable)
index 0000000..704ef41
--- /dev/null
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.parameters;
+
+import java.util.Map;
+import javax.validation.constraints.NotNull;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.validation.annotation.Validated;
+
+/**
+ * Class to hold all parameters needed for the A1PMS participant.
+ */
+@Validated
+@Data
+@ConfigurationProperties(prefix = "a1pms")
+public class A1PmsParameters {
+
+    @NotNull
+    private String baseUrl;
+
+    @NotNull
+    private Endpoints endpoints;
+
+    @NotNull
+    private Map<String, String> headers;
+
+    @Data
+    public static class Endpoints {
+
+        String health;
+
+        String services;
+
+        String service;
+    }
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/parameters/A1PmsParticipantParameters.java b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/parameters/A1PmsParticipantParameters.java
new file mode 100755 (executable)
index 0000000..b3e0360
--- /dev/null
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.parameters;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import lombok.Getter;
+import lombok.Setter;
+import org.onap.policy.clamp.acm.participant.intermediary.parameters.ParticipantIntermediaryParameters;
+import org.onap.policy.clamp.acm.participant.intermediary.parameters.ParticipantParameters;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.validation.annotation.Validated;
+
+/**
+ * Class to hold all parameters needed for the A1PMS participant.
+ */
+@Validated
+@Getter
+@Setter
+@ConfigurationProperties(prefix = "participant")
+public class A1PmsParticipantParameters implements ParticipantParameters {
+
+    @NotNull
+    @Valid
+    private ParticipantIntermediaryParameters intermediaryParameters;
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/webclient/AcA1PmsClient.java b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/webclient/AcA1PmsClient.java
new file mode 100755 (executable)
index 0000000..25fb67f
--- /dev/null
@@ -0,0 +1,129 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.webclient;
+
+import java.lang.invoke.MethodHandles;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Predicate;
+import lombok.RequiredArgsConstructor;
+import org.onap.policy.clamp.acm.participant.a1pms.exception.A1PolicyServiceException;
+import org.onap.policy.clamp.acm.participant.a1pms.models.A1PolicyServiceEntity;
+import org.onap.policy.clamp.acm.participant.a1pms.parameters.A1PmsParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+
+@Component
+@RequiredArgsConstructor
+public class AcA1PmsClient {
+
+    private final A1PmsParameters a1PmsParameters;
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    /**
+     * Get webclient for A1PMS.
+     *
+     * @return webClient
+     */
+    private WebClient getPmsClient() {
+        return WebClient.builder().baseUrl(a1PmsParameters.getBaseUrl())
+                       .defaultHeaders(httpHeaders -> httpHeaders.addAll(createHeaders())).build();
+    }
+
+    /**
+     * Get A1PMS health status.
+     *
+     * @return whether A1PMS is healthy
+     */
+    public boolean isPmsHealthy() {
+        return Objects.equals(Boolean.TRUE,
+                getPmsClient().method(HttpMethod.GET).uri(a1PmsParameters.getEndpoints().getHealth())
+                        .exchangeToMono(clientResponse -> Mono.just(clientResponse.statusCode().is2xxSuccessful()))
+                        .block());
+    }
+
+
+    /**
+     * Create service in A1PMS.
+     * @param policyServiceEntities List of service entities
+     * @throws A1PolicyServiceException Exception on creating service
+     */
+    public void createService(List<A1PolicyServiceEntity> policyServiceEntities) throws A1PolicyServiceException {
+        policyServiceEntities.forEach(
+                a1PolicyServiceEntity -> getPmsClient().method(HttpMethod.PUT)
+                                           .uri(a1PmsParameters.getEndpoints().getServices())
+                                           .bodyValue(a1PolicyServiceEntity).retrieve()
+                                           .onStatus(HttpStatus::isError,
+                                                   clientResponse -> Mono.error(new A1PolicyServiceException(
+                                                                   clientResponse.statusCode().value(),
+                                                                   "Error in creating policy service")))
+                                           .onStatus(Predicate.isEqual(HttpStatus.OK),
+                                                   clientResponse -> {
+                                                       LOGGER.warn("Client {} already exists and the configuration "
+                                                                           + "is updated",
+                                                               a1PolicyServiceEntity.getClientId());
+                                                       return Mono.empty();
+                                                   })
+                                           .toBodilessEntity()
+                                           .block());
+    }
+
+    /**
+     * Delete service in A1PMS.
+     * @param policyServiceEntities List of service entities
+     * @throws A1PolicyServiceException Exception on deleting service
+     */
+    public void deleteService(List<A1PolicyServiceEntity> policyServiceEntities) throws A1PolicyServiceException {
+        policyServiceEntities.forEach(
+                a1PolicyServiceEntity -> getPmsClient().method(HttpMethod.DELETE)
+                                             .uri(a1PmsParameters.getEndpoints().getService(),
+                                                     a1PolicyServiceEntity.getClientId())
+                                             .bodyValue(a1PolicyServiceEntity).retrieve()
+                                             .onStatus(HttpStatus::isError,
+                                                     clientResponse -> Mono.error(
+                                                             new A1PolicyServiceException(
+                                                                     clientResponse.statusCode().value(),
+                                                                     "Error in deleting policy service")))
+                                             .toBodilessEntity()
+                                             .block());
+    }
+
+    /**
+     * Prepare the Http headers to call A1PMS.
+     *
+     * @return httpHeaders
+     */
+    private HttpHeaders createHeaders() {
+        var headers = new HttpHeaders();
+        for (Map.Entry<String, String> entry : a1PmsParameters.getHeaders().entrySet()) {
+            headers.add(entry.getKey(), entry.getValue());
+        }
+        return headers;
+    }
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/main/resources/config/application.yaml b/participant/participant-impl/participant-impl-a1pms/src/main/resources/config/application.yaml
new file mode 100755 (executable)
index 0000000..fcc2057
--- /dev/null
@@ -0,0 +1,59 @@
+spring:
+  security:
+    user:
+      name: participantUser
+      password: zb!XztG34
+  autoconfigure:
+    exclude:
+      - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
+      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
+      - org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
+      - org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration
+security:
+  enable-csrf: false
+
+a1pms:
+  baseUrl: http://a1policymanagement.onap:8081
+  headers:
+    content-type: application/json
+  endpoints:
+    health: /a1-policy/v2/rics
+    services: /a1-policy/v2/services
+    service: /a1-policy/v2/services/{service_id}
+
+participant:
+  intermediaryParameters:
+    reportingTimeIntervalMs: 120000
+    description: Participant Description
+    participantId:
+      name: A1PMSParticipant0
+      version: 1.0.0
+    participantType:
+      name: org.onap.policy.clamp.acm.A1PMSParticipant
+      version: 2.3.4
+    clampAutomationCompositionTopics:
+      topicSources:
+        - topic: POLICY-ACRUNTIME-PARTICIPANT
+          servers:
+            - ${topicServer:localhost}
+          topicCommInfrastructure: dmaap
+          fetchTimeout: 15000
+      topicSinks:
+        - topic: POLICY-ACRUNTIME-PARTICIPANT
+          servers:
+            - ${topicServer:localhost}
+          topicCommInfrastructure: dmaap
+
+
+management:
+  endpoints:
+    web:
+      base-path: /
+      exposure:
+        include: health, metrics, prometheus
+server:
+  port: 8086
+  servlet:
+    context-path: /onap/policy/clamp/acm/a1pmsparticipant
+
+
diff --git a/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/handler/AcElementHandlerTest.java b/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/handler/AcElementHandlerTest.java
new file mode 100755 (executable)
index 0000000..690f5f2
--- /dev/null
@@ -0,0 +1,110 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.handler;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Map;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Spy;
+import org.onap.policy.clamp.acm.participant.a1pms.exception.A1PolicyServiceException;
+import org.onap.policy.clamp.acm.participant.a1pms.utils.CommonTestData;
+import org.onap.policy.clamp.acm.participant.a1pms.utils.ToscaUtils;
+import org.onap.policy.clamp.acm.participant.a1pms.webclient.AcA1PmsClient;
+import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionOrderedState;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionState;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+@ExtendWith(SpringExtension.class)
+class AcElementHandlerTest {
+
+    private final AcA1PmsClient acA1PmsClient = mock(AcA1PmsClient.class);
+
+    @InjectMocks
+    @Spy
+    private AutomationCompositionElementHandler automationCompositionElementHandler =
+        new AutomationCompositionElementHandler(acA1PmsClient);
+
+
+    private final CommonTestData commonTestData = new CommonTestData();
+
+    private static ToscaServiceTemplate serviceTemplate;
+    private static final String A1_AUTOMATION_COMPOSITION_ELEMENT =
+        "org.onap.domain.database.A1PMSAutomationCompositionElement";
+
+    @BeforeAll
+    static void init() {
+        serviceTemplate = ToscaUtils.readAutomationCompositionFromTosca();
+    }
+
+    @BeforeEach
+    void startMocks() throws A1PolicyServiceException {
+        automationCompositionElementHandler.setIntermediaryApi(mock(ParticipantIntermediaryApi.class));
+        when(acA1PmsClient.isPmsHealthy()).thenReturn(Boolean.TRUE);
+        doNothing().when(acA1PmsClient).createService(any());
+    }
+
+    @Test
+    void test_automationCompositionElementStateChange() throws A1PolicyServiceException {
+        var automationCompositionId = commonTestData.getAutomationCompositionId();
+        var element = commonTestData.getAutomationCompositionElement();
+        var automationCompositionElementId = element.getId();
+
+        Map<String, ToscaNodeTemplate> nodeTemplatesMap = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates();
+        automationCompositionElementHandler.automationCompositionElementUpdate(
+                commonTestData.getAutomationCompositionId(), element,
+                nodeTemplatesMap.get(A1_AUTOMATION_COMPOSITION_ELEMENT));
+
+        assertDoesNotThrow(() -> automationCompositionElementHandler.automationCompositionElementStateChange(
+            automationCompositionId, automationCompositionElementId, AutomationCompositionState.PASSIVE,
+            AutomationCompositionOrderedState.PASSIVE));
+
+        assertDoesNotThrow(() -> automationCompositionElementHandler.automationCompositionElementStateChange(
+            automationCompositionId, automationCompositionElementId, AutomationCompositionState.PASSIVE,
+            AutomationCompositionOrderedState.UNINITIALISED));
+
+        assertDoesNotThrow(() -> automationCompositionElementHandler.automationCompositionElementStateChange(
+            automationCompositionId, automationCompositionElementId, AutomationCompositionState.PASSIVE,
+            AutomationCompositionOrderedState.RUNNING));
+    }
+
+    @Test
+    void test_AutomationCompositionElementUpdate() {
+        AutomationCompositionElement element = commonTestData.getAutomationCompositionElement();
+
+        Map<String, ToscaNodeTemplate> nodeTemplatesMap = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates();
+        assertDoesNotThrow(() -> automationCompositionElementHandler.automationCompositionElementUpdate(
+            commonTestData.getAutomationCompositionId(), element,
+            nodeTemplatesMap.get(A1_AUTOMATION_COMPOSITION_ELEMENT)));
+    }
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/rest/ActuatorControllerTest.java b/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/rest/ActuatorControllerTest.java
new file mode 100755 (executable)
index 0000000..831dc5e
--- /dev/null
@@ -0,0 +1,92 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.rest;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.core.Response;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.onap.policy.clamp.acm.participant.a1pms.utils.CommonActuatorController;
+import org.springframework.boot.test.autoconfigure.actuate.metrics.AutoConfigureMetrics;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+@AutoConfigureMetrics
+@ExtendWith(SpringExtension.class)
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
+@ActiveProfiles("test")
+class ActuatorControllerTest extends CommonActuatorController {
+
+    private static final String HEALTH_ENDPOINT = "health";
+    private static final String METRICS_ENDPOINT = "metrics";
+    private static final String PROMETHEUS_ENDPOINT = "prometheus";
+
+    @LocalServerPort
+    private int randomServerPort;
+
+    @BeforeEach
+    public void setUpPort() {
+        super.setHttpPrefix(randomServerPort);
+    }
+
+    @Test
+    void testGetHealth_Unauthorized() {
+        assertUnauthorizedActGet(HEALTH_ENDPOINT);
+    }
+
+    @Test
+    void testGetMetrics_Unauthorized() {
+        assertUnauthorizedActGet(METRICS_ENDPOINT);
+    }
+
+    @Test
+    void testGetPrometheus_Unauthorized() {
+        assertUnauthorizedActGet(PROMETHEUS_ENDPOINT);
+    }
+
+    @Test
+    void testGetHealth() {
+        Invocation.Builder invocationBuilder = super.sendActRequest(HEALTH_ENDPOINT);
+        Response rawresp = invocationBuilder.buildGet().invoke();
+        assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
+    }
+
+    @Test
+    void testGetMetrics() {
+        Invocation.Builder invocationBuilder = super.sendActRequest(METRICS_ENDPOINT);
+        Response rawresp = invocationBuilder.buildGet().invoke();
+        assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
+    }
+
+    @Test
+    void testGePrometheus() {
+        Invocation.Builder invocationBuilder = super.sendActRequest(PROMETHEUS_ENDPOINT);
+        Response rawresp = invocationBuilder.buildGet().invoke();
+        assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
+    }
+
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/CommonActuatorController.java b/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/CommonActuatorController.java
new file mode 100755 (executable)
index 0000000..fc00f66
--- /dev/null
@@ -0,0 +1,107 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.utils;
+
+import static org.junit.Assert.assertEquals;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.onap.policy.common.gson.GsonMessageBodyHandler;
+import org.onap.policy.common.utils.network.NetworkUtil;
+
+/**
+ * Class to perform Rest unit tests.
+ */
+public class CommonActuatorController {
+
+    public static final String SELF = NetworkUtil.getHostname();
+    public static final String CONTEXT_PATH = "onap/policy/clamp/acm/a1pmsparticipant/";
+
+    private static String httpPrefix;
+
+    /**
+     * Sends a request to an actuator endpoint.
+     *
+     * @param endpoint the target endpoint
+     * @return a request builder
+     */
+    protected Invocation.Builder sendActRequest(final String endpoint) {
+        return sendFqeRequest(httpPrefix + CONTEXT_PATH + endpoint, true);
+    }
+
+    /**
+     * Sends a request to an actuator endpoint, without any authorization header.
+     *
+     * @param endpoint the target endpoint
+     * @return a request builder
+     */
+    protected Invocation.Builder sendNoAuthActRequest(final String endpoint) {
+        return sendFqeRequest(httpPrefix + CONTEXT_PATH + endpoint, false);
+    }
+
+    /**
+     * Sends a request to a fully qualified endpoint.
+     *
+     * @param fullyQualifiedEndpoint the fully qualified target endpoint
+     * @param includeAuth            if authorization header should be included
+     * @return a request builder
+     */
+    protected Invocation.Builder sendFqeRequest(final String fullyQualifiedEndpoint, boolean includeAuth) {
+        final Client client = ClientBuilder.newBuilder().build();
+
+        client.property(ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE, "true");
+        client.register(GsonMessageBodyHandler.class);
+
+        if (includeAuth) {
+            client.register(HttpAuthenticationFeature.basic("participantUser", "zb!XztG34"));
+        }
+
+        final WebTarget webTarget = client.target(fullyQualifiedEndpoint);
+
+        return webTarget.request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN);
+    }
+
+    /**
+     * Assert that GET call to actuator endpoint is Unauthorized.
+     *
+     * @param endPoint the endpoint
+     */
+    protected void assertUnauthorizedActGet(final String endPoint) {
+        Response rawresp = sendNoAuthActRequest(endPoint).buildGet().invoke();
+        assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus());
+    }
+
+    /**
+     * Set Up httpPrefix.
+     *
+     * @param port the port
+     */
+    protected void setHttpPrefix(int port) {
+        httpPrefix = "http://" + SELF + ":" + port + "/";
+    }
+
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/CommonTestData.java b/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/CommonTestData.java
new file mode 100755 (executable)
index 0000000..be573cb
--- /dev/null
@@ -0,0 +1,78 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 Nordix Foundation.
+ *  Modifications Copyright (C) 2022 AT&T Intellectual Property. 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.utils;
+
+import java.util.List;
+import java.util.UUID;
+import org.onap.policy.clamp.acm.participant.a1pms.models.A1PolicyServiceEntity;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionOrderedState;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+public class CommonTestData {
+
+    private static final String TEST_KEY_NAME = "org.onap.domain.database.A1PMSAutomationCompositionElement";
+
+    /**
+     * Get a automationComposition Element.
+     *
+     * @return automationCompositionElement object
+     */
+    public AutomationCompositionElement getAutomationCompositionElement() {
+        AutomationCompositionElement element = new AutomationCompositionElement();
+        element.setId(UUID.randomUUID());
+        element.setDefinition(new ToscaConceptIdentifier(TEST_KEY_NAME, "1.0.1"));
+        element.setOrderedState(AutomationCompositionOrderedState.PASSIVE);
+        return element;
+    }
+
+    /**
+     * Get automation composition id.
+     *
+     * @return ToscaConceptIdentifier automationCompositionId
+     */
+    public ToscaConceptIdentifier getAutomationCompositionId() {
+        return getAutomationCompositionId(0);
+    }
+
+    /**
+     * Get automation composition id.
+     * @param instanceNo Identifier instance no
+     * @return ToscaConceptIdentifier automationCompositionId
+     */
+    public ToscaConceptIdentifier getAutomationCompositionId(int instanceNo) {
+        return new ToscaConceptIdentifier("A1PMSInstance" + instanceNo, "1.0.0");
+    }
+
+
+    /**
+     * Get valid policy entities.
+     * @return List of policy entities
+     */
+    public List<A1PolicyServiceEntity> getValidPolicyEntities() {
+        A1PolicyServiceEntity a1PolicyServiceEntity1 = new A1PolicyServiceEntity(getAutomationCompositionId(0),
+                "testService1", "http://localhost", 0);
+        A1PolicyServiceEntity a1PolicyServiceEntity2 = new A1PolicyServiceEntity(getAutomationCompositionId(1),
+                "testService2", "http://127.0.0.1", 0);
+        return List.of(a1PolicyServiceEntity1, a1PolicyServiceEntity2);
+    }
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/MockRestEndpoint.java b/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/MockRestEndpoint.java
new file mode 100755 (executable)
index 0000000..9f8a281
--- /dev/null
@@ -0,0 +1,83 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.utils;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+
+/**
+ * The Class MockRestEndpoint creates rest server endpoints for simulating Rest calls.
+ */
+@Path("/")
+@Produces("application/json")
+public class MockRestEndpoint {
+
+    /**
+     * Get dummy health endpoint.
+     *
+     * @return the response
+     */
+    @Path("/healthy")
+    @GET
+    public Response getApplicationHealthy() {
+        return Response.status(200).entity("{}").build();
+    }
+
+    /**
+     * Get dummy health endpoint.
+     *
+     * @return the response
+     */
+    @Path("/unhealthy")
+    @GET
+    public Response getApplicationUnHealthy() {
+        return Response.status(500).entity("{}").build();
+    }
+
+    @Path("/services/success")
+    @PUT
+    public Response createServiceSuccess() {
+        return Response.status(200).entity("{}").build();
+    }
+
+    @Path("/services/failure")
+    @PUT
+    public Response createServiceFailure() {
+        return Response.status(500).entity("{}").build();
+    }
+
+    @Path("/service/success/{clientId}")
+    @DELETE
+    public Response deleteServiceSuccess(@PathParam("clientId") String clientId) {
+        return Response.status(204).entity("{}").build();
+    }
+
+    @Path("/service/failure/{clientId}")
+    @DELETE
+    public Response deleteServiceFailure(@PathParam("clientId") String clientId) {
+        return Response.status(500).entity("{}").build();
+    }
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/MockServerRest.java b/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/MockServerRest.java
new file mode 100755 (executable)
index 0000000..dc0ed4a
--- /dev/null
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.utils;
+
+import org.onap.policy.common.endpoints.http.server.HttpServletServer;
+import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance;
+import org.onap.policy.common.gson.GsonMessageBodyHandler;
+import org.onap.policy.common.utils.network.NetworkUtil;
+
+/**
+ * The Class MockServerRest that manages test servers for REST requests for the test.
+ */
+public class MockServerRest implements AutoCloseable {
+    private static final String HOST = "localhost";
+    private HttpServletServer restServer;
+    private int restServerPort = 0;
+
+    /**
+     * Instantiates a new REST simulator.
+     */
+    public MockServerRest(int restServerPort) {
+        this.restServerPort = restServerPort;
+        restServer = HttpServletServerFactoryInstance.getServerFactory().build("MockRestEndpoint", false, HOST,
+                restServerPort, "/", false, false);
+        restServer.addServletClass(null, MockRestEndpoint.class.getName());
+        restServer.setSerializationProvider(GsonMessageBodyHandler.class.getName());
+        restServer.start();
+    }
+
+    /**
+     * Validate the Rest server.
+     * @throws InterruptedException if is not alive
+     */
+    public void validate() throws InterruptedException {
+        if (!NetworkUtil.isTcpPortOpen(HOST, restServerPort, 50, 200L)) {
+            throw new IllegalStateException("port " + restServerPort + " is still not in use");
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        if (restServer != null) {
+            restServer.stop();
+            restServer = null;
+        }
+    }
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/ToscaUtils.java b/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/utils/ToscaUtils.java
new file mode 100755 (executable)
index 0000000..19471c0
--- /dev/null
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.utils;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.onap.policy.common.utils.coder.YamlJsonTranslator;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
+
+/**
+ * Util class for Test scope.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class ToscaUtils {
+
+    private static final YamlJsonTranslator yamlTranslator = new YamlJsonTranslator();
+    private static final String TOSCA_TEMPLATE_YAML = "clamp/acm/test/participant-a1pms.yaml";
+
+
+    /**
+     * Read a service template yaml.
+     * @return ToscaServiceTemplate
+     */
+    public static ToscaServiceTemplate readAutomationCompositionFromTosca() {
+        return serializeAutomationCompositionYaml();
+    }
+
+    private static ToscaServiceTemplate serializeAutomationCompositionYaml() {
+        String automationCompositionString = ResourceUtils.getResourceAsString(ToscaUtils.TOSCA_TEMPLATE_YAML);
+        return yamlTranslator.fromYaml(automationCompositionString, ToscaServiceTemplate.class);
+    }
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/webclient/AcA1PmsClientTest.java b/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/webclient/AcA1PmsClientTest.java
new file mode 100755 (executable)
index 0000000..0c4eabc
--- /dev/null
@@ -0,0 +1,148 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.a1pms.webclient;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.onap.policy.clamp.acm.participant.a1pms.parameters.A1PmsParameters;
+import org.onap.policy.clamp.acm.participant.a1pms.utils.CommonTestData;
+import org.onap.policy.clamp.acm.participant.a1pms.utils.MockServerRest;
+import org.onap.policy.common.utils.network.NetworkUtil;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+@ExtendWith(SpringExtension.class)
+class AcA1PmsClientTest {
+
+    private static int mockServerPort;
+
+    private static MockServerRest mockServer;
+
+    private static CommonTestData commonTestData;
+
+    @Mock
+    private A1PmsParameters a1PmsParameters;
+
+
+    private final String healthyUrl = "/healthy";
+
+    private final String servicesUrl = "/services/success";
+
+    private final String serviceUrl = "/service/success/{serviceId}";
+
+    /**
+     * Set up Mock server.
+     */
+    @BeforeAll
+    static void setUpMockServer() throws IOException, InterruptedException {
+        mockServerPort = NetworkUtil.allocPort();
+        mockServer = new MockServerRest(mockServerPort);
+        mockServer.validate();
+        commonTestData = new CommonTestData();
+    }
+
+    @AfterAll
+    static void stopServer() throws Exception {
+        mockServer.close();
+        mockServer = null;
+    }
+
+    void initializePmsHealthParameters(String healthUrl) {
+        String testMockUrl = "http://localhost";
+        when(a1PmsParameters.getBaseUrl()).thenReturn(testMockUrl + ":" + mockServerPort);
+        var endpoints = new A1PmsParameters.Endpoints();
+        endpoints.setHealth(healthUrl);
+        when(a1PmsParameters.getEndpoints()).thenReturn(endpoints);
+    }
+
+    void initializePmsServicesParameters(String servicesUrl) {
+        initializePmsHealthParameters(healthyUrl);
+        var endpoints = a1PmsParameters.getEndpoints();
+        endpoints.setServices(servicesUrl);
+        when(a1PmsParameters.getEndpoints()).thenReturn(endpoints);
+    }
+
+    void initializePmsServiceParameters(String serviceUrl) {
+        initializePmsServicesParameters(servicesUrl);
+        var endpoints = a1PmsParameters.getEndpoints();
+        endpoints.setService(serviceUrl);
+        when(a1PmsParameters.getEndpoints()).thenReturn(endpoints);
+    }
+
+
+    @Test
+    void test_healthyPms() {
+        initializePmsHealthParameters(healthyUrl);
+        var client = new AcA1PmsClient(a1PmsParameters);
+        assertTrue(client.isPmsHealthy());
+    }
+
+    @Test
+    void test_unhealthyPms() {
+        String unhealthyUrl = "/unhealthy";
+        initializePmsHealthParameters(unhealthyUrl);
+        var client = new AcA1PmsClient(a1PmsParameters);
+        assertFalse(client.isPmsHealthy());
+    }
+
+    @Test
+    void test_createServicesSuccess() {
+        initializePmsServicesParameters(servicesUrl);
+        var client = new AcA1PmsClient(a1PmsParameters);
+        assertDoesNotThrow(() -> client.createService(commonTestData.getValidPolicyEntities()));
+    }
+
+    @Test
+    void test_createServicesFailure() {
+        String createServiceFailureUrl = "services/failure";
+        initializePmsServicesParameters(createServiceFailureUrl);
+        var client = new AcA1PmsClient(a1PmsParameters);
+        String expectedMessage = "Error in creating policy service";
+        assertThrows(Exception.class,
+                () -> client.createService(commonTestData.getValidPolicyEntities()), expectedMessage);
+    }
+
+    @Test
+    void test_deleteServicesSuccess() {
+        initializePmsServiceParameters(serviceUrl);
+        var client = new AcA1PmsClient(a1PmsParameters);
+        assertDoesNotThrow(() -> client.deleteService(commonTestData.getValidPolicyEntities()));
+    }
+
+    @Test
+    void test_deleteServicesFailure() {
+        String deleteServiceFailureUrl = "services/failure/{serviceId}";
+        initializePmsServiceParameters(deleteServiceFailureUrl);
+        var client = new AcA1PmsClient(a1PmsParameters);
+        String expectedMessage = "Error in deleting policy service";
+        assertThrows(Exception.class,
+                () -> client.deleteService(commonTestData.getValidPolicyEntities()), expectedMessage);
+    }
+}
diff --git a/participant/participant-impl/participant-impl-a1pms/src/test/resources/application-test.yaml b/participant/participant-impl/participant-impl-a1pms/src/test/resources/application-test.yaml
new file mode 100755 (executable)
index 0000000..be33b52
--- /dev/null
@@ -0,0 +1,24 @@
+participant:
+  intermediaryParameters:
+    reportingTimeInterval: 120000
+    description: Participant Description
+    participantId:
+      name: A1PMSParticipant0
+      version: 1.0.0
+    participantType:
+      name: org.onap.policy.clamp.acm.A1PMSParticipant
+      version: 2.3.4
+    clampAutomationCompositionTopics:
+      topicSources:
+        -
+          topic: POLICY-ACRUNTIME-PARTICIPANT
+          servers:
+            - localhost
+          topicCommInfrastructure: dmaap
+          fetchTimeout: 15000
+      topicSinks:
+        -
+          topicCommInfrastructure: dmaap
+          servers:
+            - localhost
+          topic: POLICY-ACRUNTIME-PARTICIPANT
\ No newline at end of file
index 7837f1d..bfbbf08 100644 (file)
@@ -40,6 +40,7 @@
         <module>participant-impl-cds</module>
         <module>participant-impl-kubernetes</module>
         <module>participant-impl-http</module>
+        <module>participant-impl-a1pms</module>
     </modules>
 
     <dependencies>
diff --git a/pom.xml b/pom.xml
index fc3755e..5509194 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
             o policy-clamp-participant-impl-policy: A standard participant for handling polcies for Policy Framework
             o policy-clamp-acm-element-impl: ACM element implementation for integration testing
             o policy-clamp-participant-impl-http: A standard participant for http configurations
+            o policy-clamp-participant-impl-a1: A standard participant for accessing A1-Policy Management Service
     </description>
 
     <properties>