Merge "Implement graceful shutdown of consumer"
authorHenrik Andersson <henrik.b.andersson@est.tech>
Fri, 22 Oct 2021 12:51:31 +0000 (12:51 +0000)
committerGerrit Code Review <gerrit@o-ran-sc.org>
Fri, 22 Oct 2021 12:51:31 +0000 (12:51 +0000)
28 files changed:
docker-compose/docker-compose-policy-framework/config/db/bootstrap-database.sh
docker-compose/docker-compose-policy-framework/config/pap/defaultConfig.json
docker-compose/docker-compose-policy-framework/config/runtime-controlloop/ClRuntimeParameters.json [deleted file]
docker-compose/docker-compose-policy-framework/docker-compose.yml
enrichment-coordinator-service/api/ecs-api.json
enrichment-coordinator-service/api/ecs-api.yaml
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eController.java
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerController.java
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerController.java
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/exceptions/ServiceException.java
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/InfoJobs.java
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/InfoProducers.java
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/InfoTypeSubscriptions.java
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/InfoTypes.java
enrichment-coordinator-service/src/test/java/org/oransc/enrichment/ApplicationTest.java
onap/oran
test/usecases/oruclosedlooprecovery/apexpolicyversion/LinkMonitor/controlloop-rest-payloads/commission.yaml
test/usecases/oruclosedlooprecovery/apexpolicyversion/LinkMonitor/controlloop-rest-payloads/instantiation-command.json
test/usecases/oruclosedlooprecovery/apexpolicyversion/LinkMonitor/controlloop-rest-payloads/instantiation.json
test/usecases/oruclosedlooprecovery/apexpolicyversion/LinkMonitor/docker-compose-controlloop/config/ks.jks [new file with mode: 0644]
test/usecases/oruclosedlooprecovery/apexpolicyversion/LinkMonitor/docker-compose-controlloop/docker-compose.yml [new file with mode: 0644]
test/usecases/oruclosedlooprecovery/apexpolicyversion/LinkMonitor/docker-compose-controlloop/wait_for_port.sh [new file with mode: 0755]
test/usecases/oruclosedlooprecovery/scriptversion/controlloop-rest-payloads/commission.yaml
test/usecases/oruclosedlooprecovery/scriptversion/controlloop-rest-payloads/instantiation-command.json
test/usecases/oruclosedlooprecovery/scriptversion/controlloop-rest-payloads/instantiation.json
test/usecases/oruclosedlooprecovery/scriptversion/docker-compose-controlloop/config/db/bootstrap-database.sh
test/usecases/oruclosedlooprecovery/scriptversion/docker-compose-controlloop/docker-compose.yml
test/usecases/oruclosedlooprecovery/scriptversion/docker-compose-controlloop/wait_for_port.sh [new file with mode: 0755]

index ac2d0a5..6a6310d 100755 (executable)
@@ -24,5 +24,5 @@
 ###
 
 mysql -uroot -p$MYSQL_ROOT_PASSWORD -f < /docker-entrypoint-initdb.d/create-db.sql
-mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "CREATE USER 'policy'@'%' IDENTIFIED BY 'P01icY';"
-mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "GRANT ALL PRIVILEGES ON controlloop.* TO 'policy'@'%';"
\ No newline at end of file
+mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "CREATE USER 'policy_user'@'%' IDENTIFIED BY 'policy_user';"
+mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "GRANT ALL PRIVILEGES ON controlloop.* TO 'policy_user'@'%';"
\ No newline at end of file
index 8c4ea64..1890dae 100644 (file)
@@ -5,7 +5,7 @@
         "port": 6969,
         "userName": "healthcheck",
         "password": "zb!XztG34",
-        "https": true,
+        "https": false,
         "aaf": false
     },
     "pdpParameters": {
diff --git a/docker-compose/docker-compose-policy-framework/config/runtime-controlloop/ClRuntimeParameters.json b/docker-compose/docker-compose-policy-framework/config/runtime-controlloop/ClRuntimeParameters.json
deleted file mode 100644 (file)
index 429e1af..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-{
-    "name": "ControlLoopRuntimeGroup",
-    "supervisionScannerIntervalSec": 1000,
-    "participantStateChangeIntervalSec": 1000,
-    "participantClUpdateIntervalSec": 1000,
-    "participantClStateChangeIntervalSec": 1000,
-    "restServerParameters": {
-        "host": "0.0.0.0",
-        "port": 6969,
-        "userName": "healthcheck",
-        "password": "zb!XztG34",
-        "https": true,
-        "aaf": false
-    },
-    "participantParameters": {
-        "heartBeatMs": 120000,
-        "updateParameters": {
-            "maxRetryCount": 1,
-            "maxWaitMs": 30000
-        },
-        "stateChangeParameters": {
-            "maxRetryCount": 1,
-            "maxWaitMs": 30000
-        }
-    },
-    "databaseProviderParameters": {
-        "name": "PolicyProviderParameterGroup",
-        "implementation": "org.onap.policy.models.provider.impl.DatabasePolicyModelsProviderImpl",
-        "databaseDriver": "org.mariadb.jdbc.Driver",
-        "databaseUrl": "jdbc:mariadb://localhost:3306/controlloop",
-        "databaseUser": "policy",
-        "databasePassword": "P01icY",
-        "persistenceUnit": "CommissioningMariaDb"
-    },
-    "topicParameterGroup": {
-        "topicSources": [
-            {
-                "topic": "POLICY-CLRUNTIME-PARTICIPANT",
-                "servers": [
-                    "localhost"
-                ],
-                "topicCommInfrastructure": "dmaap",
-                "fetchTimeout": 15000
-            }
-        ],
-        "topicSinks": [
-            {
-                "topic": "POLICY-CLRUNTIME-PARTICIPANT",
-                "servers": [
-                    "localhost"
-                ],
-                "topicCommInfrastructure": "dmaap"
-            },
-            {
-                "topic": "POLICY-NOTIFICATION",
-                "servers": [
-                    "localhost"
-                ],
-                "topicCommInfrastructure": "dmaap"
-            }
-        ]
-    }
-}
index 4878357..894b117 100644 (file)
@@ -145,7 +145,7 @@ services:
         'pap', '6969'
         ]
    apex-pdp:
-      image: registry.nordix.org/onap/policy-apex-pdp:2.6.0-SNAPSHOT
+      image: nexus3.onap.org:10001/onap/policy-apex-pdp:2.5.4
       container_name: policy-apex-pdp
       depends_on:
        - mariadb
index 0e8164e..7da2270 100644 (file)
                         "description": "Information type is not found",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
                     },
-                    "406": {
+                    "409": {
                         "description": "The Information type has one or several active producers",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
                     }
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
                     },
                     "400": {
-                        "description": "Bad request",
+                        "description": "Input validation failed",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
                     }
                 },
                         "description": "Producer created",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
                     },
+                    "400": {
+                        "description": "Input validation failed",
+                        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+                    },
                     "404": {
-                        "description": "Producer not found",
+                        "description": "Producer type not found",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
                     }
                 },
                         "description": "Job created",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
                     },
+                    "400": {
+                        "description": "Input validation failed",
+                        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+                    },
                     "404": {
                         "description": "Enrichment Information type is not found",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+                    },
+                    "409": {
+                        "description": "Cannot modify job type",
+                        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
                     }
                 },
                 "parameters": [{
                         "description": "Job created",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
                     },
+                    "400": {
+                        "description": "Input validation failed",
+                        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+                    },
                     "404": {
                         "description": "Information type is not found",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+                    },
+                    "409": {
+                        "description": "Cannot modify job type",
+                        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
                     }
                 },
                 "parameters": [
index 3445ede..c4463b0 100644 (file)
@@ -189,7 +189,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/Void'
         400:
-          description: Bad request
+          description: Input validation failed
           content:
             application/json:
               schema:
@@ -226,7 +226,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/ProblemDetails'
-        406:
+        409:
           description: The Information type has one or several active producers
           content:
             application/json:
@@ -429,8 +429,14 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/Void'
+        400:
+          description: Input validation failed
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ProblemDetails'
         404:
-          description: Producer not found
+          description: Producer type not found
           content:
             application/json:
               schema:
@@ -564,12 +570,24 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/Void'
+        400:
+          description: Input validation failed
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ProblemDetails'
         404:
           description: Enrichment Information type is not found
           content:
             application/json:
               schema:
                 $ref: '#/components/schemas/ProblemDetails'
+        409:
+          description: Cannot modify job type
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ProblemDetails'
     delete:
       tags:
       - A1-EI (registration)
@@ -711,12 +729,24 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/Void'
+        400:
+          description: Input validation failed
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ProblemDetails'
         404:
           description: Information type is not found
           content:
             application/json:
               schema:
                 $ref: '#/components/schemas/ProblemDetails'
+        409:
+          description: Cannot modify job type
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ProblemDetails'
     delete:
       tags:
       - Data consumer
index 5f796b8..9609e27 100644 (file)
@@ -277,8 +277,18 @@ public class A1eController {
             @ApiResponse(
                 responseCode = "404",
                 description = "Enrichment Information type is not found", //
-                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) //
+                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))),
+            @ApiResponse(
+                responseCode = "400",
+                description = "Input validation failed", //
+                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))), //
+            @ApiResponse(
+                responseCode = "409",
+                description = "Cannot modify job type", //
+                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class)))
+
         })
+
     public Mono<ResponseEntity<Object>> putIndividualEiJob( //
         @PathVariable("eiJobId") String eiJobId, //
         @RequestBody A1eEiJobInfo eiJobObject) {
@@ -289,7 +299,7 @@ public class A1eController {
             .flatMap(this::startEiJob) //
             .doOnNext(newEiJob -> this.eiJobs.put(newEiJob)) //
             .flatMap(newEiJob -> Mono.just(new ResponseEntity<>(isNewJob ? HttpStatus.CREATED : HttpStatus.OK)))
-            .onErrorResume(throwable -> Mono.just(ErrorResponse.create(throwable, HttpStatus.NOT_FOUND)));
+            .onErrorResume(throwable -> Mono.just(ErrorResponse.create(throwable, HttpStatus.INTERNAL_SERVER_ERROR)));
     }
 
     private Mono<InfoJob> startEiJob(InfoJob newEiJob) {
@@ -320,7 +330,7 @@ public class A1eController {
         if (url != null && !url.isEmpty()) {
             URI uri = new URI(url);
             if (!uri.isAbsolute()) {
-                throw new ServiceException("URI: " + url + " is not absolute", HttpStatus.CONFLICT);
+                throw new ServiceException("URI: " + url + " is not absolute", HttpStatus.BAD_REQUEST);
             }
         }
     }
@@ -338,7 +348,7 @@ public class A1eController {
                 JSONObject json = new JSONObject(objectAsString);
                 schema.validate(json);
             } catch (Exception e) {
-                throw new ServiceException("Json validation failure " + e.toString(), HttpStatus.CONFLICT);
+                throw new ServiceException("Json validation failure " + e.toString(), HttpStatus.BAD_REQUEST);
             }
         }
     }
index 9de57d5..47a4a2e 100644 (file)
@@ -282,8 +282,15 @@ public class ConsumerController {
             @ApiResponse(
                 responseCode = "404",
                 description = "Information type is not found", //
-                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) //
-        })
+                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))), //
+            @ApiResponse(
+                responseCode = "400",
+                description = "Input validation failed", //
+                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))), //
+            @ApiResponse(
+                responseCode = "409",
+                description = "Cannot modify job type", //
+                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class)))})
     public Mono<ResponseEntity<Object>> putIndividualInfoJob( //
         @PathVariable("infoJobId") String jobId, //
         @Parameter(
@@ -460,7 +467,7 @@ public class ConsumerController {
         if (url != null && !url.isEmpty()) {
             URI uri = new URI(url);
             if (!uri.isAbsolute()) {
-                throw new ServiceException("URI: " + url + " is not absolute", HttpStatus.CONFLICT);
+                throw new ServiceException("URI: " + url + " is not absolute", HttpStatus.BAD_REQUEST);
             }
         }
     }
@@ -478,7 +485,7 @@ public class ConsumerController {
                 JSONObject json = new JSONObject(objectAsString);
                 schema.validate(json);
             } catch (Exception e) {
-                throw new ServiceException("Json validation failure " + e.toString(), HttpStatus.CONFLICT);
+                throw new ServiceException("Json validation failure " + e.toString(), HttpStatus.BAD_REQUEST);
             }
         }
     }
index 0aa6974..cad6a04 100644 (file)
@@ -138,7 +138,7 @@ public class ProducerController {
                 content = @Content(schema = @Schema(implementation = VoidResponse.class))), //
             @ApiResponse(
                 responseCode = "400",
-                description = "Bad request", //
+                description = "Input validation failed", //
                 content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class)))})
     @Operation(summary = "Individual Information Type", description = "")
     public ResponseEntity<Object> putInfoType( //
@@ -175,7 +175,7 @@ public class ProducerController {
                 description = "Information type is not found", //
                 content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))), //
             @ApiResponse(
-                responseCode = "406",
+                responseCode = "409",
                 description = "The Information type has one or several active producers", //
                 content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) //
         })
@@ -188,7 +188,7 @@ public class ProducerController {
         }
         if (!this.infoProducers.getProducersForType(type).isEmpty()) {
             String firstProducerId = this.infoProducers.getProducersForType(type).iterator().next().getId();
-            return ErrorResponse.create("The type has active producers: " + firstProducerId, HttpStatus.NOT_ACCEPTABLE);
+            return ErrorResponse.create("The type has active producers: " + firstProducerId, HttpStatus.CONFLICT);
         }
         this.infoTypes.remove(type);
         infoJobs.getJobsForType(type).forEach(job -> infoJobs.remove(job, infoProducers)); // Delete jobs for the type
@@ -329,7 +329,11 @@ public class ProducerController {
                 content = @Content(schema = @Schema(implementation = VoidResponse.class))), //
             @ApiResponse(
                 responseCode = "404",
-                description = "Producer not found", //
+                description = "Producer type not found", //
+                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))), //
+            @ApiResponse(
+                responseCode = "400",
+                description = "Input validation failed", //
                 content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) //
         })
     public ResponseEntity<Object> putInfoProducer( //
@@ -341,19 +345,23 @@ public class ProducerController {
             InfoProducer previousDefinition = this.infoProducers.get(infoProducerId);
             this.infoProducers.registerProducer(toProducerRegistrationInfo(infoProducerId, registrationInfo));
             return new ResponseEntity<>(previousDefinition == null ? HttpStatus.CREATED : HttpStatus.OK);
-        } catch (Exception e) {
-            return ErrorResponse.create(e, HttpStatus.NOT_FOUND);
+        } catch (ServiceException e) {
+            return ErrorResponse.create(e, e.getHttpStatus());
         }
     }
 
-    private void validateUri(String url) throws URISyntaxException, ServiceException {
+    private void validateUri(String url) throws ServiceException {
         if (url != null && !url.isEmpty()) {
-            URI uri = new URI(url);
-            if (!uri.isAbsolute()) {
-                throw new ServiceException("URI: " + url + " is not absolute", HttpStatus.CONFLICT);
+            try {
+                URI uri = new URI(url);
+                if (!uri.isAbsolute()) {
+                    throw new ServiceException("URI: " + url + " is not absolute", HttpStatus.BAD_REQUEST);
+                }
+            } catch (URISyntaxException e) {
+                throw new ServiceException(e.getMessage(), HttpStatus.BAD_REQUEST);
             }
         } else {
-            throw new ServiceException("Missing required URL", HttpStatus.CONFLICT);
+            throw new ServiceException("Missing required URL", HttpStatus.BAD_REQUEST);
         }
     }
 
@@ -381,8 +389,8 @@ public class ProducerController {
             final InfoProducer producer = this.infoProducers.getProducer(infoProducerId);
             this.infoProducers.deregisterProducer(producer);
             return new ResponseEntity<>(HttpStatus.NO_CONTENT);
-        } catch (Exception e) {
-            return ErrorResponse.create(e, HttpStatus.NOT_FOUND);
+        } catch (ServiceException e) {
+            return ErrorResponse.create(e, e.getHttpStatus());
         }
     }
 
index ffccf80..bce786f 100644 (file)
@@ -28,11 +28,6 @@ public class ServiceException extends Exception {
     @Getter
     private final HttpStatus httpStatus;
 
-    public ServiceException(String message) {
-        super(message);
-        this.httpStatus = null;
-    }
-
     public ServiceException(String message, Exception originalException) {
         super(message, originalException);
         this.httpStatus = null;
index 52fa1d6..7469e08 100644 (file)
@@ -43,6 +43,7 @@ import org.oransc.enrichment.controllers.r1producer.ProducerCallbacks;
 import org.oransc.enrichment.exceptions.ServiceException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
 import org.springframework.util.FileSystemUtils;
 
 /**
@@ -91,7 +92,7 @@ public class InfoJobs {
     public synchronized InfoJob getJob(String id) throws ServiceException {
         InfoJob ric = allEiJobs.get(id);
         if (ric == null) {
-            throw new ServiceException("Could not find Information job: " + id);
+            throw new ServiceException("Could not find Information job: " + id, HttpStatus.NOT_FOUND);
         }
         return ric;
     }
index 57e7922..1102e36 100644 (file)
@@ -36,6 +36,7 @@ import org.oransc.enrichment.exceptions.ServiceException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Component;
 
 /**
@@ -110,7 +111,7 @@ public class InfoProducers {
     public synchronized InfoProducer getProducer(String id) throws ServiceException {
         InfoProducer p = allEiProducers.get(id);
         if (p == null) {
-            throw new ServiceException("Could not find Information Producer: " + id);
+            throw new ServiceException("Could not find Information Producer: " + id, HttpStatus.NOT_FOUND);
         }
         return p;
     }
index 2d6da4f..65978e1 100644 (file)
@@ -47,6 +47,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
 import org.springframework.util.FileSystemUtils;
 
 import reactor.core.publisher.Flux;
@@ -118,7 +119,7 @@ public class InfoTypeSubscriptions {
     public synchronized SubscriptionInfo getSubscription(String id) throws ServiceException {
         SubscriptionInfo p = allSubscriptions.get(id);
         if (p == null) {
-            throw new ServiceException("Could not find Information subscription: " + id);
+            throw new ServiceException("Could not find Information subscription: " + id, HttpStatus.NOT_FOUND);
         }
         return p;
     }
@@ -196,7 +197,8 @@ public class InfoTypeSubscriptions {
 
                 private Mono<String> error() {
                     return Mono.error(new ServiceException(
-                        "No notifyTypeRegistered handler found for interface version " + apiVersion));
+                        "No notifyTypeRegistered handler found for interface version " + apiVersion,
+                        HttpStatus.INTERNAL_SERVER_ERROR));
                 }
             };
         }
index 85664f6..c23875b 100644 (file)
@@ -42,6 +42,7 @@ import org.oransc.enrichment.configuration.ApplicationConfig;
 import org.oransc.enrichment.exceptions.ServiceException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
 import org.springframework.util.FileSystemUtils;
 
 /**
@@ -84,7 +85,7 @@ public class InfoTypes {
     public synchronized InfoType getType(String id) throws ServiceException {
         InfoType type = allEiTypes.get(id);
         if (type == null) {
-            throw new ServiceException("Information type not found: " + id);
+            throw new ServiceException("Information type not found: " + id, HttpStatus.NOT_FOUND);
         }
         return type;
     }
index 4d64ef6..4418429 100644 (file)
@@ -490,7 +490,10 @@ class ApplicationTest {
             "targetUri", "jobStatusUrl");
         String body = gson.toJson(jobInfo);
 
-        testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT, "Json validation failure");
+        testErrorCode(restClient().put(url, body), HttpStatus.BAD_REQUEST, "Json validation failure");
+
+        testErrorCode(restClient().put(url, "{jojo}"), HttpStatus.BAD_REQUEST, "", false);
+
     }
 
     @Test
@@ -503,7 +506,7 @@ class ApplicationTest {
             new ConsumerJobInfo("typeId", jsonObject("{ \"XXstring\" : \"value\" }"), "owner", "targetUri", null);
         String body = gson.toJson(jobInfo);
 
-        testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT, "Json validation failure");
+        testErrorCode(restClient().put(url, body), HttpStatus.BAD_REQUEST, "Json validation failure");
     }
 
     @Test
@@ -515,7 +518,7 @@ class ApplicationTest {
         ConsumerJobInfo jobInfo = new ConsumerJobInfo(TYPE_ID, jsonObject(), "owner", "junk", null);
         String body = gson.toJson(jobInfo);
 
-        testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT, "URI: junk is not absolute");
+        testErrorCode(restClient().put(url, body), HttpStatus.BAD_REQUEST, "URI: junk is not absolute");
     }
 
     @Test
@@ -552,6 +555,8 @@ class ApplicationTest {
         String url = ProducerConsts.API_ROOT + "/info-types/" + TYPE_ID;
         String body = "{}";
         testErrorCode(restClient().put(url, body), HttpStatus.BAD_REQUEST, "No schema provided");
+
+        testErrorCode(restClient().post(url, body), HttpStatus.METHOD_NOT_ALLOWED, "", false);
     }
 
     @Test
@@ -572,8 +577,7 @@ class ApplicationTest {
     void producerDeleteEiTypeExistingProducer() throws Exception {
         putInfoProducerWithOneType(PRODUCER_ID, TYPE_ID);
         String url = ProducerConsts.API_ROOT + "/info-types/" + TYPE_ID;
-        testErrorCode(restClient().delete(url), HttpStatus.NOT_ACCEPTABLE,
-            "The type has active producers: " + PRODUCER_ID);
+        testErrorCode(restClient().delete(url), HttpStatus.CONFLICT, "The type has active producers: " + PRODUCER_ID);
         assertThat(this.infoTypes.size()).isEqualTo(1);
     }
 
index 8efef05..3b916e4 160000 (submodule)
--- a/onap/oran
+++ b/onap/oran
@@ -1 +1 @@
-Subproject commit 8efef0513821e7a586de4831a982833050be03e8
+Subproject commit 3b916e4dc5777863cb4ee873b41ee460fb9aec27
index c22a890..c2731f4 100644 (file)
@@ -202,22 +202,86 @@ node_types:
     properties:
       provider:
         type: string
-        requred: false
+        required: false
+        metadata:
+          common: true
+        description: Specifies the organization that provides the control loop element
       participant_id:
         type: onap.datatypes.ToscaConceptIdentifier
         requred: true
+        metadata:
+          common: true
+      participantType:
+        type: onap.datatypes.ToscaConceptIdentifier
+        required: true
+        metadata:
+          common: true
+        description: The identity of the participant type that hosts this type of Control Loop Element
+      startPhase:
+        type: integer
+        required: false
+        constraints:
+          - greater_or_equal: 0
+        metadata:
+          common: true
+        description: A value indicating the start phase in which this control loop element will be started, the
+          first start phase is zero. Control Loop Elements are started in their start_phase order and stopped
+          in reverse start phase order. Control Loop Elements with the same start phase are started and
+          stopped simultaneously
+      uninitializedToPassiveTimeout:
+        type: integer
+        required: false
+        constraints:
+          - greater_or_equal: 0
+        default: 60
+        metadata:
+          common: true
+        description: The maximum time in seconds to wait for a state chage from uninitialized to passive
+      passiveToRunningTimeout:
+        type: integer
+        required: false
+        constraints:
+          - greater_or_equal: 0
+        default: 60
+        metadata:
+          common: true
+        description: The maximum time in seconds to wait for a state chage from passive to running
+      runningToPassiveTimeout:
+        type: integer
+        required: false
+        constraints:
+          - greater_or_equal: 0
+        default: 60
+        metadata:
+          common: true
+        description: The maximum time in seconds to wait for a state chage from running to passive
+      passiveToUninitializedTimeout:
+        type: integer
+        required: false
+        constraints:
+          - greater_or_equal: 0
+        default: 60
+        metadata:
+          common: true
+        description: The maximum time in seconds to wait for a state chage from passive to uninitialized
   org.onap.policy.clamp.controlloop.ControlLoop:
     version: 1.0.1
     derived_from: tosca.nodetypes.Root
     properties:
       provider:
         type: string
-        requred: false
+        required: false
+        metadata:
+          common: true
+        description: Specifies the organization that provides the control loop element
       elements:
         type: list
         required: true
+        metadata:
+          common: true
         entry_schema:
           type: onap.datatypes.ToscaConceptIdentifier
+        description: Specifies a list of control loop element definitions that make up this control loop definition
   org.onap.policy.clamp.controlloop.PolicyControlLoopElement:
     version: 1.0.1
     derived_from: org.onap.policy.clamp.controlloop.ControlLoopElement
@@ -237,11 +301,20 @@ topology_template:
       description: Control loop element for the Link Monitor
       properties:
         provider: Ericsson
-        participantType: org.onap.policy.controlloop.PolicyControlLoopParticipant:2.3.1
-        startPhase: 0
-        policyType: onap.policies.controlloop.operational.common.Apex:1.0.0
-        policyId: operational.apex.linkmonitor:1.0.0
-    org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition:
+        participant_id:
+          name: org.onap.PM_Policy
+          version: 1.0.0
+        participantType:
+          name: org.onap.policy.controlloop.PolicyControlLoopParticipant
+          version: 2.3.1
+        policy_type_id:
+          name: onap.policies.controlloop.operational.common.Apex
+          version: 1.0.0
+        policy_id:
+          name: operational.apex.linkmonitor
+          version: 1.0.0 
+        pdpGroup: defaultGroup
+    org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition0:
       version: 1.2.3
       type: org.onap.policy.clamp.controlloop.ControlLoop
       type_version: 1.0.0
index ec01a33..798de5d 100644 (file)
@@ -4,7 +4,7 @@
             "name": "LinkMonitorInstance0",
             "version": "1.0.1",
             "definition": {
-                "name": "org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition",
+                "name": "org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition0",
                 "version": "1.2.3"
             },
             "state": "UNINITIALISED",
                         "name": "org.onap.policy.controlloop.PolicyControlLoopParticipant",
                         "version": "2.3.1"
                     },
+                    "participantId": {
+                        "name": "org.onap.PM_Policy",
+                        "version": "1.0.0"
+                    },
                     "state": "UNINITIALISED",
                     "orderedState": "UNINITIALISED",
                     "description": "Link Monitor Policy Control Loop Element"
diff --git a/test/usecases/oruclosedlooprecovery/apexpolicyversion/LinkMonitor/docker-compose-controlloop/config/ks.jks b/test/usecases/oruclosedlooprecovery/apexpolicyversion/LinkMonitor/docker-compose-controlloop/config/ks.jks
new file mode 100644 (file)
index 0000000..001c7e1
Binary files /dev/null and b/test/usecases/oruclosedlooprecovery/apexpolicyversion/LinkMonitor/docker-compose-controlloop/config/ks.jks differ
diff --git a/test/usecases/oruclosedlooprecovery/apexpolicyversion/LinkMonitor/docker-compose-controlloop/docker-compose.yml b/test/usecases/oruclosedlooprecovery/apexpolicyversion/LinkMonitor/docker-compose-controlloop/docker-compose.yml
new file mode 100644 (file)
index 0000000..bd35d74
--- /dev/null
@@ -0,0 +1,84 @@
+#
+# ===========LICENSE_START====================================================
+# Copyright (C) 2021 Nordix Foundation. All rights reserved.
+# ============================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=====================================================
+#
+version: '2'
+networks:
+  default:
+    driver: bridge
+    name: nonrtric-docker-net
+services:
+   controlloop-runtime:
+      image: nexus3.onap.org:10001/onap/policy-clamp-cl-runtime:6.1.3
+      container_name: controlloop-runtime
+      hostname: controlloop-runtime
+      ports:
+       - "6969:6969"
+      expose:
+       - 6969
+      volumes:
+       - ./config/ks.jks:/opt/app/policy/clamp/etc/ssl/policy-keystore:ro
+       - ./wait_for_port.sh:/opt/app/policy/clamp/bin/wait_for_port.sh:ro
+      environment:
+       - TOPICSERVER=onap-dmaap
+       - MARIADB_HOST=mariadb
+       - MARIADB_PORT=3306
+       - KEYSTORE=/opt/app/policy/clamp/etc/ssl/policy-keystore
+       - KEYSTORE_PASSWD=Pol1cy_0nap
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_SERVERS_0=onap-dmaap
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_TOPICCOMMINFRASTRUCTURE=dmaap
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_FETCHTIMEOUT=15000
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_USEHTTPS=false
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_SERVERS_0=onap-dmaap
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_TOPICCOMMINFRASTRUCTURE=dmaap
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_FETCHTIMEOUT=15000
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_USEHTTPS=false
+      entrypoint: /opt/app/policy/clamp/bin/wait_for_port.sh
+      command: [
+        '-c', '/opt/app/policy/clamp/bin/controlloop-runtime.sh',
+        'mariadb', '3306',
+        'onap-dmaap', '3904'
+        ]
+   policy-participant:
+      image: nexus3.onap.org:10001/onap/policy-clamp-cl-pf-ppnt:6.1.3
+      container_name: policy-participant
+      depends_on:
+       - controlloop-runtime
+      hostname: policy-participant
+      volumes:
+       - ./config/ks.jks:/opt/app/policy/clamp/etc/ssl/policy-keystore:ro
+       - ./wait_for_port.sh:/opt/app/policy/clamp/bin/wait_for_port.sh:ro
+      environment:
+       - TOPICSERVER=onap-dmaap
+       - KEYSTORE=/opt/app/policy/clamp/etc/ssl/policy-keystore
+       - KEYSTORE_PASSWD=Pol1cy_0nap
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_SERVERS_0=onap-dmaap
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_TOPICCOMMINFRASTRUCTURE=dmaap
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_FETCHTIMEOUT=15000
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_USEHTTPS=false
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_SERVERS_0=onap-dmaap
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_TOPICCOMMINFRASTRUCTURE=dmaap
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_FETCHTIMEOUT=15000
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_USEHTTPS=false
+      entrypoint: /opt/app/policy/clamp/bin/wait_for_port.sh
+      command: [
+        '-c', '/opt/app/policy/clamp/bin/policy-participant.sh',
+        'controlloop-runtime', '6969'
+        ]
\ No newline at end of file
diff --git a/test/usecases/oruclosedlooprecovery/apexpolicyversion/LinkMonitor/docker-compose-controlloop/wait_for_port.sh b/test/usecases/oruclosedlooprecovery/apexpolicyversion/LinkMonitor/docker-compose-controlloop/wait_for_port.sh
new file mode 100755 (executable)
index 0000000..aec5f22
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/sh
+# ============LICENSE_START====================================================
+#  Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+# =============================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END======================================================
+
+tmout=120
+cmd=
+while getopts c:t: opt; do
+    case "$opt" in
+    c) cmd="$OPTARG" ;;
+    t) tmout="$OPTARG" ;;
+    esac
+done
+nargs=$(expr $OPTIND - 1)
+shift $nargs
+
+even_args=$(expr $# % 2)
+if [ $# -lt 2 -o $even_args -ne 0 ]; then
+    echo "args: [-t timeout] [-c command] hostname1 port1 hostname2 port2 ..." >&2
+    exit 1
+fi
+
+while [ $# -ge 2 ]; do
+    export host=$1
+    export port=$2
+    shift
+    shift
+
+    echo "Waiting for $host port $port..."
+    timeout $tmout sh -c 'until nc -vz "$host" "$port"; do echo -n ".";
+        sleep 1; done'
+    rc=$?
+
+    if [ $rc != 0 ]; then
+        echo "$host port $port cannot be reached"
+        exit $rc
+    fi
+done
+
+$cmd
+
+exit 0
index 6d9bdd2..2963a8c 100644 (file)
@@ -76,7 +76,7 @@ node_types:
         requred: true
 topology_template:
   node_templates:
-    org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition:
+    org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition1:
       version: 1.2.3
       type: org.onap.policy.clamp.controlloop.ControlLoop
       type_version: 1.0.1
@@ -107,17 +107,18 @@ topology_template:
       properties:
         provider: ONAP
         participant_id:
+          name: K8sParticipant0
+          version: 1.0.0
+        participantType:
           name: org.onap.k8s.controlloop.K8SControlLoopParticipant
           version: 2.3.4
-        uninitializedToPassiveTimeout: 180
-        podStatusCheckInterval: 30
         chart:
           chartId:
             name: oru-app
             version: 0.1.0
           releaseName: oru-app
-         # repository can point to a helm repo or a path in local file system where chart is stored
-          repository: chartmuseum
+          repository:
+            repoName: chartmuseum
           namespace: nonrtric
     org.onap.domain.linkmonitor.MessageGeneratorK8SMicroserviceControlLoopElement:
       version: 1.2.3
@@ -127,17 +128,18 @@ topology_template:
       properties:
         provider: ONAP
         participant_id:
+          name: K8sParticipant0
+          version: 1.0.0
+        participantType:
           name: org.onap.k8s.controlloop.K8SControlLoopParticipant
           version: 2.3.4
-        uninitializedToPassiveTimeout: 180
-        podStatusCheckInterval: 30
         chart:
           chartId:
             name: message-generator
             version: 0.1.0
           releaseName: message-generator
-         # repository can point to a helm repo or a path in local file system where chart is stored
-          repository: chartmuseum
+          repository:
+            repoName: chartmuseum
           namespace: nonrtric
           overrideParams:
             image.tag: v2
@@ -149,17 +151,18 @@ topology_template:
       properties:
         provider: ONAP
         participant_id:
+          name: K8sParticipant0
+          version: 1.0.0
+        participantType:
           name: org.onap.k8s.controlloop.K8SControlLoopParticipant
           version: 2.3.4
-        uninitializedToPassiveTimeout: 180
-        podStatusCheckInterval: 30
         chart:
           chartId:
             name: sdnr-simulator
             version: 0.1.0
           releaseName: sdnr-simulator
-         # repository can point to a helm repo or a path in local file system where chart is stored
-          repository: chartmuseum
+          repository:
+            repoName: chartmuseum
           namespace: nonrtric
     org.onap.domain.linkmonitor.DmaapMrK8SMicroserviceControlLoopElement:
       version: 1.2.3
@@ -169,15 +172,16 @@ topology_template:
       properties:
         provider: ONAP
         participant_id:
+          name: K8sParticipant0
+          version: 1.0.0
+        participantType:
           name: org.onap.k8s.controlloop.K8SControlLoopParticipant
           version: 2.3.4
-        uninitializedToPassiveTimeout: 180
-        podStatusCheckInterval: 30
         chart:
           chartId:
             name: dmaap-mr
             version: 0.1.0
           releaseName: dmaap-mr
-         # repository can point to a helm repo or a path in local file system where chart is stored
-          repository: chartmuseum
+          repository:
+            repoName: chartmuseum
           namespace: nonrtric
\ No newline at end of file
index a09c112..b1da263 100644 (file)
@@ -1,8 +1,8 @@
 {
-    "orderedState": "RUNNING",
+    "orderedState": "PASSIVE",
     "controlLoopIdentifierList": [
         {
-            "name": "LinkMonitorInstance0",
+            "name": "LinkMonitorInstance1",
             "version": "1.0.1"
         }
     ]
index e80b67f..ec3b9f1 100644 (file)
@@ -1,18 +1,18 @@
 {
     "controlLoopList": [
         {
-            "name": "LinkMonitorInstance0",
+            "name": "LinkMonitorInstance1",
             "version": "1.0.1",
             "definition": {
-                "name": "org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition",
+                "name": "org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition1",
                 "version": "1.2.3"
             },
             "state": "UNINITIALISED",
             "orderedState": "UNINITIALISED",
-            "description": "Link Monitor control loop instance 0",
+            "description": "Link Monitor control loop instance 1",
             "elements": {
-                "709c62b3-8918-41b9-a747-d21eb79c6c22": {
-                    "id": "709c62b3-8918-41b9-a747-d21eb79c6c22",
+                "709c62b3-8918-41b9-a747-d21eb79c6c12": {
+                    "id": "709c62b3-8918-41b9-a747-d21eb79c6c12",
                     "definition": {
                         "name": "org.onap.domain.linkmonitor.OruAppK8SMicroserviceControlLoopElement",
                         "version": "1.2.3"
                         "name": "org.onap.k8s.controlloop.K8SControlLoopParticipant",
                         "version": "2.3.4"
                     },
+                    "participantId": {
+                        "name": "K8sParticipant0",
+                        "version": "1.0.0"
+                    },
                     "state": "UNINITIALISED",
                     "orderedState": "UNINITIALISED",
                     "description": "Oru App k8s Control Loop Element"
                 },
-                "709c62b3-8918-41b9-a747-d21eb79c6c23": {
-                    "id": "709c62b3-8918-41b9-a747-d21eb79c6c23",
+                "709c62b3-8918-41b9-a747-d21eb79c6c13": {
+                    "id": "709c62b3-8918-41b9-a747-d21eb79c6c13",
                     "definition": {
                         "name": "org.onap.domain.linkmonitor.MessageGeneratorK8SMicroserviceControlLoopElement",
                         "version": "1.2.3"
                         "name": "org.onap.k8s.controlloop.K8SControlLoopParticipant",
                         "version": "2.3.4"
                     },
+                    "participantId": {
+                        "name": "K8sParticipant0",
+                        "version": "1.0.0"
+                    },
                     "state": "UNINITIALISED",
                     "orderedState": "UNINITIALISED",
                     "description": "Message Generator k8s Control Loop Element"
                 },
-                "709c62b3-8918-41b9-a747-d21eb79c6c24": {
-                    "id": "709c62b3-8918-41b9-a747-d21eb79c6c24",
+                "709c62b3-8918-41b9-a747-d21eb79c6c14": {
+                    "id": "709c62b3-8918-41b9-a747-d21eb79c6c14",
                     "definition": {
                         "name": "org.onap.domain.linkmonitor.SdnrSimulatorK8SMicroserviceControlLoopElement",
                         "version": "1.2.3"
                         "name": "org.onap.k8s.controlloop.K8SControlLoopParticipant",
                         "version": "2.3.4"
                     },
+                    "participantId": {
+                        "name": "K8sParticipant0",
+                        "version": "1.0.0"
+                    },
                     "state": "UNINITIALISED",
                     "orderedState": "UNINITIALISED",
                     "description": "Sdnr Simulator k8s Control Loop Element"
                 },
-                "709c62b3-8918-41b9-a747-d21eb79c6c25": {
-                    "id": "709c62b3-8918-41b9-a747-d21eb79c6c25",
+                "709c62b3-8918-41b9-a747-d21eb79c6c15": {
+                    "id": "709c62b3-8918-41b9-a747-d21eb79c6c15",
                     "definition": {
                         "name": "org.onap.domain.linkmonitor.DmaapMrK8SMicroserviceControlLoopElement",
                         "version": "1.2.3"
                         "name": "org.onap.k8s.controlloop.K8SControlLoopParticipant",
                         "version": "2.3.4"
                     },
+                    "participantId": {
+                        "name": "K8sParticipant0",
+                        "version": "1.0.0"
+                    },
                     "state": "UNINITIALISED",
                     "orderedState": "UNINITIALISED",
                     "description": "Dmaap Mr k8s Control Loop Element"
index ac2d0a5..6a6310d 100755 (executable)
@@ -24,5 +24,5 @@
 ###
 
 mysql -uroot -p$MYSQL_ROOT_PASSWORD -f < /docker-entrypoint-initdb.d/create-db.sql
-mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "CREATE USER 'policy'@'%' IDENTIFIED BY 'P01icY';"
-mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "GRANT ALL PRIVILEGES ON controlloop.* TO 'policy'@'%';"
\ No newline at end of file
+mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "CREATE USER 'policy_user'@'%' IDENTIFIED BY 'policy_user';"
+mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "GRANT ALL PRIVILEGES ON controlloop.* TO 'policy_user'@'%';"
\ No newline at end of file
index 47fab67..80d5186 100644 (file)
@@ -35,7 +35,7 @@ services:
       expose:
        - 3306
    controlloop-runtime:
-      image: nexus3.onap.org:10001/onap/policy-controlloop-runtime:6.1.2-SNAPSHOT
+      image: nexus3.onap.org:10001/onap/policy-clamp-cl-runtime:6.1.3
       container_name: controlloop-runtime
       depends_on:
        - mariadb
@@ -45,28 +45,57 @@ services:
       expose:
        - 6969
       volumes:
-       - ./config/ks.jks:/opt/app/policy/clamp/etc/ssl/policy-keystore.jks:ro
+       - ./config/ks.jks:/opt/app/policy/clamp/etc/ssl/policy-keystore:ro
+       - ./wait_for_port.sh:/opt/app/policy/clamp/bin/wait_for_port.sh:ro
       environment:
        - TOPICSERVER=onap-dmaap
        - MARIADB_HOST=mariadb
        - MARIADB_PORT=3306
+       - KEYSTORE=/opt/app/policy/clamp/etc/ssl/policy-keystore
+       - KEYSTORE_PASSWD=Pol1cy_0nap
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_SERVERS_0=onap-dmaap
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_TOPICCOMMINFRASTRUCTURE=dmaap
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_FETCHTIMEOUT=15000
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_USEHTTPS=false
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_SERVERS_0=onap-dmaap
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_TOPICCOMMINFRASTRUCTURE=dmaap
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_FETCHTIMEOUT=15000
+       - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_USEHTTPS=false
+      entrypoint: /opt/app/policy/clamp/bin/wait_for_port.sh
+      command: [
+        '-c', '/opt/app/policy/clamp/bin/controlloop-runtime.sh',
+        'mariadb', '3306',
+        'onap-dmaap', '3904'
+        ]
    k8s-participant:
-      image: nexus3.onap.org:10001/onap/kubernetes-participant:6.1.2-SNAPSHOT
+      image: nexus3.onap.org:10001/onap/policy-clamp-cl-k8s-ppnt:6.1.3
       container_name: k8s-participant
       depends_on:
        - mariadb
        - controlloop-runtime
-       - chartmuseum
       hostname: k8s-participant
       volumes:
-       - ./config/ks.jks:/opt/app/policy/clamp/etc/ssl/policy-keystore.jks:ro
+       - ./config/ks.jks:/opt/app/policy/clamp/etc/ssl/policy-keystore:ro
        - ./../helm:/home/policy/helm
+       - ./wait_for_port.sh:/opt/app/policy/clamp/bin/wait_for_port.sh:ro
        - <PATH TO kube-config>:/home/policy/.kube/config:ro
       environment:
        - TOPICSERVER=onap-dmaap
-       - KEYSTORE=/opt/app/policy/clamp/etc/ssl/policy-keystore.jks
+       - KEYSTORE=/opt/app/policy/clamp/etc/ssl/policy-keystore
        - KEYSTORE_PASSWD=Pol1cy_0nap
-      entrypoint: sh -c "/home/policy/helm/chartmuseum_init.sh && /opt/app/policy/clamp/bin/kubernetes-participant.sh"
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_SERVERS_0=onap-dmaap
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_TOPICCOMMINFRASTRUCTURE=dmaap
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_FETCHTIMEOUT=15000
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_USEHTTPS=false
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_SERVERS_0=onap-dmaap
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_TOPICCOMMINFRASTRUCTURE=dmaap
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_FETCHTIMEOUT=15000
+       - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_USEHTTPS=false
+      entrypoint: sh -c "/opt/app/policy/clamp/bin/wait_for_port.sh controlloop-runtime 6969 && /home/policy/helm/chartmuseum_init.sh && /opt/app/policy/clamp/bin/kubernetes-participant.sh"
    chartmuseum:
       image: ghcr.io/helm/chartmuseum:v0.13.1
       container_name: chartmuseum
diff --git a/test/usecases/oruclosedlooprecovery/scriptversion/docker-compose-controlloop/wait_for_port.sh b/test/usecases/oruclosedlooprecovery/scriptversion/docker-compose-controlloop/wait_for_port.sh
new file mode 100755 (executable)
index 0000000..aec5f22
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/sh
+# ============LICENSE_START====================================================
+#  Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+# =============================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END======================================================
+
+tmout=120
+cmd=
+while getopts c:t: opt; do
+    case "$opt" in
+    c) cmd="$OPTARG" ;;
+    t) tmout="$OPTARG" ;;
+    esac
+done
+nargs=$(expr $OPTIND - 1)
+shift $nargs
+
+even_args=$(expr $# % 2)
+if [ $# -lt 2 -o $even_args -ne 0 ]; then
+    echo "args: [-t timeout] [-c command] hostname1 port1 hostname2 port2 ..." >&2
+    exit 1
+fi
+
+while [ $# -ge 2 ]; do
+    export host=$1
+    export port=$2
+    shift
+    shift
+
+    echo "Waiting for $host port $port..."
+    timeout $tmout sh -c 'until nc -vz "$host" "$port"; do echo -n ".";
+        sleep 1; done'
+    rc=$?
+
+    if [ $rc != 0 ]; then
+        echo "$host port $port cannot be reached"
+        exit $rc
+    fi
+done
+
+$cmd
+
+exit 0