Running Dmaap consumer in a seprate thread 87/2387/9
authorPatrikBuhr <patrik.buhr@est.tech>
Thu, 30 Jan 2020 15:10:19 +0000 (16:10 +0100)
committerPatrikBuhr <patrik.buhr@est.tech>
Wed, 5 Feb 2020 11:46:53 +0000 (12:46 +0100)
Fixed some potential threading problems

Enabled spring boot actuator for REST API
to control traces, diagnostics etc.

API documentation updates

Added GET policy_status in the agent NBI

Change-Id: Ied170bb1e8f350f17b385a0ef1def87cc6ec8750
Issue-ID: NONRTRIC-107
Signed-off-by: PatrikBuhr <patrik.buhr@est.tech>
23 files changed:
docs/api-docs.rst
policy-agent/docs/api.yaml [moved from policy-agent/docs/api.doc with 55% similarity]
policy-agent/pom.xml
policy-agent/src/main/java/org/oransc/policyagent/SwaggerConfig.java
policy-agent/src/main/java/org/oransc/policyagent/clients/A1Client.java
policy-agent/src/main/java/org/oransc/policyagent/clients/OscA1Client.java
policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOscA1Client.java
policy-agent/src/main/java/org/oransc/policyagent/clients/SdnrOnapA1Client.java
policy-agent/src/main/java/org/oransc/policyagent/clients/StdA1Client.java
policy-agent/src/main/java/org/oransc/policyagent/configuration/ApplicationConfig.java
policy-agent/src/main/java/org/oransc/policyagent/configuration/ApplicationConfigParser.java
policy-agent/src/main/java/org/oransc/policyagent/controllers/PolicyController.java
policy-agent/src/main/java/org/oransc/policyagent/controllers/RicRepositoryController.java
policy-agent/src/main/java/org/oransc/policyagent/dmaap/DmaapMessageConsumerImpl.java
policy-agent/src/main/java/org/oransc/policyagent/dmaap/DmaapMessageHandler.java
policy-agent/src/main/java/org/oransc/policyagent/repository/Ric.java
policy-agent/src/main/java/org/oransc/policyagent/tasks/RefreshConfigTask.java
policy-agent/src/main/java/org/oransc/policyagent/tasks/RicRecoveryTask.java
policy-agent/src/test/java/org/oransc/policyagent/ApplicationTest.java
policy-agent/src/test/java/org/oransc/policyagent/configuration/ApplicationConfigParserTest.java
policy-agent/src/test/java/org/oransc/policyagent/configuration/ApplicationConfigTest.java
policy-agent/src/test/java/org/oransc/policyagent/dmaap/DmaapMessageHandlerTest.java
policy-agent/src/test/java/org/oransc/policyagent/utils/MockA1Client.java

index 7365572..acfe38c 100644 (file)
@@ -68,8 +68,7 @@ See the README.md file in the nonrtric/policy-agent repo for info about how to u
 
 API Functions
 -------------
-
-See the following document for the Policy Agent API: nonrtric/policy-agent/docs/api.doc.
+See the following document for the Policy Agent API: nonrtric/policy-agent/docs/api.yaml
 
 Near-RT RIC Simulator
 =====================
similarity index 55%
rename from policy-agent/docs/api.doc
rename to policy-agent/docs/api.yaml
index e3f44ed..1416298 100644 (file)
@@ -1,16 +1,13 @@
 swagger: '2.0'
 info:
-  description: Api Documentation
+  description: This page lists all the rest apis for Policy server.
   version: '1.0'
-  title: Api Documentation
-  termsOfService: 'urn:tos'
-  contact: {}
-  license:
-    name: Apache 2.0
-    url: 'http://www.apache.org/licenses/LICENSE-2.0'
+  title: Policy server
 host: 'localhost:8081'
 basePath: /
 tags:
+  - name: operation-handler
+    description: Operation Handler
   - name: policy-controller
     description: Policy Controller
   - name: ric-repository-controller
@@ -19,21 +16,324 @@ tags:
     description: Service Controller
   - name: status-controller
     description: Status Controller
+  - name: web-mvc-links-handler
+    description: Web Mvc Links Handler
 paths:
+  /actuator:
+    get:
+      tags:
+        - web-mvc-links-handler
+      summary: links
+      operationId: linksUsingGET
+      produces:
+        - application/vnd.spring-boot.actuator.v3+json
+        - application/json
+        - application/vnd.spring-boot.actuator.v2+json
+      responses:
+        '200':
+          description: OK
+          schema:
+            type: object
+            additionalProperties:
+              type: object
+              additionalProperties:
+                $ref: '#/definitions/Link'
+        '401':
+          description: Unauthorized
+        '403':
+          description: Forbidden
+        '404':
+          description: Not Found
+      deprecated: false
+  /actuator/health:
+    get:
+      tags:
+        - operation-handler
+      summary: handle
+      operationId: handleUsingGET_1
+      produces:
+        - application/vnd.spring-boot.actuator.v3+json
+        - application/json
+        - application/vnd.spring-boot.actuator.v2+json
+      parameters:
+        - in: body
+          name: body
+          description: body
+          required: false
+          schema:
+            type: object
+            additionalProperties:
+              type: string
+      responses:
+        '200':
+          description: OK
+          schema:
+            type: object
+        '401':
+          description: Unauthorized
+        '403':
+          description: Forbidden
+        '404':
+          description: Not Found
+      deprecated: false
+  /actuator/health/**:
+    get:
+      tags:
+        - operation-handler
+      summary: handle
+      operationId: handleUsingGET
+      produces:
+        - application/vnd.spring-boot.actuator.v3+json
+        - application/json
+        - application/vnd.spring-boot.actuator.v2+json
+      parameters:
+        - in: body
+          name: body
+          description: body
+          required: false
+          schema:
+            type: object
+            additionalProperties:
+              type: string
+      responses:
+        '200':
+          description: OK
+          schema:
+            type: object
+        '401':
+          description: Unauthorized
+        '403':
+          description: Forbidden
+        '404':
+          description: Not Found
+      deprecated: false
+  /actuator/info:
+    get:
+      tags:
+        - operation-handler
+      summary: handle
+      operationId: handleUsingGET_2
+      produces:
+        - application/vnd.spring-boot.actuator.v3+json
+        - application/json
+        - application/vnd.spring-boot.actuator.v2+json
+      parameters:
+        - in: body
+          name: body
+          description: body
+          required: false
+          schema:
+            type: object
+            additionalProperties:
+              type: string
+      responses:
+        '200':
+          description: OK
+          schema:
+            type: object
+        '401':
+          description: Unauthorized
+        '403':
+          description: Forbidden
+        '404':
+          description: Not Found
+      deprecated: false
+  /actuator/logfile:
+    get:
+      tags:
+        - operation-handler
+      summary: handle
+      operationId: handleUsingGET_3
+      produces:
+        - text/plain;charset=UTF-8
+      parameters:
+        - in: body
+          name: body
+          description: body
+          required: false
+          schema:
+            type: object
+            additionalProperties:
+              type: string
+      responses:
+        '200':
+          description: OK
+          schema:
+            type: object
+        '401':
+          description: Unauthorized
+        '403':
+          description: Forbidden
+        '404':
+          description: Not Found
+      deprecated: false
+  /actuator/loggers:
+    get:
+      tags:
+        - operation-handler
+      summary: handle
+      operationId: handleUsingGET_5
+      produces:
+        - application/vnd.spring-boot.actuator.v3+json
+        - application/json
+        - application/vnd.spring-boot.actuator.v2+json
+      parameters:
+        - in: body
+          name: body
+          description: body
+          required: false
+          schema:
+            type: object
+            additionalProperties:
+              type: string
+      responses:
+        '200':
+          description: OK
+          schema:
+            type: object
+        '401':
+          description: Unauthorized
+        '403':
+          description: Forbidden
+        '404':
+          description: Not Found
+      deprecated: false
+  '/actuator/loggers/{name}':
+    get:
+      tags:
+        - operation-handler
+      summary: handle
+      operationId: handleUsingGET_4
+      produces:
+        - application/vnd.spring-boot.actuator.v3+json
+        - application/json
+        - application/vnd.spring-boot.actuator.v2+json
+      parameters:
+        - in: body
+          name: body
+          description: body
+          required: false
+          schema:
+            type: object
+            additionalProperties:
+              type: string
+      responses:
+        '200':
+          description: OK
+          schema:
+            type: object
+        '401':
+          description: Unauthorized
+        '403':
+          description: Forbidden
+        '404':
+          description: Not Found
+      deprecated: false
+    post:
+      tags:
+        - operation-handler
+      summary: handle
+      operationId: handleUsingPOST
+      consumes:
+        - application/vnd.spring-boot.actuator.v3+json
+        - application/json
+        - application/vnd.spring-boot.actuator.v2+json
+      produces:
+        - '*/*'
+      parameters:
+        - in: body
+          name: body
+          description: body
+          required: false
+          schema:
+            type: object
+            additionalProperties:
+              type: string
+      responses:
+        '200':
+          description: OK
+          schema:
+            type: object
+        '201':
+          description: Created
+        '401':
+          description: Unauthorized
+        '403':
+          description: Forbidden
+        '404':
+          description: Not Found
+      deprecated: false
+  /actuator/metrics:
+    get:
+      tags:
+        - operation-handler
+      summary: handle
+      operationId: handleUsingGET_7
+      produces:
+        - application/vnd.spring-boot.actuator.v3+json
+        - application/json
+        - application/vnd.spring-boot.actuator.v2+json
+      parameters:
+        - in: body
+          name: body
+          description: body
+          required: false
+          schema:
+            type: object
+            additionalProperties:
+              type: string
+      responses:
+        '200':
+          description: OK
+          schema:
+            type: object
+        '401':
+          description: Unauthorized
+        '403':
+          description: Forbidden
+        '404':
+          description: Not Found
+      deprecated: false
+  '/actuator/metrics/{requiredMetricName}':
+    get:
+      tags:
+        - operation-handler
+      summary: handle
+      operationId: handleUsingGET_6
+      produces:
+        - application/vnd.spring-boot.actuator.v3+json
+        - application/json
+        - application/vnd.spring-boot.actuator.v2+json
+      parameters:
+        - in: body
+          name: body
+          description: body
+          required: false
+          schema:
+            type: object
+            additionalProperties:
+              type: string
+      responses:
+        '200':
+          description: OK
+          schema:
+            type: object
+        '401':
+          description: Unauthorized
+        '403':
+          description: Forbidden
+        '404':
+          description: Not Found
+      deprecated: false
   /policies:
     get:
       tags:
         - policy-controller
-      summary: Returns the policies
+      summary: Query policies
       operationId: getPoliciesUsingGET
       produces:
         - '*/*'
       parameters:
-        - name: type
-          in: query
-          description: type
-          required: false
-          type: string
         - name: ric
           in: query
           description: ric
@@ -44,6 +344,11 @@ paths:
           description: service
           required: false
           type: string
+        - name: type
+          in: query
+          description: type
+          required: false
+          type: string
       responses:
         '200':
           description: Policies
@@ -57,6 +362,7 @@ paths:
           description: Forbidden
         '404':
           description: Not Found
+      deprecated: false
   /policy:
     get:
       tags:
@@ -86,6 +392,7 @@ paths:
           description: Forbidden
         '404':
           description: Not Found
+      deprecated: false
     put:
       tags:
         - policy-controller
@@ -96,16 +403,17 @@ paths:
       produces:
         - '*/*'
       parameters:
-        - name: type
-          in: query
-          description: type
-          required: true
-          type: string
         - name: instance
           in: query
           description: instance
           required: true
           type: string
+        - in: body
+          name: jsonBody
+          description: jsonBody
+          required: true
+          schema:
+            type: object
         - name: ric
           in: query
           description: ric
@@ -116,12 +424,11 @@ paths:
           description: service
           required: true
           type: string
-        - in: body
-          name: jsonBody
-          description: jsonBody
+        - name: type
+          in: query
+          description: type
           required: true
-          schema:
-            type: object
+          type: string
       responses:
         '200':
           description: Policy created or updated
@@ -135,10 +442,11 @@ paths:
           description: Forbidden
         '404':
           description: Not Found
+      deprecated: false
     delete:
       tags:
         - policy-controller
-      summary: Deletes the policy
+      summary: Delete a policy
       operationId: deletePolicyUsingDELETE
       produces:
         - '*/*'
@@ -152,15 +460,16 @@ paths:
         '200':
           description: OK
           schema:
-            $ref: '#/definitions/Mono«ResponseEntity«Void»»'
+            type: object
         '204':
           description: Policy deleted
           schema:
-            $ref: '#/definitions/Mono«ResponseEntity«Void»»'
+            type: object
         '401':
           description: Unauthorized
         '403':
           description: Forbidden
+      deprecated: false
   /policy_schema:
     get:
       tags:
@@ -186,6 +495,7 @@ paths:
           description: Forbidden
         '404':
           description: Not Found
+      deprecated: false
   /policy_schemas:
     get:
       tags:
@@ -213,11 +523,42 @@ paths:
           description: Forbidden
         '404':
           description: Not Found
+      deprecated: false
+  /policy_status:
+    get:
+      tags:
+        - policy-controller
+      summary: Returns a policy status
+      operationId: getPolicyStatusUsingGET
+      produces:
+        - '*/*'
+      parameters:
+        - name: instance
+          in: query
+          description: instance
+          required: true
+          type: string
+      responses:
+        '200':
+          description: Policy status
+          schema:
+            type: object
+        '204':
+          description: Policy is not found
+          schema:
+            type: string
+        '401':
+          description: Unauthorized
+        '403':
+          description: Forbidden
+        '404':
+          description: Not Found
+      deprecated: false
   /policy_types:
     get:
       tags:
         - policy-controller
-      summary: Returns policy types
+      summary: Query policy type names
       operationId: getPolicyTypesUsingGET
       produces:
         - '*/*'
@@ -240,6 +581,7 @@ paths:
           description: Forbidden
         '404':
           description: Not Found
+      deprecated: false
   /ric:
     get:
       tags:
@@ -267,11 +609,12 @@ paths:
           description: RIC is not fond
           schema:
             type: string
+      deprecated: false
   /rics:
     get:
       tags:
         - ric-repository-controller
-      summary: Returns NearRT RIC information
+      summary: Query NearRT RIC information
       operationId: getRicsUsingGET
       produces:
         - '*/*'
@@ -294,6 +637,7 @@ paths:
           description: Forbidden
         '404':
           description: Not Found
+      deprecated: false
   /service:
     put:
       tags:
@@ -324,6 +668,7 @@ paths:
           description: Forbidden
         '404':
           description: Not Found
+      deprecated: false
   /services:
     get:
       tags:
@@ -351,6 +696,7 @@ paths:
           description: Forbidden
         '404':
           description: Not Found
+      deprecated: false
     delete:
       tags:
         - service-controller
@@ -375,6 +721,7 @@ paths:
           description: Unauthorized
         '403':
           description: Forbidden
+      deprecated: false
   /services/keepalive:
     post:
       tags:
@@ -404,6 +751,7 @@ paths:
           description: Forbidden
         '404':
           description: 'The service is not found, needs re-registration'
+      deprecated: false
   /status:
     get:
       tags:
@@ -423,7 +771,21 @@ paths:
           description: Forbidden
         '404':
           description: Not Found
+      deprecated: false
 definitions:
+  Link:
+    type: object
+    properties:
+      href:
+        type: string
+      templated:
+        type: boolean
+    title: Link
+  'Map«string,Link»':
+    type: object
+    title: 'Map«string,Link»'
+    additionalProperties:
+      $ref: '#/definitions/Link'
   Mono«ResponseEntity«Void»»:
     type: object
     title: Mono«ResponseEntity«Void»»
@@ -436,27 +798,21 @@ definitions:
       id:
         type: string
         description: identity of the policy
-        allowEmptyValue: false
       json:
         type: string
         description: the configuration of the policy
-        allowEmptyValue: false
       lastModified:
         type: string
         description: 'timestamp, last modification time'
-        allowEmptyValue: false
       ric:
         type: string
         description: identity the target NearRT RIC
-        allowEmptyValue: false
       service:
         type: string
         description: the name of the service owning the policy
-        allowEmptyValue: false
       type:
         type: string
         description: name of the policy type
-        allowEmptyValue: false
     title: PolicyInfo
   RicInfo:
     type: object
@@ -464,17 +820,14 @@ definitions:
       managedElementIds:
         type: array
         description: O1 identities for managed entities
-        allowEmptyValue: false
         items:
           type: string
       name:
         type: string
         description: identity of the ric
-        allowEmptyValue: false
       policyTypes:
         type: array
         description: supported policy types
-        allowEmptyValue: false
         items:
           type: string
     title: RicInfo
@@ -484,16 +837,13 @@ definitions:
       callbackUrl:
         type: string
         description: callback for notifying of RIC recovery
-        allowEmptyValue: false
       keepAliveIntervalSeconds:
         type: integer
         format: int64
         description: keep alive interval for policies owned by the service. 0 means no timeout supervision. Polcies that are not refreshed within this time are removed
-        allowEmptyValue: false
       name:
         type: string
         description: identity of the service
-        allowEmptyValue: false
     title: ServiceRegistrationInfo
   ServiceStatus:
     type: object
@@ -502,15 +852,12 @@ definitions:
         type: integer
         format: int64
         description: policy keep alive timeout
-        allowEmptyValue: false
       name:
         type: string
         description: identity of the service
-        allowEmptyValue: false
       timeSincePingSeconds:
         type: integer
         format: int64
         description: time since last invocation by the service
-        allowEmptyValue: false
     title: ServiceStatus
 
index 311229f..daad418 100644 (file)
 * limitations under the License.
 * ========================LICENSE_END===================================
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
-       <modelVersion>4.0.0</modelVersion>
-       <parent>
-               <groupId>org.springframework.boot</groupId>
-               <artifactId>spring-boot-starter-parent</artifactId>
-               <version>2.2.4.RELEASE</version>
-               <relativePath />
-       </parent>
-       <groupId>org.o-ran-sc.nonrtric</groupId>
-       <artifactId>policy-agent</artifactId>
-       <version>1.0.0-SNAPSHOT</version>
-       <licenses>
-               <license>
-                       <name>The Apache Software License, Version 2.0</name>
-                       <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
-               </license>
-       </licenses>
-       <repositories>
-               <repository>
-                       <id>onap-releases</id>
-                       <name>onap-releases</name>
-                       <url>https://nexus.onap.org/content/repositories/releases/</url>
-               </repository>
-       </repositories>
-       <properties>
-               <java.version>11</java.version>
-               <springfox.version>2.8.0</springfox.version>
-               <immutable.version>2.7.1</immutable.version>
-               <sdk.version>1.1.6</sdk.version>
-               <swagger.version>2.0.0</swagger.version>
-               <json.version>20180130</json.version>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.2.4.RELEASE</version>
+        <relativePath />
+    </parent>
+    <groupId>org.o-ran-sc.nonrtric</groupId>
+    <artifactId>policy-agent</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <licenses>
+        <license>
+            <name>The Apache Software License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+        </license>
+    </licenses>
+    <repositories>
+        <repository>
+            <id>onap-releases</id>
+            <name>onap-releases</name>
+            <url>https://nexus.onap.org/content/repositories/releases/</url>
+        </repository>
+    </repositories>
+    <properties>
+        <java.version>11</java.version>
+        <springfox.version>2.9.2</springfox.version>
+        <immutable.version>2.7.1</immutable.version>
+        <sdk.version>1.1.6</sdk.version>
+        <swagger.version>2.0.0</swagger.version>
+        <json.version>20180130</json.version>
         <commons-net.version>3.3</commons-net.version>
-               <awaitility.version>4.0.1</awaitility.version>
-               <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
-               <formatter-maven-plugin.version>2.8.1</formatter-maven-plugin.version>
-               <spotless-maven-plugin.version>1.18.0</spotless-maven-plugin.version>
-               <docker-maven-plugin>0.30.0</docker-maven-plugin>
-               <version.dmaap>1.1.9</version.dmaap>
+        <awaitility.version>4.0.1</awaitility.version>
+        <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
+        <formatter-maven-plugin.version>2.8.1</formatter-maven-plugin.version>
+        <spotless-maven-plugin.version>1.18.0</spotless-maven-plugin.version>
+        <docker-maven-plugin>0.30.0</docker-maven-plugin>
+        <version.dmaap>1.1.9</version.dmaap>
         <javax.ws.rs-api.version>2.1.1</javax.ws.rs-api.version>
-       </properties>
-       <dependencies>
-               <dependency>
-                       <groupId>org.springframework.boot</groupId>
-                       <artifactId>spring-boot-starter-web</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.springframework.boot</groupId>
-                       <artifactId>spring-boot-starter-thymeleaf</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.springframework.boot</groupId>
-                       <artifactId>spring-boot-starter-webflux</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.springframework.boot</groupId>
-                       <artifactId>spring-boot-devtools</artifactId>
-                       <optional>true</optional>
-               </dependency>
-               <dependency>
-                       <groupId>org.springframework</groupId>
-                       <artifactId>spring-webflux</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>io.swagger.core.v3</groupId>
-                       <artifactId>swagger-jaxrs2</artifactId>
-                       <version>${swagger.version}</version>
-               </dependency>
-               <dependency>
-                       <groupId>io.swagger.core.v3</groupId>
-                       <artifactId>swagger-jaxrs2-servlet-initializer</artifactId>
-                       <version>${swagger.version}</version>
-               </dependency>
-               <dependency>
-                       <groupId>javax.xml.bind</groupId>
-                       <artifactId>jaxb-api</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.immutables</groupId>
-                       <artifactId>value</artifactId>
-                       <version>${immutable.version}</version>
-                       <scope>provided</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.immutables</groupId>
-                       <artifactId>gson</artifactId>
-                       <version>${immutable.version}</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.json</groupId>
-                       <artifactId>json</artifactId>
-                       <version>${json.version}</version>
-               </dependency>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-thymeleaf</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-webflux</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webflux</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.swagger.core.v3</groupId>
+            <artifactId>swagger-jaxrs2</artifactId>
+            <version>${swagger.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.swagger.core.v3</groupId>
+            <artifactId>swagger-jaxrs2-servlet-initializer</artifactId>
+            <version>${swagger.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.xml.bind</groupId>
+            <artifactId>jaxb-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.immutables</groupId>
+            <artifactId>value</artifactId>
+            <version>${immutable.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.immutables</groupId>
+            <artifactId>gson</artifactId>
+            <version>${immutable.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.json</groupId>
+            <artifactId>json</artifactId>
+            <version>${json.version}</version>
+        </dependency>
         <dependency>
             <groupId>commons-net</groupId>
             <artifactId>commons-net</artifactId>
             <version>${commons-net.version}</version>
         </dependency>
-               <!--TEST -->
-               <dependency>
-                       <groupId>org.springframework.boot</groupId>
-                       <artifactId>spring-boot-starter-test</artifactId>
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.springframework.boot</groupId>
-                       <artifactId>spring-boot-configuration-processor</artifactId>
-                       <optional>true</optional>
-               </dependency>
-               <dependency>
-                       <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
-                       <artifactId>cbs-client</artifactId>
+        <!-- Actuator dependencies -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+        <!--TEST -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
+            <artifactId>cbs-client</artifactId>
             <version>${sdk.version}</version>
         </dependency>
         <dependency>
             <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
             <artifactId>dmaap-client</artifactId>
-                       <version>${sdk.version}</version>
-               </dependency>
+            <version>${sdk.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
             <scope>provided</scope>
         </dependency>
-               <!--REQUIRED TO GENERATE DOCUMENTATION -->
-               <dependency>
-                       <groupId>io.springfox</groupId>
-                       <artifactId>springfox-swagger2</artifactId>
-                       <version>${springfox.version}</version>
-               </dependency>
-               <dependency>
-                       <groupId>io.springfox</groupId>
-                       <artifactId>springfox-swagger-ui</artifactId>
-                       <version>${springfox.version}</version>
-               </dependency>
-               <!-- TEST -->
-               <dependency>
-                       <groupId>org.awaitility</groupId>
-                       <artifactId>awaitility</artifactId>
-                       <version>${awaitility.version}</version>
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>io.projectreactor</groupId>
-                       <artifactId>reactor-test</artifactId>
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.junit.jupiter</groupId>
-                       <artifactId>junit-jupiter-engine</artifactId>
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.mockito</groupId>
-                       <artifactId>mockito-junit-jupiter</artifactId>
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.mockito</groupId>
-                       <artifactId>mockito-core</artifactId>
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.onap.dmaap.messagerouter.dmaapclient</groupId>
-                       <artifactId>dmaapClient</artifactId>
-                       <version>${version.dmaap}</version>
-               </dependency>
+        <!--REQUIRED TO GENERATE DOCUMENTATION -->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>${springfox.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>${springfox.version}</version>
+        </dependency>
+        <!-- TEST -->
+        <dependency>
+            <groupId>org.awaitility</groupId>
+            <artifactId>awaitility</artifactId>
+            <version>${awaitility.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.projectreactor</groupId>
+            <artifactId>reactor-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-junit-jupiter</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.dmaap.messagerouter.dmaapclient</groupId>
+            <artifactId>dmaapClient</artifactId>
+            <version>${version.dmaap}</version>
+        </dependency>
         <dependency>
             <groupId>javax.ws.rs</groupId>
             <artifactId>javax.ws.rs-api</artifactId>
             <groupId>org.glassfish.jersey.inject</groupId>
             <artifactId>jersey-hk2</artifactId>
         </dependency>
-       </dependencies>
-       <build>
-               <plugins>
-                       <plugin>
-                               <groupId>org.springframework.boot</groupId>
-                               <artifactId>spring-boot-maven-plugin</artifactId>
-                       </plugin>
-                       <plugin>
-                               <groupId>net.revelc.code.formatter</groupId>
-                               <artifactId>formatter-maven-plugin</artifactId>
-                               <version>${formatter-maven-plugin.version}</version>
-                               <configuration>
-                                       <configFile>${project.basedir}/eclipse-formatter.xml</configFile>
-                               </configuration>
-                               <!-- https://code.revelc.net/formatter-maven-plugin/ use mvn formatter:format 
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>net.revelc.code.formatter</groupId>
+                <artifactId>formatter-maven-plugin</artifactId>
+                <version>${formatter-maven-plugin.version}</version>
+                <configuration>
+                    <configFile>${project.basedir}/eclipse-formatter.xml</configFile>
+                </configuration>
+                <!-- https://code.revelc.net/formatter-maven-plugin/ use mvn formatter:format 
                                        spotless:apply process-sources -->
-                       </plugin>
-                       <plugin>
-                               <groupId>com.diffplug.spotless</groupId>
-                               <artifactId>spotless-maven-plugin</artifactId>
-                               <version>${spotless-maven-plugin.version}</version>
-                               <configuration>
-                                       <java>
-                                               <removeUnusedImports />
-                                               <importOrder>
-                                                       <order>com,java,javax,org</order>
-                                               </importOrder>
-                                       </java>
-                               </configuration>
-                               <!-- https://github.com/diffplug/spotless/tree/master/plugin-maven use 
+            </plugin>
+            <plugin>
+                <groupId>com.diffplug.spotless</groupId>
+                <artifactId>spotless-maven-plugin</artifactId>
+                <version>${spotless-maven-plugin.version}</version>
+                <configuration>
+                    <java>
+                        <removeUnusedImports />
+                        <importOrder>
+                            <order>com,java,javax,org</order>
+                        </importOrder>
+                    </java>
+                </configuration>
+                <!-- https://github.com/diffplug/spotless/tree/master/plugin-maven use 
                                        mvn spotless:apply to rewrite source files use mvn spotless:check to validate 
                                        source files -->
-                       </plugin>
-                       <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-surefire-plugin</artifactId>
-                               <configuration>
-                                       <skipTests>false</skipTests>
-                               </configuration>
-                       </plugin>
-                       <plugin>
-                               <artifactId>maven-failsafe-plugin</artifactId>
-                       </plugin>
-                       <plugin>
-                               <groupId>org.codehaus.mojo</groupId>
-                               <artifactId>build-helper-maven-plugin</artifactId>
-                               <executions>
-                                       <execution>
-                                               <id>add-source</id>
-                                               <phase>generate-sources</phase>
-                                               <goals>
-                                                       <goal>add-source</goal>
-                                               </goals>
-                                               <configuration>
-                                                       <sources>
-                                                               <source>${project.build.directory}/generated-sources/annotations/</source>
-                                                       </sources>
-                                               </configuration>
-                                       </execution>
-                               </executions>
-                       </plugin>
-                       <plugin>
-                               <groupId>io.fabric8</groupId>
-                               <artifactId>docker-maven-plugin</artifactId>
-                               <version>${docker-maven-plugin}</version>
-                               <inherited>false</inherited>
-                               <executions>
-                                       <execution>
-                                               <id>generate-policy-agent-image</id>
-                                               <phase>package</phase>
-                                               <goals>
-                                                       <goal>build</goal>
-                                               </goals>
-                                               <configuration>
-                                                       <pullRegistry>${env.CONTAINER_PULL_REGISTRY}</pullRegistry>
-                                                       <images>
-                                                               <image>
-                                                                       <name>o-ran-sc/nonrtric-policy-agent:${project.version}</name>
-                                                                       <build>
-                                                                               <cleanup>try</cleanup>
-                                                                               <contextDir>${basedir}</contextDir>
-                                                                               <dockerFile>Dockerfile</dockerFile>
-                                                                               <args>
-                                                                                       <JAR>${project.build.finalName}.jar</JAR>
-                                                                               </args>
-                                                                               <tags>
-                                                                                       <tag>${project.version}</tag>
-                                                                               </tags>
-                                                                       </build>
-                                                               </image>
-                                                       </images>
-                                               </configuration>
-                                       </execution>
-                                       <execution>
-                                               <id>push-policy-agent-image</id>
-                                               <goals>
-                                                       <goal>build</goal>
-                                                       <goal>push</goal>
-                                               </goals>
-                                               <configuration>
-                                                       <pullRegistry>${env.CONTAINER_PULL_REGISTRY}</pullRegistry>
-                                                       <pushRegistry>${env.CONTAINER_PUSH_REGISTRY}</pushRegistry>
-                                                       <images>
-                                                               <image>
-                                                                       <name>o-ran-sc/nonrtric-policy-agent:${project.version}</name>
-                                                                       <build>
-                                                                               <contextDir>${basedir}</contextDir>
-                                                                               <dockerFile>Dockerfile</dockerFile>
-                                                                               <args>
-                                                                                       <JAR>${project.build.finalName}.jar</JAR>
-                                                                               </args>
-                                                                               <tags>
-                                                                                       <tag>${project.version}</tag>
-                                                                               </tags>
-                                                                       </build>
-                                                               </image>
-                                                       </images>
-                                               </configuration>
-                                       </execution>
-                               </executions>
-                       </plugin>
-               </plugins>
-       </build>
-       <issueManagement>
-               <system>JIRA</system>
-               <url>https://jira.o-ran-sc.org/</url>
-       </issueManagement>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <skipTests>false</skipTests>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-failsafe-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>add-source</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>${project.build.directory}/generated-sources/annotations/</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>io.fabric8</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+                <version>${docker-maven-plugin}</version>
+                <inherited>false</inherited>
+                <executions>
+                    <execution>
+                        <id>generate-policy-agent-image</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>build</goal>
+                        </goals>
+                        <configuration>
+                            <pullRegistry>${env.CONTAINER_PULL_REGISTRY}</pullRegistry>
+                            <images>
+                                <image>
+                                    <name>o-ran-sc/nonrtric-policy-agent:${project.version}</name>
+                                    <build>
+                                        <cleanup>try</cleanup>
+                                        <contextDir>${basedir}</contextDir>
+                                        <dockerFile>Dockerfile</dockerFile>
+                                        <args>
+                                            <JAR>${project.build.finalName}.jar</JAR>
+                                        </args>
+                                        <tags>
+                                            <tag>${project.version}</tag>
+                                        </tags>
+                                    </build>
+                                </image>
+                            </images>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>push-policy-agent-image</id>
+                        <goals>
+                            <goal>build</goal>
+                            <goal>push</goal>
+                        </goals>
+                        <configuration>
+                            <pullRegistry>${env.CONTAINER_PULL_REGISTRY}</pullRegistry>
+                            <pushRegistry>${env.CONTAINER_PUSH_REGISTRY}</pushRegistry>
+                            <images>
+                                <image>
+                                    <name>o-ran-sc/nonrtric-policy-agent:${project.version}</name>
+                                    <build>
+                                        <contextDir>${basedir}</contextDir>
+                                        <dockerFile>Dockerfile</dockerFile>
+                                        <args>
+                                            <JAR>${project.build.finalName}.jar</JAR>
+                                        </args>
+                                        <tags>
+                                            <tag>${project.version}</tag>
+                                        </tags>
+                                    </build>
+                                </image>
+                            </images>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+    <issueManagement>
+        <system>JIRA</system>
+        <url>https://jira.o-ran-sc.org/</url>
+    </issueManagement>
 </project>
index f3b4a5a..df5e7b4 100644 (file)
 
 package org.oransc.policyagent;
 
+import com.google.common.base.Predicates;
+
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
 
+import springfox.documentation.builders.ApiInfoBuilder;
 import springfox.documentation.builders.PathSelectors;
 import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
 import springfox.documentation.spi.DocumentationType;
 import springfox.documentation.spring.web.plugins.Docket;
 import springfox.documentation.swagger2.annotations.EnableSwagger2;
@@ -37,12 +43,48 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
  */
 @Configuration
 @EnableSwagger2
-public class SwaggerConfig {
+public class SwaggerConfig extends WebMvcConfigurationSupport {
+
+    static final String API_TITLE = "Policy server";
+    static final String DESCRIPTION = "This page lists all the rest apis for Policy server.";
+    static final String VERSION = "1.0";
+    static final String RESOURCES_PATH = "classpath:/META-INF/resources/";
+    static final String WEBJARS_PATH = RESOURCES_PATH + "webjars/";
+    static final String SWAGGER_UI = "swagger-ui.html";
+    static final String WEBJARS = "/webjars/**";
+
+    /**
+     * Gets the API info.
+     *
+     * @return the API info.
+     */
     @Bean
     public Docket api() {
-        return new Docket(DocumentationType.SWAGGER_2).select() //
-            .apis(RequestHandlerSelectors.basePackage("org.oransc.policyagent.controllers")) //
+        return new Docket(DocumentationType.SWAGGER_2) //
+            .apiInfo(apiInfo()) //
+            .select() //
+            .apis(RequestHandlerSelectors.any()) //
             .paths(PathSelectors.any()) //
+            .paths(Predicates.not(PathSelectors.regex("/error"))) //
+            // this endpoint is not implemented, but was visible for Swagger
+            .build();
+    }
+
+    private static ApiInfo apiInfo() {
+        return new ApiInfoBuilder() //
+            .title(API_TITLE) //
+            .description(DESCRIPTION) //
+            .version(VERSION) //
             .build();
     }
+
+    @Override
+    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
+        registry.addResourceHandler(SWAGGER_UI) //
+            .addResourceLocations(RESOURCES_PATH);
+
+        registry.addResourceHandler(WEBJARS) //
+            .addResourceLocations(WEBJARS_PATH);
+    }
+
 }
index 0a2bc8e..0b18104 100644 (file)
@@ -47,4 +47,6 @@ public interface A1Client {
 
     public Flux<String> deleteAllPolicies();
 
+    public Mono<String> getPolicyStatus(Policy policy);
+
 }
index dd77504..5c18103 100644 (file)
@@ -130,4 +130,11 @@ public class OscA1Client implements A1Client {
             return Mono.error(ex);
         }
     }
+
+    @Override
+    public Mono<String> getPolicyStatus(Policy policy) {
+        // /a1-p/policytypes/{policy_type_id}/policies/{policy_instance_id}/status
+        return restClient.get("/policytypes/" + policy.type().name() + "/policies/" + policy.id() + "/status");
+
+    }
 }
index 2f8fab4..ff6e857 100644 (file)
@@ -200,4 +200,9 @@ public class SdncOscA1Client implements A1Client {
             return Mono.error(ex);
         }
     }
+
+    @Override
+    public Mono<String> getPolicyStatus(Policy policy) {
+        return Mono.error(new Exception("Status not implemented in the SDNC controller"));
+    }
 }
index 1993be7..248c218 100644 (file)
@@ -205,4 +205,9 @@ public class SdnrOnapA1Client implements A1Client {
             return Mono.error(ex);
         }
     }
+
+    @Override
+    public Mono<String> getPolicyStatus(Policy policy) {
+        return Mono.error(new Exception("Status not implemented in the controller"));
+    }
 }
index 1c40308..702658e 100644 (file)
@@ -130,4 +130,9 @@ public class StdA1Client implements A1Client {
         }
     }
 
+    @Override
+    public Mono<String> getPolicyStatus(Policy policy) {
+        return restClient.get("/policies/" + policy.id() + "/status");
+    }
+
 }
index 1e8c6d4..a48e591 100644 (file)
@@ -134,8 +134,12 @@ public class ApplicationConfig {
 
     public void setConfiguration(@NotNull Collection<RicConfig> ricConfigs, Properties dmaapPublisherConfig,
         Properties dmaapConsumerConfig) {
+
         Collection<Notification> notifications = new Vector<>();
         synchronized (this) {
+            this.dmaapPublisherConfig = dmaapPublisherConfig;
+            this.dmaapConsumerConfig = dmaapConsumerConfig;
+
             Map<String, RicConfig> newRicConfigs = new HashMap<>();
             for (RicConfig newConfig : ricConfigs) {
                 RicConfig oldConfig = this.ricConfigs.get(newConfig.name());
@@ -156,10 +160,8 @@ public class ApplicationConfig {
             }
             this.ricConfigs = newRicConfigs;
         }
-        notifyObservers(notifications);
 
-        this.dmaapPublisherConfig = dmaapPublisherConfig;
-        this.dmaapConsumerConfig = dmaapConsumerConfig;
+        notifyObservers(notifications);
     }
 
     private void notifyObservers(Collection<Notification> notifications) {
index 1ffe9c8..c21af83 100644 (file)
@@ -25,14 +25,18 @@ import com.google.gson.GsonBuilder;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
+
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.Set;
 import java.util.Vector;
+
 import javax.validation.constraints.NotNull;
+
 import lombok.Getter;
+
 import org.onap.dmaap.mr.test.clients.ProtocolTypeConstants;
 import org.oransc.policyagent.exceptions.ServiceException;
 import org.springframework.http.MediaType;
@@ -48,25 +52,24 @@ public class ApplicationConfigParser {
     @Getter
     private Vector<RicConfig> ricConfigs;
     @Getter
-    private Properties dmaapPublisherConfig;
+    private Properties dmaapPublisherConfig = new Properties();
     @Getter
-    private Properties dmaapConsumerConfig;
+    private Properties dmaapConsumerConfig = new Properties();
 
     public void parse(JsonObject root) throws ServiceException {
         JsonObject agentConfigJson = root.getAsJsonObject(CONFIG);
         ricConfigs = parseRics(agentConfigJson);
-        JsonObject dmaapPublisherConfigJson = agentConfigJson.getAsJsonObject("streams_publishes");
-        if (dmaapPublisherConfigJson == null) {
-            dmaapPublisherConfig = new Properties();
-        } else {
-            dmaapPublisherConfig = parseDmaapConfig(dmaapPublisherConfigJson);
+
+        JsonObject json = agentConfigJson.getAsJsonObject("streams_publishes");
+        if (json != null) {
+            this.dmaapPublisherConfig = parseDmaapConfig(json);
         }
-        JsonObject dmaapConsumerConfigJson = agentConfigJson.getAsJsonObject("streams_subscribes");
-        if (dmaapConsumerConfigJson == null) {
-            dmaapConsumerConfig = new Properties();
-        } else {
-            dmaapConsumerConfig = parseDmaapConfig(dmaapConsumerConfigJson);
+
+        json = agentConfigJson.getAsJsonObject("streams_subscribes");
+        if (json != null) {
+            this.dmaapConsumerConfig = parseDmaapConfig(json);
         }
+
     }
 
     private Vector<RicConfig> parseRics(JsonObject config) throws ServiceException {
@@ -99,8 +102,8 @@ public class ApplicationConfigParser {
         JsonObject dmaapInfo = get(streamConfigEntry, "dmaap_info").getAsJsonObject();
         String topicUrl = getAsString(dmaapInfo, "topic_url");
 
-        Properties dmaapProps = new Properties();
         try {
+            Properties dmaapProps = new Properties();
             URL url = new URL(topicUrl);
             String passwd = "";
             String userName = "";
@@ -127,11 +130,11 @@ public class ApplicationConfigParser {
             dmaapProps.put("maxAgeMs", "10000");
             dmaapProps.put("compress", true);
             dmaapProps.put("MessageSentThreadOccurance", "2");
+            return dmaapProps;
         } catch (MalformedURLException e) {
             throw new ServiceException("Could not parse the URL", e);
         }
 
-        return dmaapProps;
     }
 
     private static @NotNull String getAsString(JsonObject obj, String memberName) throws ServiceException {
index 12deb81..e0971c5 100644 (file)
@@ -108,7 +108,7 @@ public class PolicyController {
     }
 
     @GetMapping("/policy_types")
-    @ApiOperation(value = "Returns policy types")
+    @ApiOperation(value = "Query policy type names")
     @ApiResponses(
         value = {@ApiResponse(
             code = 200,
@@ -138,7 +138,6 @@ public class PolicyController {
             @ApiResponse(code = 200, message = "Policy found", response = Object.class), //
             @ApiResponse(code = 204, message = "Policy is not found")} //
     )
-
     public ResponseEntity<String> getPolicy( //
         @RequestParam(name = "instance", required = true) String instance) {
         try {
@@ -150,7 +149,7 @@ public class PolicyController {
     }
 
     @DeleteMapping("/policy")
-    @ApiOperation(value = "Deletes the policy", response = Object.class)
+    @ApiOperation(value = "Delete a policy", response = Object.class)
     @ApiResponses(value = {@ApiResponse(code = 204, message = "Policy deleted", response = Object.class)})
     public Mono<ResponseEntity<Void>> deletePolicy( //
         @RequestParam(name = "instance", required = true) String id) {
@@ -201,7 +200,7 @@ public class PolicyController {
     }
 
     @GetMapping("/policies")
-    @ApiOperation(value = "Returns the policies")
+    @ApiOperation(value = "Query policies")
     @ApiResponses(
         value = {
             @ApiResponse(code = 200, message = "Policies", response = PolicyInfo.class, responseContainer = "List")})
@@ -230,6 +229,26 @@ public class PolicyController {
         }
     }
 
+    @GetMapping("/policy_status")
+    @ApiOperation(value = "Returns a policy status") //
+    @ApiResponses(
+        value = { //
+            @ApiResponse(code = 200, message = "Policy status", response = Object.class), //
+            @ApiResponse(code = 204, message = "Policy is not found", response = String.class)} //
+    )
+    public Mono<ResponseEntity<String>> getPolicyStatus( //
+        @RequestParam(name = "instance", required = true) String instance) {
+        try {
+            Policy policy = policies.getPolicy(instance);
+
+            return a1ClientFactory.createA1Client(policy.ric()) //
+                .flatMap(client -> client.getPolicyStatus(policy)) //
+                .flatMap(status -> Mono.just(new ResponseEntity<String>(status, HttpStatus.OK)));
+        } catch (ServiceException e) {
+            return Mono.just(new ResponseEntity<String>(e.getMessage(), HttpStatus.NO_CONTENT));
+        }
+    }
+
     private boolean include(String filter, String value) {
         return filter == null || value.equals(filter);
     }
index a566781..bb3b735 100644 (file)
@@ -83,7 +83,7 @@ public class RicRepositoryController {
      *         Example: http://localhost:8080/ric
      */
     @GetMapping("/rics")
-    @ApiOperation(value = "Returns NearRT RIC information")
+    @ApiOperation(value = "Query NearRT RIC information")
     @ApiResponses(
         value = { //
             @ApiResponse(code = 200, message = "OK", response = RicInfo.class, responseContainer = "List") //
index db4956a..4a2605b 100644 (file)
 package org.oransc.policyagent.dmaap;
 
 import com.google.common.collect.Iterables;
+
+import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.time.Duration;
 import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 import org.onap.dmaap.mr.client.MRBatchingPublisher;
 import org.onap.dmaap.mr.client.MRClientFactory;
 import org.onap.dmaap.mr.client.MRConsumer;
 import org.onap.dmaap.mr.client.response.MRConsumerResponse;
 import org.oransc.policyagent.clients.AsyncRestClient;
 import org.oransc.policyagent.configuration.ApplicationConfig;
+import org.oransc.policyagent.exceptions.ServiceException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.scheduling.annotation.EnableScheduling;
-import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
 @Component
-@EnableScheduling
-public class DmaapMessageConsumerImpl implements DmaapMessageConsumer {
+public class DmaapMessageConsumerImpl implements Runnable {
 
     private static final Logger logger = LoggerFactory.getLogger(DmaapMessageConsumerImpl.class);
 
-    private boolean alive = false;
+    final Duration ERROR_TIMEOUT = Duration.ofSeconds(30);
+    final Duration TIME_BETWEEN_DMAAP_POLLS = Duration.ofSeconds(10);
     private final ApplicationConfig applicationConfig;
-    protected MRConsumer consumer;
-    private MRBatchingPublisher producer;
 
     @Value("${server.port}")
     private int localServerPort;
@@ -54,15 +57,20 @@ public class DmaapMessageConsumerImpl implements DmaapMessageConsumer {
     @Autowired
     public DmaapMessageConsumerImpl(ApplicationConfig applicationConfig) {
         this.applicationConfig = applicationConfig;
+
+        Thread thread = new Thread(this);
+        thread.start();
+    }
+
+    private boolean isDmaapConfigured() {
+        Properties consumerCfg = applicationConfig.getDmaapConsumerConfig();
+        Properties producerCfg = applicationConfig.getDmaapPublisherConfig();
+        return (consumerCfg != null && consumerCfg.size() > 0 && producerCfg != null && producerCfg.size() > 0);
     }
 
-    @Scheduled(fixedRate = 1000 * 40)
     @Override
     public void run() {
-        if (!alive) {
-            init();
-        }
-        if (this.alive) {
+        while (sleep(TIME_BETWEEN_DMAAP_POLLS) && isDmaapConfigured()) {
             try {
                 Iterable<String> dmaapMsgs = fetchAllMessages();
                 if (dmaapMsgs != null && Iterables.size(dmaapMsgs) > 0) {
@@ -73,61 +81,45 @@ public class DmaapMessageConsumerImpl implements DmaapMessageConsumer {
                 }
             } catch (Exception e) {
                 logger.error("{}: cannot fetch because of ", this, e.getMessage(), e);
+                sleep(ERROR_TIMEOUT);
             }
         }
     }
 
-    private Iterable<String> fetchAllMessages() {
-        MRConsumerResponse response = null;
-        try {
-            response = consumer.fetchWithReturnConsumerResponse();
-        } catch (Exception e) {
-            logger.error("Failed to get message from DMAAP", e);
-        }
+    private Iterable<String> fetchAllMessages() throws ServiceException, FileNotFoundException, IOException {
+        Properties dmaapConsumerProperties = this.applicationConfig.getDmaapConsumerConfig();
+        MRConsumer consumer = MRClientFactory.createConsumer(dmaapConsumerProperties);
+        MRConsumerResponse response = consumer.fetchWithReturnConsumerResponse();
         if (response == null || !"200".equals(response.getResponseCode())) {
-            logger.warn("{}: DMaaP NULL response received", this);
+            throw new ServiceException("DMaaP NULL response received");
         } else {
             logger.debug("DMaaP consumer received {} : {}", response.getResponseCode(), response.getResponseMessage());
+            return response.getActualMessages();
         }
-        return response.getActualMessages();
     }
 
-    @Override
-    public void init() {
-        Properties dmaapConsumerProperties = applicationConfig.getDmaapConsumerConfig();
-        Properties dmaapPublisherProperties = applicationConfig.getDmaapPublisherConfig();
-        // No need to start if there is no configuration.
-        if (dmaapConsumerProperties == null || dmaapPublisherProperties == null || dmaapConsumerProperties.size() == 0
-                || dmaapPublisherProperties.size() == 0) {
-            logger.error("DMaaP properties Failed to Load");
-            return;
-        }
-        try {
-            logger.debug("Creating DMAAP Client");
-            logger.debug("dmaapConsumerProperties---> {}", dmaapConsumerProperties.getProperty("topic"));
-            logger.debug("dmaapPublisherProperties---> {}", dmaapPublisherProperties.getProperty("topic"));
-            consumer = MRClientFactory.createConsumer(dmaapConsumerProperties);
-            producer = MRClientFactory.createBatchingPublisher(dmaapPublisherProperties);
-            this.alive = true;
-        } catch (IOException e) {
-            logger.error("Exception occurred while creating Dmaap Consumer", e);
-        }
-    }
-
-    @Override
-    public void processMsg(String msg) throws Exception {
+    private void processMsg(String msg) throws Exception {
         logger.debug("Message Reveived from DMAAP : {}", msg);
         createDmaapMessageHandler().handleDmaapMsg(msg);
     }
 
-    protected DmaapMessageHandler createDmaapMessageHandler() {
+    private DmaapMessageHandler createDmaapMessageHandler() throws FileNotFoundException, IOException {
         String agentBaseUrl = "http://localhost:" + this.localServerPort;
         AsyncRestClient agentClient = new AsyncRestClient(agentBaseUrl);
-        return new DmaapMessageHandler(this.producer, this.applicationConfig, agentClient);
+        Properties dmaapPublisherProperties = applicationConfig.getDmaapPublisherConfig();
+        MRBatchingPublisher producer = MRClientFactory.createBatchingPublisher(dmaapPublisherProperties);
+
+        return new DmaapMessageHandler(producer, this.applicationConfig, agentClient);
     }
 
-    @Override
-    public boolean isAlive() {
-        return alive;
+    private boolean sleep(Duration duration) {
+        CountDownLatch sleep = new CountDownLatch(1);
+        try {
+            sleep.await(duration.toMillis(), TimeUnit.MILLISECONDS);
+            return true;
+        } catch (Exception e) {
+            logger.error("msg", e);
+            return false;
+        }
     }
 }
index 2d963c3..9b0c809 100644 (file)
@@ -22,7 +22,9 @@ package org.oransc.policyagent.dmaap;
 
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+
 import java.io.IOException;
+
 import org.onap.dmaap.mr.client.MRBatchingPublisher;
 import org.oransc.policyagent.clients.AsyncRestClient;
 import org.oransc.policyagent.configuration.ApplicationConfig;
@@ -37,27 +39,23 @@ public class DmaapMessageHandler {
     private static final Logger logger = LoggerFactory.getLogger(DmaapMessageHandler.class);
 
     private static Gson gson = new GsonBuilder() //
-            .serializeNulls() //
-            .create(); //
+        .serializeNulls() //
+        .create(); //
 
     private final MRBatchingPublisher dmaapClient;
     private final AsyncRestClient agentClient;
 
     public DmaapMessageHandler(MRBatchingPublisher dmaapClient, ApplicationConfig applicationConfig,
-            AsyncRestClient agentClient) {
+        AsyncRestClient agentClient) {
         this.agentClient = agentClient;
         this.dmaapClient = dmaapClient;
     }
 
     public void handleDmaapMsg(String msg) {
-        try {
-            this.createTask(msg) //
-                    .subscribe(x -> logger.debug("handleDmaapMsg: " + x), //
-                            throwable -> logger.warn("handleDmaapMsg failure ", throwable), //
-                            () -> logger.debug("handleDmaapMsg complete"));
-        } catch (Exception e) {
-            logger.warn("Received unparsable message from DMAAP: {}", msg);
-        }
+        this.createTask(msg) //
+            .subscribe(x -> logger.debug("handleDmaapMsg: " + x), //
+                throwable -> logger.warn("handleDmaapMsg failure ", throwable), //
+                () -> logger.debug("handleDmaapMsg complete"));
     }
 
     Mono<String> createTask(String msg) {
@@ -65,8 +63,8 @@ public class DmaapMessageHandler {
             DmaapRequestMessage dmaapRequestMessage = gson.fromJson(msg, ImmutableDmaapRequestMessage.class);
 
             return this.invokePolicyAgent(dmaapRequestMessage) //
-                    .onErrorResume(t -> handleAgentCallError(t, dmaapRequestMessage)) //
-                    .flatMap(response -> sendDmaapResponse(response, dmaapRequestMessage, HttpStatus.OK));
+                .onErrorResume(t -> handleAgentCallError(t, dmaapRequestMessage)) //
+                .flatMap(response -> sendDmaapResponse(response, dmaapRequestMessage, HttpStatus.OK));
 
         } catch (Exception e) {
             logger.warn("Received unparsable message from DMAAP: {}", msg);
@@ -77,7 +75,7 @@ public class DmaapMessageHandler {
     private Mono<String> handleAgentCallError(Throwable t, DmaapRequestMessage dmaapRequestMessage) {
         logger.debug("Agent call failed: " + t.getMessage());
         return sendDmaapResponse(t.toString(), dmaapRequestMessage, HttpStatus.NOT_FOUND) //
-                .flatMap(s -> Mono.empty());
+            .flatMap(s -> Mono.empty());
     }
 
     private Mono<String> invokePolicyAgent(DmaapRequestMessage dmaapRequestMessage) {
@@ -99,10 +97,10 @@ public class DmaapMessageHandler {
     }
 
     private Mono<String> sendDmaapResponse(String response, DmaapRequestMessage dmaapRequestMessage,
-            HttpStatus status) {
+        HttpStatus status) {
         return getDmaapResponseMessage(dmaapRequestMessage, response, status) //
-                .flatMap(body -> sendToDmaap(body)) //
-                .onErrorResume(t -> handleResponseCallError(t, dmaapRequestMessage));
+            .flatMap(body -> sendToDmaap(body)) //
+            .onErrorResume(t -> handleResponseCallError(t, dmaapRequestMessage));
     }
 
     private Mono<String> sendToDmaap(String body) {
@@ -122,16 +120,16 @@ public class DmaapMessageHandler {
     }
 
     private Mono<String> getDmaapResponseMessage(DmaapRequestMessage dmaapRequestMessage, String response,
-            HttpStatus status) {
+        HttpStatus status) {
         DmaapResponseMessage dmaapResponseMessage = ImmutableDmaapResponseMessage.builder() //
-                .status(status.toString()) //
-                .message(response) //
-                .type("response") //
-                .correlationId(dmaapRequestMessage.correlationId()) //
-                .originatorId(dmaapRequestMessage.originatorId()) //
-                .requestId(dmaapRequestMessage.requestId()) //
-                .timestamp(dmaapRequestMessage.timestamp()) //
-                .build();
+            .status(status.toString()) //
+            .message(response) //
+            .type("response") //
+            .correlationId(dmaapRequestMessage.correlationId()) //
+            .originatorId(dmaapRequestMessage.originatorId()) //
+            .requestId(dmaapRequestMessage.requestId()) //
+            .timestamp(dmaapRequestMessage.timestamp()) //
+            .build();
         String str = gson.toJson(dmaapResponseMessage);
 
         return Mono.just(str);
index 220477f..e50a98c 100644 (file)
@@ -36,8 +36,7 @@ import org.oransc.policyagent.configuration.RicConfig;
  */
 public class Ric {
     private final RicConfig ricConfig;
-    @Getter
-    @Setter
+
     private RicState state = RicState.UNDEFINED;
     private Map<String, PolicyType> supportedPolicyTypes = new HashMap<>();
     @Getter
@@ -61,13 +60,21 @@ public class Ric {
         return this.ricConfig;
     }
 
+    public synchronized RicState getState() {
+        return this.state;
+    }
+
+    public synchronized void setState(RicState state) {
+        this.state = state;
+    }
+
     /**
      * Gets the nodes managed by this Ric.
      *
      * @return a vector containing the nodes managed by this Ric.
      */
-    public Vector<String> getManagedElementIds() {
-        return ricConfig.managedElementIds();
+    public synchronized Collection<String> getManagedElementIds() {
+        return new Vector<>(ricConfig.managedElementIds());
     }
 
     /**
@@ -76,7 +83,7 @@ public class Ric {
      * @param managedElementId the node name to check.
      * @return true if the given node is managed by this Ric.
      */
-    public boolean isManaging(String managedElementId) {
+    public synchronized boolean isManaging(String managedElementId) {
         return ricConfig.managedElementIds().contains(managedElementId);
     }
 
@@ -85,7 +92,7 @@ public class Ric {
      *
      * @param managedElementId the node to add.
      */
-    public void addManagedElement(String managedElementId) {
+    public synchronized void addManagedElement(String managedElementId) {
         if (!ricConfig.managedElementIds().contains(managedElementId)) {
             ricConfig.managedElementIds().add(managedElementId);
         }
@@ -96,7 +103,7 @@ public class Ric {
      *
      * @param managedElementId the node to remove.
      */
-    public void removeManagedElement(String managedElementId) {
+    public synchronized void removeManagedElement(String managedElementId) {
         ricConfig.managedElementIds().remove(managedElementId);
     }
 
@@ -105,12 +112,12 @@ public class Ric {
      *
      * @return the policy types supported by this Ric in an unmodifiable list.
      */
-    public Collection<PolicyType> getSupportedPolicyTypes() {
-        return supportedPolicyTypes.values();
+    public synchronized Collection<PolicyType> getSupportedPolicyTypes() {
+        return new Vector<>(supportedPolicyTypes.values());
     }
 
-    public Collection<String> getSupportedPolicyTypeNames() {
-        return supportedPolicyTypes.keySet();
+    public synchronized Collection<String> getSupportedPolicyTypeNames() {
+        return new Vector<>(supportedPolicyTypes.keySet());
     }
 
     /**
@@ -118,14 +125,14 @@ public class Ric {
      *
      * @param type the policy type to support.
      */
-    public void addSupportedPolicyType(PolicyType type) {
+    public synchronized void addSupportedPolicyType(PolicyType type) {
         supportedPolicyTypes.put(type.name(), type);
     }
 
     /**
      * Removes all policy type as supported by this Ric.
      */
-    public void clearSupportedPolicyTypes() {
+    public synchronized void clearSupportedPolicyTypes() {
         supportedPolicyTypes.clear();
     }
 
@@ -136,12 +143,12 @@ public class Ric {
      *
      * @return true if the given type is supported by this Ric, false otherwise.
      */
-    public boolean isSupportingType(String typeName) {
+    public synchronized boolean isSupportingType(String typeName) {
         return supportedPolicyTypes.containsKey(typeName);
     }
 
     @Override
-    public String toString() {
+    public synchronized String toString() {
         return Ric.class.getSimpleName() + ": " + "name: " + name() + ", state: " + state + ", baseUrl: "
             + ricConfig.baseUrl() + ", managedNodes: " + ricConfig.managedElementIds();
     }
index 267fc1f..f5834e3 100644 (file)
@@ -81,9 +81,9 @@ public class RefreshConfigTask {
         stop();
         loadConfigurationFromFile();
         refreshTask = createRefreshTask() //
-            .subscribe(notUsed -> logger.info("Refreshed configuration data"),
+            .subscribe(notUsed -> logger.debug("Refreshed configuration data"),
                 throwable -> logger.error("Configuration refresh terminated due to exception", throwable),
-                () -> logger.error("Configuration refresh terminated"));
+                () -> logger.debug("Configuration refresh completed"));
     }
 
     public void stop() {
index ab25eab..c88eb6c 100644 (file)
@@ -70,7 +70,8 @@ public class RicRecoveryTask {
 
         synchronized (ric) {
             if (ric.getState() == Ric.RicState.RECOVERING) {
-                return; // Already running
+                logger.debug("Recovery ric: {} is already running", ric.getConfig().name());
+                return;
             }
             ric.setState(Ric.RicState.RECOVERING);
         }
index 847cde1..aeeb19a 100644 (file)
@@ -195,6 +195,7 @@ public class ApplicationTest {
 
         Policy policy = addPolicy("policyId", "typeName", "service", "ric"); // This should be created in the RIC
         supervision.checkAllRics(); // The created policy should be put in the RIC
+        await().untilAsserted(() -> RicState.RECOVERING.equals(rics.getRic("ric").getState()));
         await().untilAsserted(() -> RicState.IDLE.equals(rics.getRic("ric").getState()));
 
         Policies ricPolicies = getA1Client("ric").getPolicies();
@@ -464,6 +465,18 @@ public class ApplicationTest {
         assertThat(entity.getStatusCode().equals(HttpStatus.NOT_FOUND));
     }
 
+    @Test
+    public void testGetPolicyStatus() throws Exception {
+        reset();
+        Policy policy = addPolicy("id", "typeName", "service1", "ric1");
+        policy.ric().setState(Ric.RicState.IDLE);
+        assertThat(policies.size()).isEqualTo(1);
+
+        String url = baseUrl() + "/policy_status?instance=id";
+        String rsp = this.restTemplate.getForObject(url, String.class);
+        assertThat(rsp.equals("OK"));
+    }
+
     private static <T> List<T> parseList(String jsonString, Class<T> clazz) {
         List<T> result = new ArrayList<>();
         JsonArray jsonArr = JsonParser.parseString(jsonString).getAsJsonArray();
index 3444540..531f1e8 100644 (file)
@@ -22,12 +22,14 @@ package org.oransc.policyagent.configuration;
 
 import static org.junit.jupiter.api.Assertions.assertAll;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+
 import com.google.common.base.Charsets;
 import com.google.common.io.Resources;
 import com.google.gson.JsonIOException;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import com.google.gson.JsonSyntaxException;
+
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -35,6 +37,7 @@ import java.io.InputStreamReader;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.util.Properties;
+
 import org.junit.jupiter.api.Test;
 import org.onap.dmaap.mr.test.clients.ProtocolTypeConstants;
 import org.springframework.http.MediaType;
index 5aeb240..71c8500 100644 (file)
@@ -27,9 +27,12 @@ import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
+
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+
 import java.io.IOException;
+
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.onap.dmaap.mr.client.MRBatchingPublisher;
@@ -37,6 +40,7 @@ import org.onap.dmaap.mr.client.response.MRPublisherResponse;
 import org.oransc.policyagent.clients.AsyncRestClient;
 import org.oransc.policyagent.configuration.ApplicationConfig;
 import org.oransc.policyagent.dmaap.DmaapRequestMessage.Operation;
+
 import reactor.core.publisher.Mono;
 import reactor.test.StepVerifier;
 
index 1151dd2..f10c66f 100644 (file)
@@ -99,4 +99,9 @@ public class MockA1Client implements A1Client {
         return Flux.empty();
     }
 
+    @Override
+    public Mono<String> getPolicyStatus(Policy policy) {
+        return Mono.just("OK");
+    }
+
 }