Added Main initial code 59/117959/9
authorFrancescoFioraEst <francesco.fiora@est.tech>
Wed, 17 Feb 2021 10:11:02 +0000 (10:11 +0000)
committerFrancesco Fiora <francesco.fiora@est.tech>
Tue, 23 Feb 2021 14:07:33 +0000 (14:07 +0000)
Issue-ID: POLICY-2995
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
Change-Id: I6f7da312f00341be8928fb66875c309c6933f194

17 files changed:
tosca-controlloop/runtime/pom.xml
tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterGroup.java [new file with mode: 0644]
tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterHandler.java [new file with mode: 0644]
tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantParameters.java [new file with mode: 0644]
tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantStateChangeParameters.java [new file with mode: 0644]
tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantUpdateParameters.java [new file with mode: 0644]
tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java [new file with mode: 0644]
tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeCommandLineArguments.java [new file with mode: 0644]
tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/Main.java [new file with mode: 0644]
tosca-controlloop/runtime/src/main/resources/version.txt [new file with mode: 0644]
tosca-controlloop/runtime/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivatorTest.java [new file with mode: 0644]
tosca-controlloop/runtime/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/MainTest.java [new file with mode: 0644]
tosca-controlloop/runtime/src/test/resources/parameters/EmptyParameters.json [new file with mode: 0644]
tosca-controlloop/runtime/src/test/resources/parameters/InvalidParameters.json [new file with mode: 0644]
tosca-controlloop/runtime/src/test/resources/parameters/NoParameters.json [new file with mode: 0644]
tosca-controlloop/runtime/src/test/resources/parameters/TestParameters.json [new file with mode: 0644]
tosca-controlloop/runtime/src/test/resources/parameters/Unreadable.json [new file with mode: 0644]

index 93498f5..e3811bb 100644 (file)
     <name>${project.artifactId}</name>
 
     <dependencies>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-            <scope>test</scope>
+      <dependency>
+            <groupId>org.onap.policy.clamp.controlloop</groupId>
+            <artifactId>controlloop-common</artifactId>
+            <version>${project.version}</version>
         </dependency>
     </dependencies>
 </project>
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterGroup.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterGroup.java
new file mode 100644 (file)
index 0000000..4c99b8e
--- /dev/null
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.main.parameters;
+
+import java.util.List;
+import javax.validation.constraints.NotBlank;
+import lombok.Getter;
+import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams;
+import org.onap.policy.common.endpoints.parameters.RestServerParameters;
+import org.onap.policy.common.endpoints.parameters.TopicParameterGroup;
+import org.onap.policy.common.parameters.ParameterGroupImpl;
+import org.onap.policy.common.parameters.annotations.NotNull;
+import org.onap.policy.models.provider.PolicyModelsProviderParameters;
+
+/**
+ * Class to hold all parameters needed for the Control Loop runtime component.
+ *
+ */
+@NotNull
+@NotBlank
+@Getter
+public class ClRuntimeParameterGroup extends ParameterGroupImpl {
+    private RestServerParameters restServerParameters;
+    private PolicyModelsProviderParameters databaseProviderParameters;
+    private ParticipantParameters participantParameters;
+    private TopicParameterGroup topicParameterGroup;
+    private List<BusTopicParams> healthCheckRestClientParameters;
+
+    /**
+     * Create the Control Loop parameter group.
+     *
+     * @param name the parameter group name
+     */
+    public ClRuntimeParameterGroup(final String name) {
+        super(name);
+    }
+}
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterHandler.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterHandler.java
new file mode 100644 (file)
index 0000000..a7f5ff3
--- /dev/null
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.main.parameters;
+
+import java.io.File;
+import javax.ws.rs.core.Response;
+import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException;
+import org.onap.policy.clamp.controlloop.runtime.main.startstop.ClRuntimeCommandLineArguments;
+import org.onap.policy.common.parameters.GroupValidationResult;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+
+/**
+ * This class handles reading, parsing and validating of control loop runtime parameters from JSON files.
+ */
+public class ClRuntimeParameterHandler {
+
+    private static final Coder CODER = new StandardCoder();
+
+    /**
+     * Read the parameters from the parameter file.
+     *
+     * @param arguments the arguments passed to control loop runtime
+     * @return the parameters read from the configuration file
+     * @throws ControlLoopException on parameter exceptions
+     */
+    public ClRuntimeParameterGroup getParameters(final ClRuntimeCommandLineArguments arguments)
+            throws ControlLoopException {
+        ClRuntimeParameterGroup clRuntimeParameterGroup = null;
+
+        // Read the parameters
+        try {
+            // Read the parameters from JSON
+            File file = new File(arguments.getFullConfigurationFilePath());
+            clRuntimeParameterGroup = CODER.decode(file, ClRuntimeParameterGroup.class);
+        } catch (final CoderException e) {
+            throw new ControlLoopException(
+                    Response.Status.NOT_ACCEPTABLE, "error reading parameters from \""
+                            + arguments.getConfigurationFilePath() + "\"\n" + "(" + e.getClass().getSimpleName() + ")",
+                    e);
+        }
+
+        // The JSON processing returns null if there is an empty file
+        if (clRuntimeParameterGroup == null) {
+            throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE,
+                    "no parameters found in \"" + arguments.getConfigurationFilePath() + "\"");
+        }
+
+        // validate the parameters
+        final GroupValidationResult validationResult = clRuntimeParameterGroup.validate();
+        if (!validationResult.isValid()) {
+            throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE, "validation error(s) on parameters from \""
+                    + arguments.getConfigurationFilePath() + "\"\n" + validationResult.getResult());
+        }
+
+        return clRuntimeParameterGroup;
+    }
+}
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantParameters.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantParameters.java
new file mode 100644 (file)
index 0000000..dfc1b28
--- /dev/null
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.main.parameters;
+
+import java.util.concurrent.TimeUnit;
+import lombok.Getter;
+import org.onap.policy.common.parameters.ParameterGroupImpl;
+import org.onap.policy.common.parameters.annotations.Min;
+import org.onap.policy.common.parameters.annotations.NotBlank;
+import org.onap.policy.common.parameters.annotations.NotNull;
+
+/**
+ * Parameters for communicating with participants.
+ */
+@NotNull
+@NotBlank
+@Getter
+public class ParticipantParameters extends ParameterGroupImpl {
+
+    /**
+     * Default maximum message age, in milliseconds, that should be examined. Any message
+     * older than this is discarded.
+     */
+    public static final long DEFAULT_MAX_AGE_MS = TimeUnit.MILLISECONDS.convert(10, TimeUnit.MINUTES);
+
+
+    @Min(1)
+    private long heartBeatMs;
+
+    @Min(1)
+    private long maxMessageAgeMs =  DEFAULT_MAX_AGE_MS;
+
+    private ParticipantUpdateParameters updateParameters;
+    private ParticipantStateChangeParameters stateChangeParameters;
+
+
+    /**
+     * Constructs the object.
+     */
+    public ParticipantParameters() {
+        super(ParticipantParameters.class.getSimpleName());
+    }
+}
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantStateChangeParameters.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantStateChangeParameters.java
new file mode 100644 (file)
index 0000000..2eea4ab
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.main.parameters;
+
+import lombok.Getter;
+import org.onap.policy.common.parameters.ParameterGroupImpl;
+import org.onap.policy.common.parameters.annotations.Min;
+import org.onap.policy.common.parameters.annotations.NotBlank;
+import org.onap.policy.common.parameters.annotations.NotNull;
+
+/**
+ * Parameters for Participant STATE-CHANGE requests.
+ */
+@NotNull
+@NotBlank
+@Getter
+public class ParticipantStateChangeParameters extends ParameterGroupImpl {
+
+    /**
+     * Maximum number of times to re-send a request to a PDP.
+     */
+    @Min(value = 0)
+    private int maxRetryCount;
+
+    /**
+     * Maximum time to wait, in milliseconds, for a PDP response.
+     */
+    @Min(value = 0)
+    private long maxWaitMs;
+
+    /**
+     * Constructs the object.
+     */
+    public ParticipantStateChangeParameters() {
+        super(ParticipantStateChangeParameters.class.getSimpleName());
+    }
+}
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantUpdateParameters.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantUpdateParameters.java
new file mode 100644 (file)
index 0000000..f70e7d5
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.main.parameters;
+
+import lombok.Getter;
+import org.onap.policy.common.parameters.ParameterGroupImpl;
+import org.onap.policy.common.parameters.annotations.Min;
+import org.onap.policy.common.parameters.annotations.NotBlank;
+import org.onap.policy.common.parameters.annotations.NotNull;
+
+/**
+ * Parameters for Participant UPDATE requests.
+ */
+@NotNull
+@NotBlank
+@Getter
+public class ParticipantUpdateParameters extends ParameterGroupImpl {
+
+    /**
+     * Maximum number of times to re-send a request to a PDP.
+     */
+    @Min(value = 0)
+    private int maxRetryCount;
+
+    /**
+     * Maximum time to wait, in milliseconds, for a PDP response.
+     */
+    @Min(value = 0)
+    private long maxWaitMs;
+
+    /**
+     * Constructs the object.
+     */
+    public ParticipantUpdateParameters() {
+        super(ParticipantUpdateParameters.class.getSimpleName());
+    }
+}
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java
new file mode 100644 (file)
index 0000000..8ac4d68
--- /dev/null
@@ -0,0 +1,115 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.main.startstop;
+
+import java.util.List;
+import javax.ws.rs.core.Response.Status;
+import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException;
+import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
+import org.onap.policy.common.endpoints.event.comm.TopicSource;
+import org.onap.policy.common.endpoints.listeners.MessageTypeDispatcher;
+import org.onap.policy.common.parameters.ParameterService;
+import org.onap.policy.common.utils.services.ServiceManagerContainer;
+
+/**
+ * This class activates the control loop runtime component as a complete service together with all its controllers,
+ * listeners & handlers.
+ */
+public class ClRuntimeActivator extends ServiceManagerContainer {
+    // Name of the message type for messages on topics
+    private static final String[] MSG_TYPE_NAMES = {"messageType"};
+
+    private final ClRuntimeParameterGroup clRuntimeParameterGroup;
+
+    // Topics from which the application receives and to which the application sends messages
+    private List<TopicSource> topicSources;
+
+    /**
+     * Listens for messages on the topic, decodes them into a message, and then dispatches them.
+     */
+    private final MessageTypeDispatcher msgDispatcher;
+
+    /**
+     * Instantiate the activator for the control loop runtime as a complete service.
+     *
+     * @param clRuntimeParameterGroup the parameters for the control loop runtime service
+     */
+    public ClRuntimeActivator(final ClRuntimeParameterGroup clRuntimeParameterGroup) {
+
+        if (clRuntimeParameterGroup == null || !clRuntimeParameterGroup.isValid()) {
+            throw new ControlLoopRuntimeException(Status.INTERNAL_SERVER_ERROR, "ParameterGroup not valid");
+        }
+
+        this.clRuntimeParameterGroup = clRuntimeParameterGroup;
+
+        topicSources = TopicEndpointManager.getManager()
+                .addTopicSources(clRuntimeParameterGroup.getTopicParameterGroup().getTopicSources());
+
+        try {
+            msgDispatcher = new MessageTypeDispatcher(MSG_TYPE_NAMES);
+        } catch (final RuntimeException e) {
+            throw new ControlLoopRuntimeException(Status.INTERNAL_SERVER_ERROR,
+                    "topic message dispatcher failed to start", e);
+        }
+
+        // @formatter:off
+        addAction("Control loop runtime parameters",
+            () -> ParameterService.register(clRuntimeParameterGroup),
+            () -> ParameterService.deregister(clRuntimeParameterGroup.getName()));
+
+        addAction("Topic endpoint management",
+            () -> TopicEndpointManager.getManager().start(),
+            () -> TopicEndpointManager.getManager().shutdown());
+
+        addAction("Topic Message Dispatcher", this::registerMsgDispatcher, this::unregisterMsgDispatcher);
+
+        clRuntimeParameterGroup.getRestServerParameters().setName(clRuntimeParameterGroup.getName());
+        // @formatter:on
+    }
+
+    /**
+     * Registers the dispatcher with the topic source(s).
+     */
+    private void registerMsgDispatcher() {
+        for (final TopicSource source : topicSources) {
+            source.register(msgDispatcher);
+        }
+    }
+
+    /**
+     * Unregisters the dispatcher from the topic source(s).
+     */
+    private void unregisterMsgDispatcher() {
+        for (final TopicSource source : topicSources) {
+            source.unregister(msgDispatcher);
+        }
+    }
+
+    /**
+     * Get the parameters used by the activator.
+     *
+     * @return the parameters of the activator
+     */
+    public ClRuntimeParameterGroup getParameterGroup() {
+        return clRuntimeParameterGroup;
+    }
+}
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeCommandLineArguments.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeCommandLineArguments.java
new file mode 100644 (file)
index 0000000..fa25b6d
--- /dev/null
@@ -0,0 +1,223 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.main.startstop;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URL;
+import java.util.Arrays;
+import javax.ws.rs.core.Response;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+
+
+/**
+ * This class reads and handles command line parameters for the control loop runtime service.
+ *
+ */
+public class ClRuntimeCommandLineArguments {
+    private static final String FILE_MESSAGE_PREAMBLE = " file \"";
+    private static final int HELP_LINE_LENGTH = 120;
+
+    private final Options options;
+    private String configurationFilePath = null;
+
+    /**
+     * Construct the options for the control loop runtime component.
+     */
+    public ClRuntimeCommandLineArguments() {
+        //@formatter:off
+        options = new Options();
+        options.addOption(Option.builder("h")
+                .longOpt("help")
+                .desc("outputs the usage of this command")
+                .required(false)
+                .type(Boolean.class)
+                .build());
+        options.addOption(Option.builder("v")
+                .longOpt("version")
+                .desc("outputs the version of control loop runtime")
+                .required(false)
+                .type(Boolean.class)
+                .build());
+        options.addOption(Option.builder("c")
+                .longOpt("config-file")
+                .desc("the full path to the configuration file to use, "
+                        + "the configuration file must be a Json file containing the control loop runtime parameters")
+                .hasArg()
+                .argName("CONFIG_FILE")
+                .required(false)
+                .type(String.class)
+                .build());
+        //@formatter:on
+    }
+
+    /**
+     * Parse the command line options.
+     *
+     * @param args The command line arguments
+     * @return a string with a message for help and version, or null if there is no message
+     * @throws ControlLoopException on command argument errors
+     */
+    public String parse(final String[] args) throws ControlLoopException {
+        // Clear all our arguments
+        setConfigurationFilePath(null);
+
+        CommandLine commandLine = null;
+        try {
+            commandLine = new DefaultParser().parse(options, args);
+        } catch (final ParseException e) {
+            throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE,
+                    "invalid command line arguments specified", e);
+        }
+
+        // Arguments left over after Commons CLI does its stuff
+        final String[] remainingArgs = commandLine.getArgs();
+
+        if (remainingArgs.length > 0) {
+            throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE,
+                    "too many command line arguments specified : " + Arrays.toString(args));
+        }
+
+        if (remainingArgs.length == 1) {
+            configurationFilePath = remainingArgs[0];
+        }
+
+        if (commandLine.hasOption('h')) {
+            return help(Main.class.getName());
+        }
+
+        if (commandLine.hasOption('v')) {
+            return version();
+        }
+
+        if (commandLine.hasOption('c')) {
+            setConfigurationFilePath(commandLine.getOptionValue('c'));
+        }
+
+        return null;
+    }
+
+    /**
+     * Validate the command line options.
+     *
+     * @throws ControlLoopException on command argument validation errors
+     */
+    public void validate() throws ControlLoopException {
+        validateReadableFile("control loop runtime configuration", configurationFilePath);
+    }
+
+    /**
+     * Print version information for control loop runtime.
+     *
+     * @return the version string
+     */
+    public String version() {
+        return ResourceUtils.getResourceAsString("version.txt");
+    }
+
+    /**
+     * Print help information for control loop runtime.
+     *
+     * @param mainClassName the main class name
+     * @return the help string
+     */
+    public String help(final String mainClassName) {
+        final HelpFormatter helpFormatter = new HelpFormatter();
+        final StringWriter stringWriter = new StringWriter();
+        final PrintWriter printWriter = new PrintWriter(stringWriter);
+
+        helpFormatter.printHelp(printWriter, HELP_LINE_LENGTH, mainClassName + " [options...]", "options", options, 0,
+                0, "");
+
+        return stringWriter.toString();
+    }
+
+    /**
+     * Gets the configuration file path.
+     *
+     * @return the configuration file path
+     */
+    public String getConfigurationFilePath() {
+        return configurationFilePath;
+    }
+
+    /**
+     * Gets the full expanded configuration file path.
+     *
+     * @return the configuration file path
+     */
+    public String getFullConfigurationFilePath() {
+        return ResourceUtils.getFilePath4Resource(getConfigurationFilePath());
+    }
+
+    /**
+     * Sets the configuration file path.
+     *
+     * @param configurationFilePath the configuration file path
+     */
+    public void setConfigurationFilePath(final String configurationFilePath) {
+        this.configurationFilePath = configurationFilePath;
+
+    }
+
+    /**
+     * Validate readable file.
+     *
+     * @param fileTag the file tag
+     * @param fileName the file name
+     * @throws ControlLoopException on the file name passed as a parameter
+     */
+    private void validateReadableFile(final String fileTag, final String fileName) throws ControlLoopException {
+        if (fileName == null || fileName.length() == 0) {
+            throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE,
+                    fileTag + " file was not specified as an argument");
+        }
+
+        // The file name refers to a resource on the local file system
+        final URL fileUrl = ResourceUtils.getUrl4Resource(fileName);
+        if (fileUrl == null) {
+            throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE,
+                    fileTag + FILE_MESSAGE_PREAMBLE + fileName + "\" does not exist");
+        }
+
+        final File theFile = new File(fileUrl.getPath());
+        if (!theFile.exists()) {
+            throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE,
+                    fileTag + FILE_MESSAGE_PREAMBLE + fileName + "\" does not exist");
+        }
+        if (!theFile.isFile()) {
+            throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE,
+                    fileTag + FILE_MESSAGE_PREAMBLE + fileName + "\" is not a normal file");
+        }
+        if (!theFile.canRead()) {
+            throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE,
+                    fileTag + FILE_MESSAGE_PREAMBLE + fileName + "\" is ureadable");
+        }
+    }
+}
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/Main.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/Main.java
new file mode 100644 (file)
index 0000000..8e60d68
--- /dev/null
@@ -0,0 +1,156 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.main.startstop;
+
+import java.util.Arrays;
+import javax.ws.rs.core.Response;
+import org.onap.policy.clamp.controlloop.common.ControlLoopConstants;
+import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException;
+import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException;
+import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup;
+import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterHandler;
+import org.onap.policy.common.utils.resources.MessageConstants;
+import org.onap.policy.common.utils.services.Registry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class initiates ONAP Policy Framework Control Loop runtime component.
+ */
+public class Main {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
+
+    private ClRuntimeActivator activator;
+    private ClRuntimeParameterGroup parameterGroup;
+
+    /**
+     * Instantiates the control loop runtime service.
+     *
+     * @param args the command line arguments
+     */
+    public Main(final String[] args) {
+        final String argumentString = Arrays.toString(args);
+        LOGGER.info("Starting the control loop runtime service with arguments - {}", argumentString);
+
+        // Check the arguments
+        final ClRuntimeCommandLineArguments arguments = new ClRuntimeCommandLineArguments();
+        try {
+            // The arguments return a string if there is a message to print and we should exit
+            final String argumentMessage = arguments.parse(args);
+            if (argumentMessage != null) {
+                LOGGER.info(argumentMessage);
+                return;
+            }
+            // Validate that the arguments are sane
+            arguments.validate();
+
+            // Read the parameters
+            parameterGroup = new ClRuntimeParameterHandler().getParameters(arguments);
+
+            // Now, create the activator for the service
+            activator = new ClRuntimeActivator(parameterGroup);
+            Registry.register(ControlLoopConstants.REG_CLRUNTIME_ACTIVATOR, activator);
+
+            // Start the activator
+            activator.start();
+        } catch (Exception exp) {
+            if (null != activator) {
+                Registry.unregister(ControlLoopConstants.REG_CLRUNTIME_ACTIVATOR);
+            }
+            throw new ControlLoopRuntimeException(Response.Status.BAD_REQUEST,
+                String.format(MessageConstants.START_FAILURE_MSG, MessageConstants.POLICY_CLAMP), exp);
+        }
+
+        // Add a shutdown hook to shut everything down in an orderly manner
+        Runtime.getRuntime().addShutdownHook(new ClRuntimeShutdownHookClass());
+        String successMsg = String.format(MessageConstants.START_SUCCESS_MSG, MessageConstants.POLICY_CLAMP);
+        LOGGER.info(successMsg);
+    }
+
+    /**
+     * Check if main is running.
+     */
+    public boolean isRunning() {
+        return activator != null && activator.isAlive();
+    }
+
+    /**
+     * Get the parameters specified in JSON.
+     *
+     * @return the parameters
+     */
+    public ClRuntimeParameterGroup getParameters() {
+        return parameterGroup;
+    }
+
+    /**
+     * Shut down Execution.
+     *
+     * @throws ControlLoopException on shutdown errors
+     */
+    public void shutdown() throws ControlLoopException {
+        // clear the parameterGroup variable
+        parameterGroup = null;
+
+        // clear the cl runtime activator
+        if (activator != null) {
+            activator.stop();
+        }
+    }
+
+    /**
+     * The Class ClRuntimeShutdownHookClass terminates the control loop runtime service when its run method is called.
+     */
+    private class ClRuntimeShutdownHookClass extends Thread {
+        /*
+         * (non-Javadoc)
+         *
+         * @see java.lang.Runnable#run()
+         */
+        @Override
+        public void run() {
+            if (!activator.isAlive()) {
+                return;
+            }
+
+            try {
+                // Shutdown the control loop runtime service and wait for everything to stop
+                activator.stop();
+            } catch (final RuntimeException e) {
+                LOGGER.warn("error occured during shut down of the control loop runtime service", e);
+            }
+        }
+    }
+
+    /**
+     * The main method.
+     *
+     * @param args the arguments
+     */
+    public static void main(final String[] args) {      // NOSONAR
+        /*
+         * NOTE: arguments are validated by the constructor, thus sonar is disabled.
+         */
+
+        new Main(args);
+    }
+}
diff --git a/tosca-controlloop/runtime/src/main/resources/version.txt b/tosca-controlloop/runtime/src/main/resources/version.txt
new file mode 100644 (file)
index 0000000..e11449e
--- /dev/null
@@ -0,0 +1,4 @@
+ONAP Tosca defined control loop
+Version: ${project.version}
+Built (UTC): ${maven.build.timestamp}
+ONAP https://wiki.onap.org
diff --git a/tosca-controlloop/runtime/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivatorTest.java b/tosca-controlloop/runtime/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivatorTest.java
new file mode 100644 (file)
index 0000000..7928124
--- /dev/null
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.main.startstop;
+
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException;
+import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup;
+import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterHandler;
+import org.onap.policy.common.utils.services.Registry;
+
+/**
+ * Class to perform unit test of {@link ClRuntimeActivator}}.
+ *
+ */
+public class ClRuntimeActivatorTest {
+
+    @Test
+    public void testStartAndStop() throws Exception {
+        Registry.newRegistry();
+        final String[] configParameters = {"-c", "src/test/resources/parameters/TestParameters.json"};
+        final ClRuntimeCommandLineArguments arguments = new ClRuntimeCommandLineArguments();
+        arguments.parse(configParameters);
+        ClRuntimeParameterGroup parameterGroup = new ClRuntimeParameterHandler().getParameters(arguments);
+        ClRuntimeActivator activator = new ClRuntimeActivator(parameterGroup);
+        activator.isAlive();
+
+        assertFalse(activator.isAlive());
+        activator.start();
+        assertTrue(activator.isAlive());
+        assertTrue(activator.getParameterGroup().isValid());
+        assertEquals(activator.getParameterGroup().getName(),
+                activator.getParameterGroup().getRestServerParameters().getName());
+
+        // repeat start - should throw an exception
+        assertThatIllegalStateException().isThrownBy(() -> activator.start());
+        assertTrue(activator.isAlive());
+        assertTrue(activator.getParameterGroup().isValid());
+
+        activator.stop();
+        assertFalse(activator.isAlive());
+
+        // repeat stop - should throw an exception
+        assertThatIllegalStateException().isThrownBy(() -> activator.stop());
+        assertFalse(activator.isAlive());
+    }
+
+    @Test
+    public void testNull() {
+        assertThatExceptionOfType(ControlLoopRuntimeException.class).isThrownBy(() -> new ClRuntimeActivator(null));
+    }
+
+    @Test
+    public void testNotValid() {
+        assertThatExceptionOfType(ControlLoopRuntimeException.class)
+                .isThrownBy(() -> new ClRuntimeActivator(new ClRuntimeParameterGroup("name")));
+    }
+}
diff --git a/tosca-controlloop/runtime/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/MainTest.java b/tosca-controlloop/runtime/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/MainTest.java
new file mode 100644 (file)
index 0000000..6dd4031
--- /dev/null
@@ -0,0 +1,157 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.main.startstop;
+
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.clamp.controlloop.common.ControlLoopConstants;
+import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException;
+import org.onap.policy.common.utils.resources.MessageConstants;
+import org.onap.policy.common.utils.services.Registry;
+
+/**
+ * Class to perform unit test of {@link Main}}.
+ *
+ */
+public class MainTest {
+
+    public static final String POLICY_CLAMP_FAILURE_MSG =
+            String.format(MessageConstants.START_FAILURE_MSG, MessageConstants.POLICY_CLAMP);
+
+    /**
+     * Set up.
+     */
+    @BeforeClass
+    public static void setUp() {
+        Registry.newRegistry();
+    }
+
+    /**
+     * Shuts "main" down.
+     *
+     * @throws Exception if an error occurs
+     */
+    @AfterClass
+    public static void tearDown() throws Exception {
+        // shut down activator
+        final ClRuntimeActivator activator =
+                Registry.getOrDefault(ControlLoopConstants.REG_CLRUNTIME_ACTIVATOR, ClRuntimeActivator.class, null);
+        if (activator != null && activator.isAlive()) {
+            activator.shutdown();
+        }
+    }
+
+    @Test
+    public void testMain_Help() {
+        final String[] configParameters = {"-h"};
+        Main main = new Main(configParameters);
+        assertFalse(main.isRunning());
+    }
+
+    @Test
+    public void testMain_Version() {
+        final String[] configParameters = {"-v"};
+        Main main = new Main(configParameters);
+        assertFalse(main.isRunning());
+    }
+
+    @Test
+    public void testMain_Valid() {
+        final String[] configParameters = {"-c", "src/test/resources/parameters/TestParameters.json"};
+        Main main = new Main(configParameters);
+        assertTrue(main.isRunning());
+
+        // ensure items were added to the registry
+        assertNotNull(Registry.get(ControlLoopConstants.REG_CLRUNTIME_ACTIVATOR, ClRuntimeActivator.class));
+
+        assertThatCode(() -> main.shutdown()).doesNotThrowAnyException();
+
+        assertFalse(main.isRunning());
+    }
+
+    @Test
+    public void testMain_NoParameter() {
+        assertThatConfigParameterThrownException(new String[] {});
+    }
+
+    @Test
+    public void testMain_FilePathNotDefined() {
+        assertThatConfigParameterThrownException(new String[] {"-c"});
+    }
+
+    @Test
+    public void testMain_TooManyCommand() {
+        assertThatConfigParameterThrownException(new String[] {"-h", "d"});
+    }
+
+    @Test
+    public void testMain_WrongParameter() {
+        assertThatConfigParameterThrownException(new String[] {"-d"});
+    }
+
+    private void assertThatConfigParameterThrownException(final String[] configParameters) {
+        assertThatThrownBy(() -> Main.main(configParameters)).isInstanceOf(ControlLoopRuntimeException.class)
+                .hasMessage(POLICY_CLAMP_FAILURE_MSG);
+    }
+
+    @Test
+    public void testParticipant_NoFileWithThisName() {
+        assertThatConfigFileThrownException("src/test/resources/parameters/NoFileWithThisName.json");
+    }
+
+    @Test
+    public void testParticipant_NotValidFile() {
+        assertThatConfigFileThrownException("src/test/resources/parameters");
+    }
+
+    @Test
+    public void testParticipant_FileEmpty() {
+        assertThatConfigFileThrownException("src/test/resources/parameters/EmptyParameters.json");
+    }
+
+    @Test
+    public void testParticipant_NoParameters() {
+        assertThatConfigFileThrownException("src/test/resources/parameters/NoParameters.json");
+    }
+
+    @Test
+    public void testParticipant_InvalidParameters() {
+        assertThatConfigFileThrownException("src/test/resources/parameters/InvalidParameters.json");
+    }
+
+    @Test
+    public void testParticipant_WrongJsonFormat() {
+        assertThatConfigFileThrownException("src/test/resources/parameters/Unreadable.json");
+    }
+
+    private void assertThatConfigFileThrownException(final String configFilePath) {
+        final String[] configParameters = new String[] {"-c", configFilePath};
+        assertThatThrownBy(() -> new Main(configParameters)).isInstanceOf(ControlLoopRuntimeException.class)
+                .hasMessage(POLICY_CLAMP_FAILURE_MSG);
+    }
+}
diff --git a/tosca-controlloop/runtime/src/test/resources/parameters/EmptyParameters.json b/tosca-controlloop/runtime/src/test/resources/parameters/EmptyParameters.json
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tosca-controlloop/runtime/src/test/resources/parameters/InvalidParameters.json b/tosca-controlloop/runtime/src/test/resources/parameters/InvalidParameters.json
new file mode 100644 (file)
index 0000000..976ec29
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  "name": ""
+}
diff --git a/tosca-controlloop/runtime/src/test/resources/parameters/NoParameters.json b/tosca-controlloop/runtime/src/test/resources/parameters/NoParameters.json
new file mode 100644 (file)
index 0000000..2c63c08
--- /dev/null
@@ -0,0 +1,2 @@
+{
+}
diff --git a/tosca-controlloop/runtime/src/test/resources/parameters/TestParameters.json b/tosca-controlloop/runtime/src/test/resources/parameters/TestParameters.json
new file mode 100644 (file)
index 0000000..c3be762
--- /dev/null
@@ -0,0 +1,79 @@
+{
+    "name": "ControlLoopRuntimeGroup",
+    "restServerParameters": {
+        "host": "0.0.0.0",
+        "port": 6969,
+        "userName": "healthcheck",
+        "password": "zb!XztG34",
+        "https": false,
+        "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.h2.Driver",
+        "databaseUrl": "jdbc:h2:mem:testdb",
+        "databaseUser": "policy",
+        "databasePassword": "P01icY",
+        "persistenceUnit": "ToscaConceptTest"
+    },
+    "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"
+            }
+        ]
+    },
+    "healthCheckRestClientParameters": [
+        {
+            "clientName": "api",
+            "hostname": "policy-api",
+            "port": 6969,
+            "userName": "healthcheck",
+            "password": "zb!XztG34",
+            "useHttps": true,
+            "basePath": "policy/api/v1/healthcheck"
+        },
+        {
+            "clientName": "distribution",
+            "hostname": "policy-distribution",
+            "port": 6969,
+            "userName": "healthcheck",
+            "password": "zb!XztG34",
+            "useHttps": true,
+            "basePath": "healthcheck"
+        }
+    ]
+}
diff --git a/tosca-controlloop/runtime/src/test/resources/parameters/Unreadable.json b/tosca-controlloop/runtime/src/test/resources/parameters/Unreadable.json
new file mode 100644 (file)
index 0000000..e69de15
--- /dev/null
@@ -0,0 +1,79 @@
+{
+    "name": "ControlLoopRuntimeGroup",
+    "restServerParameters": {
+        "host": "0.0.0.0",
+        "port": 6969,
+        "userName": "healthcheck",
+        "password": "zb!XztG34",
+        "https": false,
+        "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.h2.Driver",
+        "databaseUrl": "jdbc:h2:mem:testdb",
+        "databaseUser": "policy",
+        "databasePassword": "P01icY",
+        "persistenceUnit": "ToscaConceptTest"
+    },
+    "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"
+            }
+        ]
+    },
+    "healthCheckRestClientParameters": [
+        {
+            "clientName": "api",
+            "hostname": "policy-api",
+            "port": 6969,
+            "userName": "healthcheck",
+            "password": "zb!XztG34",
+            "useHttps": true,
+            "basePath": "policy/api/v1/healthcheck"
+        },
+        {
+            "clientName": "distribution",
+            "hostname": "policy-distribution",
+            "port": 6969,
+            "userName": "healthcheck",
+            "password": "zb!XztG34",
+            "useHttps": true,
+            "basePath": "healthcheck"
+        }
+    ]
+    
\ No newline at end of file