Added status controller

Change-Id: I6ee63a6d9a0cb5b0003a8f2b907abdcc14374faf
Issue-ID: NONRTRIC-173
Signed-off-by: PatrikBuhr <patrik.buhr@est.tech>
diff --git a/enrichment-coordinator-service/docs/api.json b/enrichment-coordinator-service/docs/api.json
index e4f7660..76be3a4 100644
--- a/enrichment-coordinator-service/docs/api.json
+++ b/enrichment-coordinator-service/docs/api.json
@@ -285,6 +285,22 @@
             }],
             "tags": ["Enrichment Data Producer API"]
         }},
+        "/status": {"get": {
+            "summary": "Returns status and statistics of this service",
+            "deprecated": false,
+            "produces": ["application/json"],
+            "operationId": "getStatusUsingGET",
+            "responses": {
+                "200": {
+                    "schema": {"$ref": "#/definitions/status_info"},
+                    "description": "Service is living"
+                },
+                "401": {"description": "Unauthorized"},
+                "403": {"description": "Forbidden"},
+                "404": {"description": "Not Found"}
+            },
+            "tags": ["Service status"]
+        }},
         "/producer_simulator/job_created_error": {"post": {
             "summary": "Callback for EI job creation, returns error",
             "deprecated": false,
@@ -554,7 +570,7 @@
             "consumes": ["application/json"]
         }}
     },
-    "host": "localhost:43453",
+    "host": "localhost:40973",
     "definitions": {
         "EiType": {
             "description": "Information for an EI type",
@@ -652,6 +668,31 @@
                 }
             }
         },
+        "status_info": {
+            "type": "object",
+            "title": "status_info",
+            "properties": {
+                "no_of_producers": {
+                    "format": "int32",
+                    "description": "Number of EI producers",
+                    "type": "integer"
+                },
+                "no_of_jobs": {
+                    "format": "int32",
+                    "description": "Number of EI jobs",
+                    "type": "integer"
+                },
+                "no_of_types": {
+                    "format": "int32",
+                    "description": "Number of EI types",
+                    "type": "integer"
+                },
+                "status": {
+                    "description": "status text",
+                    "type": "string"
+                }
+            }
+        },
         "EiJobStatus": {
             "description": "Status for an EI Job",
             "type": "object",
@@ -749,6 +790,10 @@
         {
             "name": "Producer Simulator",
             "description": "Producer Simulator Controller"
+        },
+        {
+            "name": "Service status",
+            "description": "Status Controller"
         }
     ]
 }
\ No newline at end of file
diff --git a/enrichment-coordinator-service/docs/api.yaml b/enrichment-coordinator-service/docs/api.yaml
index f3fa767..48a65dd 100644
--- a/enrichment-coordinator-service/docs/api.yaml
+++ b/enrichment-coordinator-service/docs/api.yaml
@@ -317,6 +317,26 @@
           required: true
       tags:
         - Enrichment Data Producer API
+  /status:
+    get:
+      summary: Returns status and statistics of this service
+      deprecated: false
+      produces:
+        - application/json
+      operationId: getStatusUsingGET
+      responses:
+        '200':
+          schema:
+            $ref: '#/definitions/status_info'
+          description: Service is living
+        '401':
+          description: Unauthorized
+        '403':
+          description: Forbidden
+        '404':
+          description: Not Found
+      tags:
+        - Service status
   /producer_simulator/job_created_error:
     post:
       summary: 'Callback for EI job creation, returns error'
@@ -599,7 +619,7 @@
         - Producer Simulator
       consumes:
         - application/json
-host: 'localhost:43453'
+host: 'localhost:40973'
 definitions:
   EiType:
     description: Information for an EI type
@@ -677,6 +697,25 @@
       ei_job_data_schema:
         description: Json schema for the job data
         type: object
+  status_info:
+    type: object
+    title: status_info
+    properties:
+      no_of_producers:
+        format: int32
+        description: Number of EI producers
+        type: integer
+      no_of_jobs:
+        format: int32
+        description: Number of EI jobs
+        type: integer
+      no_of_types:
+        format: int32
+        description: Number of EI types
+        type: integer
+      status:
+        description: status text
+        type: string
   EiJobStatus:
     description: Status for an EI Job
     type: object
@@ -761,4 +800,6 @@
     description: Producer Controller
   - name: Producer Simulator
     description: Producer Simulator Controller
+  - name: Service status
+    description: Status Controller
 
diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/StatusController.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/StatusController.java
new file mode 100644
index 0000000..a210aa5
--- /dev/null
+++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/StatusController.java
@@ -0,0 +1,99 @@
+/*-
+ * ========================LICENSE_START=================================
+ * ONAP : ccsdk oran
+ * ======================================================================
+ * Copyright (C) 2020 Nordix Foundation. All rights reserved.
+ * ======================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.enrichment.controllers;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+import org.immutables.gson.Gson;
+import org.oransc.enrichment.repository.EiJobs;
+import org.oransc.enrichment.repository.EiProducers;
+import org.oransc.enrichment.repository.EiTypes;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Mono;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+
+@RestController("StatusController")
+@Api(tags = "Service status")
+public class StatusController {
+
+    @Autowired
+    private EiJobs eiJobs;
+
+    @Autowired
+    private EiTypes eiTypes;
+
+    @Autowired
+    private EiProducers eiProducers;
+
+    @Gson.TypeAdapters
+    @ApiModel(value = "status_info")
+    public static class StatusInfo {
+        @ApiModelProperty(value = "status text")
+        @SerializedName("status")
+        @JsonProperty(value = "status", required = true)
+        public final String status;
+
+        @ApiModelProperty(value = "Number of EI producers")
+        @SerializedName("no_of_producers")
+        @JsonProperty(value = "no_of_producers", required = true)
+        public final int noOfProducers;
+
+        @ApiModelProperty(value = "Number of EI types")
+        @SerializedName("no_of_types")
+        @JsonProperty(value = "no_of_types", required = true)
+        public final int noOfTypes;
+
+        @ApiModelProperty(value = "Number of EI jobs")
+        @SerializedName("no_of_jobs")
+        @JsonProperty(value = "no_of_jobs", required = true)
+        public final int noOfJobs;
+
+        public StatusInfo(String status, EiProducers producers, EiTypes types, EiJobs jobs) {
+            this.status = status;
+            this.noOfJobs = jobs.size();
+            this.noOfProducers = producers.size();
+            this.noOfTypes = types.size();
+        }
+    }
+
+    @GetMapping(path = "/status", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation(value = "Returns status and statistics of this service")
+    @ApiResponses(value = { //
+            @ApiResponse(code = 200, message = "Service is living", response = StatusInfo.class) //
+    })
+    public Mono<ResponseEntity<Object>> getStatus() {
+        StatusInfo info = new StatusInfo("hunky dory", this.eiProducers, this.eiTypes, this.eiJobs);
+        return Mono.just(new ResponseEntity<>(info, HttpStatus.OK));
+    }
+
+}
diff --git a/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/ApplicationTest.java b/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/ApplicationTest.java
index 67b0d8a..d8a0b32 100644
--- a/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/ApplicationTest.java
+++ b/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/ApplicationTest.java
@@ -82,10 +82,9 @@
 
 @ExtendWith(SpringExtension.class)
 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
-@TestPropertySource(
-    properties = { //
+@TestPropertySource(properties = { //
         "server.ssl.key-store=./config/keystore.jks", //
-        "app.webclient.trust-store=./config/truststore.jks"})
+        "app.webclient.trust-store=./config/truststore.jks" })
 class ApplicationTest {
     private final String EI_TYPE_ID = "typeId";
     private final String EI_PRODUCER_ID = "producerId";
@@ -113,8 +112,8 @@
     ProducerSupervision producerSupervision;
 
     private static Gson gson = new GsonBuilder() //
-        .serializeNulls() //
-        .create(); //
+            .serializeNulls() //
+            .create(); //
 
     /**
      * Overrides the BeanFactory.
@@ -284,8 +283,8 @@
 
         String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
         // The element with name "property1" is mandatory in the schema
-        ConsumerEiJobInfo jobInfo =
-            new ConsumerEiJobInfo(jsonObject("{ \"XXstring\" : \"value\" }"), "owner", "targetUri");
+        ConsumerEiJobInfo jobInfo = new ConsumerEiJobInfo(jsonObject("{ \"XXstring\" : \"value\" }"), "owner",
+                "targetUri");
         String body = gson.toJson(jobInfo);
 
         testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT, "Json validation failure");
@@ -329,7 +328,7 @@
         String url = ConsumerConsts.API_ROOT + "/eitypes/typeId2/eijobs/jobId";
         String body = gson.toJson(eiJobInfo());
         testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT,
-            "Not allowed to change type for existing EI job");
+                "Not allowed to change type for existing EI job");
     }
 
     @Test
@@ -448,7 +447,7 @@
     }
 
     private void assertProducerOpState(String producerId,
-        ProducerStatusInfo.OperationalState expectedOperationalState) {
+            ProducerStatusInfo.OperationalState expectedOperationalState) {
         String statusUrl = ProducerConsts.API_ROOT + "/eiproducers/" + producerId + "/status";
         ResponseEntity<String> resp = restClient().getForEntity(statusUrl).block();
         ProducerStatusInfo statusInfo = gson.fromJson(resp.getBody(), ProducerStatusInfo.class);
@@ -474,29 +473,39 @@
         assertThat(this.eiTypes.size()).isEqualTo(0);
     }
 
+    @Test
+    void testGetStatus() throws JsonMappingException, JsonProcessingException, ServiceException {
+        putEiProducerWithOneTypeRejecting("simulateProducerError", EI_TYPE_ID);
+        putEiProducerWithOneTypeRejecting("simulateProducerError2", EI_TYPE_ID);
+
+        String url = "/status";
+        ResponseEntity<String> resp = restClient().getForEntity(url).block();
+        assertThat(resp.getBody()).contains("hunky dory");
+    }
+
     ProducerEiTypeRegistrationInfo producerEiTypeRegistrationInfo(String typeId)
-        throws JsonMappingException, JsonProcessingException {
+            throws JsonMappingException, JsonProcessingException {
         return new ProducerEiTypeRegistrationInfo(jsonSchemaObject(), typeId);
     }
 
     ProducerRegistrationInfo producerEiRegistratioInfoRejecting(String typeId)
-        throws JsonMappingException, JsonProcessingException {
+            throws JsonMappingException, JsonProcessingException {
         Collection<ProducerEiTypeRegistrationInfo> types = new ArrayList<>();
         types.add(producerEiTypeRegistrationInfo(typeId));
         return new ProducerRegistrationInfo(types, //
-            baseUrl() + ProducerSimulatorController.JOB_CREATED_ERROR_URL,
-            baseUrl() + ProducerSimulatorController.JOB_DELETED_ERROR_URL,
-            baseUrl() + ProducerSimulatorController.SUPERVISION_ERROR_URL);
+                baseUrl() + ProducerSimulatorController.JOB_CREATED_ERROR_URL,
+                baseUrl() + ProducerSimulatorController.JOB_DELETED_ERROR_URL,
+                baseUrl() + ProducerSimulatorController.SUPERVISION_ERROR_URL);
     }
 
     ProducerRegistrationInfo producerEiRegistratioInfo(String typeId)
-        throws JsonMappingException, JsonProcessingException {
+            throws JsonMappingException, JsonProcessingException {
         Collection<ProducerEiTypeRegistrationInfo> types = new ArrayList<>();
         types.add(producerEiTypeRegistrationInfo(typeId));
         return new ProducerRegistrationInfo(types, //
-            baseUrl() + ProducerSimulatorController.JOB_CREATED_URL,
-            baseUrl() + ProducerSimulatorController.JOB_DELETED_URL,
-            baseUrl() + ProducerSimulatorController.SUPERVISION_URL);
+                baseUrl() + ProducerSimulatorController.JOB_CREATED_URL,
+                baseUrl() + ProducerSimulatorController.JOB_DELETED_URL,
+                baseUrl() + ProducerSimulatorController.SUPERVISION_URL);
     }
 
     ConsumerEiJobInfo eiJobInfo() throws JsonMappingException, JsonProcessingException {
@@ -514,17 +523,17 @@
     Object jsonSchemaObject() {
         // a json schema with one mandatory property named "string"
         String schemaStr = "{" //
-            + "\"$schema\": \"http://json-schema.org/draft-04/schema#\"," //
-            + "\"type\": \"object\"," //
-            + "\"properties\": {" //
-            + EI_JOB_PROPERTY + " : {" //
-            + "    \"type\": \"string\"" //
-            + "  }" //
-            + "}," //
-            + "\"required\": [" //
-            + EI_JOB_PROPERTY //
-            + "]" //
-            + "}"; //
+                + "\"$schema\": \"http://json-schema.org/draft-04/schema#\"," //
+                + "\"type\": \"object\"," //
+                + "\"properties\": {" //
+                + EI_JOB_PROPERTY + " : {" //
+                + "    \"type\": \"string\"" //
+                + "  }" //
+                + "}," //
+                + "\"required\": [" //
+                + EI_JOB_PROPERTY //
+                + "]" //
+                + "}"; //
         return jsonObject(schemaStr);
     }
 
@@ -533,7 +542,7 @@
     }
 
     private EiJob putEiJob(String eiTypeId, String jobId)
-        throws JsonMappingException, JsonProcessingException, ServiceException {
+            throws JsonMappingException, JsonProcessingException, ServiceException {
 
         String url = ConsumerConsts.API_ROOT + "/eitypes/" + eiTypeId + "/eijobs/" + jobId;
         String body = gson.toJson(eiJobInfo());
@@ -543,7 +552,7 @@
     }
 
     private EiType putEiProducerWithOneTypeRejecting(String producerId, String eiTypeId)
-        throws JsonMappingException, JsonProcessingException, ServiceException {
+            throws JsonMappingException, JsonProcessingException, ServiceException {
         String url = ProducerConsts.API_ROOT + "/eiproducers/" + producerId;
         String body = gson.toJson(producerEiRegistratioInfoRejecting(eiTypeId));
 
@@ -552,7 +561,7 @@
     }
 
     private EiType putEiProducerWithOneType(String producerId, String eiTypeId)
-        throws JsonMappingException, JsonProcessingException, ServiceException {
+            throws JsonMappingException, JsonProcessingException, ServiceException {
         String url = ProducerConsts.API_ROOT + "/eiproducers/" + producerId;
         String body = gson.toJson(producerEiRegistratioInfo(eiTypeId));
 
@@ -567,14 +576,14 @@
     private AsyncRestClient restClient(boolean useTrustValidation) {
         WebClientConfig config = this.applicationConfig.getWebClientConfig();
         config = ImmutableWebClientConfig.builder() //
-            .keyStoreType(config.keyStoreType()) //
-            .keyStorePassword(config.keyStorePassword()) //
-            .keyStore(config.keyStore()) //
-            .keyPassword(config.keyPassword()) //
-            .isTrustStoreUsed(useTrustValidation) //
-            .trustStore(config.trustStore()) //
-            .trustStorePassword(config.trustStorePassword()) //
-            .build();
+                .keyStoreType(config.keyStoreType()) //
+                .keyStorePassword(config.keyStorePassword()) //
+                .keyStore(config.keyStore()) //
+                .keyPassword(config.keyPassword()) //
+                .isTrustStoreUsed(useTrustValidation) //
+                .trustStore(config.trustStore()) //
+                .trustStorePassword(config.trustStorePassword()) //
+                .build();
 
         return new AsyncRestClient(baseUrl(), config);
     }
@@ -588,16 +597,16 @@
     }
 
     private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains,
-        boolean expectApplicationProblemJsonMediaType) {
+            boolean expectApplicationProblemJsonMediaType) {
         StepVerifier.create(request) //
-            .expectSubscription() //
-            .expectErrorMatches(
-                t -> checkWebClientError(t, expStatus, responseContains, expectApplicationProblemJsonMediaType)) //
-            .verify();
+                .expectSubscription() //
+                .expectErrorMatches(
+                        t -> checkWebClientError(t, expStatus, responseContains, expectApplicationProblemJsonMediaType)) //
+                .verify();
     }
 
     private boolean checkWebClientError(Throwable throwable, HttpStatus expStatus, String responseContains,
-        boolean expectApplicationProblemJsonMediaType) {
+            boolean expectApplicationProblemJsonMediaType) {
         assertTrue(throwable instanceof WebClientResponseException);
         WebClientResponseException responseException = (WebClientResponseException) throwable;
         assertThat(responseException.getStatusCode()).isEqualTo(expStatus);