CDS Actor service-provider implemntation
https://wiki.onap.org/display/DW/CDS+actor+support+in+Policy
Issue-ID: POLICY-1763
Signed-off-by: Rashmi Pujar <rashmi.pujar@bell.ca>
Change-Id: Idcb6e9168b949745cc644e97ba77c479573a8bf5
diff --git a/models-interactions/model-actors/actor.cds/pom.xml b/models-interactions/model-actors/actor.cds/pom.xml
new file mode 100644
index 0000000..5c4a044
--- /dev/null
+++ b/models-interactions/model-actors/actor.cds/pom.xml
@@ -0,0 +1,71 @@
+<!--
+ ============LICENSE_START=======================================================
+ Copyright (C) 2019 Bell Canada. 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=========================================================
+ -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.policy.models.policy-models-interactions.model-actors</groupId>
+ <artifactId>model-actors</artifactId>
+ <version>2.1.3-SNAPSHOT</version>
+ </parent>
+ <artifactId>actor.cds</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.policy.models.policy-models-interactions.model-actors</groupId>
+ <artifactId>actorServiceProvider</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId>
+ <artifactId>cds</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId>
+ <artifactId>events</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.models.policy-models-interactions</groupId>
+ <artifactId>simulators</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.common</groupId>
+ <artifactId>policy-endpoints</artifactId>
+ <version>${policy.common.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId>
+ <artifactId>aai</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProvider.java b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProvider.java
new file mode 100644
index 0000000..aaf07ac
--- /dev/null
+++ b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProvider.java
@@ -0,0 +1,240 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Bell Canada. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.cds;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.Struct;
+import com.google.protobuf.Struct.Builder;
+import com.google.protobuf.util.JsonFormat;
+import io.grpc.Status;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers;
+import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader;
+import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType;
+import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput;
+import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput;
+import org.onap.policy.cds.api.CdsProcessorListener;
+import org.onap.policy.cds.client.CdsProcessorGrpcClient;
+import org.onap.policy.cds.properties.CdsServerProperties;
+import org.onap.policy.controlloop.ControlLoopOperation;
+import org.onap.policy.controlloop.VirtualControlLoopEvent;
+import org.onap.policy.controlloop.actor.cds.beans.ConfigDeployRequest;
+import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants;
+import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
+import org.onap.policy.controlloop.policy.Policy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * CDS Actor service-provider implementation. This is a deploy dark feature for El-Alto release.
+ */
+public class CdsActorServiceProvider implements Actor {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CdsActorServiceProvider.class);
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public String actor() {
+ return CdsActorConstants.CDS_ACTOR;
+ }
+
+ /**
+ * {@inheritDoc}. Note: This is a placeholder for now.
+ */
+ @Override
+ public List<String> recipes() {
+ return new ArrayList<>();
+ }
+
+ /**
+ * {@inheritDoc}. Note: This is a placeholder for now.
+ */
+ @Override
+ public List<String> recipeTargets(final String recipe) {
+ return new ArrayList<>();
+ }
+
+ /**
+ * {@inheritDoc}. Note: This is a placeholder for now.
+ */
+ @Override
+ public List<String> recipePayloads(final String recipe) {
+ return new ArrayList<>();
+ }
+
+ /**
+ * Build the CDS ExecutionServiceInput request from the policy object and the AAI enriched parameters. TO-DO: Avoid
+ * leaking Exceptions to the Kie Session thread. TBD item for Frankfurt release.
+ *
+ * @param onset the event that is reporting the alert for policy to perform an action.
+ * @param operation the control loop operation specifying the actor, operation, target, etc.
+ * @param policy the policy specified from the yaml generated by CLAMP or through Policy API.
+ * @param aaiParams Map of enriched AAI attributes in node.attribute notation.
+ * @return an Optional ExecutionServiceInput instance if valid else an Optional empty object is returned.
+ */
+ public Optional<ExecutionServiceInput> constructRequest(VirtualControlLoopEvent onset,
+ ControlLoopOperation operation, Policy policy, Map<String, String> aaiParams) {
+
+ // For the current operational TOSCA policy model (yaml) CBA name and version are embedded in the payload
+ // section, with the new policy type model being proposed in Frankfurt we will be able to move it out.
+ Map<String, String> payload = policy.getPayload();
+ if (!validateCdsMandatoryParams(policy)) {
+ return Optional.empty();
+ }
+ String cbaName = payload.get(CdsActorConstants.KEY_CBA_NAME);
+ String cbaVersion = payload.get(CdsActorConstants.KEY_CBA_VERSION);
+ String cbaActionName = policy.getRecipe();
+
+ // Embed payload from policy to ConfigDeployRequest object, serialize and inject into grpc request.
+ ConfigDeployRequest request = new ConfigDeployRequest();
+ request.setConfigDeployProperties(payload);
+
+ // Inject AAI properties into payload map. Offer flexibility to the usecase
+ // implementation to inject whatever AAI parameters are of interest to them.
+ // E.g. For vFW usecase El-Alto inject service-instance-id, generic-vnf-id as needed by CDS.
+ request.setAaiProperties(aaiParams);
+
+ Builder struct = Struct.newBuilder();
+ try {
+ String requestStr = request.toString();
+ Preconditions.checkState(!Strings.isNullOrEmpty(requestStr), "Unable to build "
+ + "config-deploy-request from payload parameters: {}", payload);
+ JsonFormat.parser().merge(requestStr, struct);
+ } catch (InvalidProtocolBufferException e) {
+ LOGGER.error("Failed to parse received message. blueprint({}:{}) for action({})", cbaName, cbaVersion,
+ cbaActionName, e);
+ return Optional.empty();
+ }
+
+ // Build CDS gRPC request common-header
+ CommonHeader commonHeader = CommonHeader.newBuilder()
+ .setOriginatorId(CdsActorConstants.ORIGINATOR_ID)
+ .setRequestId(onset.getRequestId().toString())
+ .setSubRequestId(operation.getSubRequestId())
+ .build();
+
+ // Build CDS gRPC request action-identifier
+ ActionIdentifiers actionIdentifiers = ActionIdentifiers.newBuilder()
+ .setBlueprintName(cbaName)
+ .setBlueprintVersion(cbaVersion)
+ .setActionName(cbaActionName)
+ .setMode(CdsActorConstants.CDS_MODE)
+ .build();
+
+ // Finally build the ExecutionServiceInput gRPC request object.
+ ExecutionServiceInput executionServiceInput = ExecutionServiceInput.newBuilder()
+ .setCommonHeader(commonHeader)
+ .setActionIdentifiers(actionIdentifiers)
+ .setPayload(struct.build())
+ .build();
+ return Optional.of(executionServiceInput);
+ }
+
+ private boolean validateCdsMandatoryParams(Policy policy) {
+ if (policy == null || policy.getPayload() == null) {
+ return false;
+ }
+ Map<String, String> payload = policy.getPayload();
+ String cbaName = payload.get(CdsActorConstants.KEY_CBA_NAME);
+ String cbaVersion = payload.get(CdsActorConstants.KEY_CBA_VERSION);
+ String cbaActionName = policy.getRecipe();
+ return !Strings.isNullOrEmpty(cbaName) && !Strings.isNullOrEmpty(cbaVersion) && !Strings
+ .isNullOrEmpty(cbaActionName);
+ }
+
+ class CdsActorServiceManager implements CdsProcessorListener {
+
+ private final AtomicReference<String> cdsResponse = new AtomicReference<>();
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public void onMessage(final ExecutionServiceOutput message) {
+ LOGGER.info("Received notification from CDS: {}", message);
+ EventType eventType = message.getStatus().getEventType();
+ switch (eventType) {
+ case EVENT_COMPONENT_FAILURE:
+ cdsResponse.compareAndSet(null, CdsActorConstants.FAILED);
+ break;
+ case EVENT_COMPONENT_PROCESSING:
+ cdsResponse.compareAndSet(null, CdsActorConstants.PROCESSING);
+ break;
+ case EVENT_COMPONENT_EXECUTED:
+ cdsResponse.compareAndSet(null, CdsActorConstants.SUCCESS);
+ break;
+ default:
+ cdsResponse.compareAndSet(null, CdsActorConstants.FAILED);
+ break;
+ }
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public void onError(final Throwable throwable) {
+ Status status = Status.fromThrowable(throwable);
+ cdsResponse.compareAndSet(null, CdsActorConstants.ERROR);
+ LOGGER.error("Failed processing blueprint {} {}", status, throwable);
+ }
+
+ /**
+ * Send gRPC request to CDS to execute the blueprint.
+ *
+ * @param cdsClient CDS grpc client object.
+ * @param cdsProps CDS properties.
+ * @param executionServiceInput a valid CDS grpc request object.
+ * @return Status of the CDS request, null if timeout happens or onError is invoked for any reason.
+ */
+ public String sendRequestToCds(CdsProcessorGrpcClient cdsClient, CdsServerProperties cdsProps,
+ ExecutionServiceInput executionServiceInput) {
+ try {
+ LOGGER.trace("Start CdsActorServiceProvider.executeCdsBlueprintProcessor {}.", executionServiceInput);
+ // TO-DO: Handle requests asynchronously once the callback support is added to actors.
+ CountDownLatch countDownLatch = cdsClient.sendRequest(executionServiceInput);
+ boolean status = countDownLatch.await(cdsProps.getTimeout(), TimeUnit.SECONDS);
+ if (!status) {
+ cdsResponse.compareAndSet(null, CdsActorConstants.TIMED_OUT);
+ }
+ LOGGER.info("CDS response {}", getCdsResponse());
+ } catch (InterruptedException ex) {
+ LOGGER.error("Caught exception in executeCdsBlueprintProcessor in CdsActorServiceProvider: ", ex);
+ cdsResponse.compareAndSet(null, CdsActorConstants.INTERRUPTED);
+ Thread.currentThread().interrupt();
+ }
+ LOGGER.info("Status of the CDS gRPC request is: {}", getCdsResponse());
+ return getCdsResponse();
+ }
+
+ String getCdsResponse() {
+ return cdsResponse.get();
+ }
+ }
+}
diff --git a/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/beans/ConfigDeployRequest.java b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/beans/ConfigDeployRequest.java
new file mode 100644
index 0000000..f33f226
--- /dev/null
+++ b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/beans/ConfigDeployRequest.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Bell Canada. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.cds.beans;
+
+import com.google.gson.Gson;
+import com.google.gson.annotations.SerializedName;
+import java.util.Map;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ConfigDeployRequest {
+
+ private static final Gson GSON = new Gson();
+
+ @SerializedName("config-deploy-properties")
+ private Map<String, String> configDeployProperties;
+
+ @SerializedName("aai-properties")
+ private Map<String, String> aaiProperties;
+
+ @Override
+ public String toString() {
+ return "{\"config-deploy-request\":" + GSON.toJson(this) + '}';
+ }
+}
diff --git a/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/constants/CdsActorConstants.java b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/constants/CdsActorConstants.java
new file mode 100644
index 0000000..b79aca0
--- /dev/null
+++ b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/constants/CdsActorConstants.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Bell Canada. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.cds.constants;
+
+public class CdsActorConstants {
+
+ public static final String CDS_ACTOR = "CDS";
+
+ // CDS Status
+ public static final String SUCCESS = "Success";
+ public static final String FAILED = "Failed";
+ public static final String PROCESSING = "Processing";
+ public static final String TIMED_OUT = "Timed out";
+ public static final String INTERRUPTED = "Thread interrupted";
+ public static final String ERROR = "Error";
+
+ // CDS blueprint archive parameters
+ public static final String KEY_CBA_NAME = "artifact_name";
+ public static final String KEY_CBA_VERSION = "artifact_version";
+ public static final String ORIGINATOR_ID = "POLICY";
+ // Temporarily set to synchronous mode to support current rules, since callbacks aren't supported yet
+ public static final String CDS_MODE = "sync";
+}
diff --git a/models-interactions/model-actors/actor.cds/src/main/resources/META-INF.services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor b/models-interactions/model-actors/actor.cds/src/main/resources/META-INF.services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor
new file mode 100644
index 0000000..e91d419
--- /dev/null
+++ b/models-interactions/model-actors/actor.cds/src/main/resources/META-INF.services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor
@@ -0,0 +1 @@
+org.onap.policy.controlloop.actor.cds.CdsActorServiceProvider
diff --git a/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProviderTest.java b/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProviderTest.java
new file mode 100644
index 0000000..65fd602
--- /dev/null
+++ b/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProviderTest.java
@@ -0,0 +1,237 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Bell Canada. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.cds;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers;
+import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader;
+import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType;
+import org.onap.ccsdk.cds.controllerblueprints.common.api.Status;
+import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput;
+import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput;
+import org.onap.policy.cds.client.CdsProcessorGrpcClient;
+import org.onap.policy.cds.properties.CdsServerProperties;
+import org.onap.policy.controlloop.ControlLoopOperation;
+import org.onap.policy.controlloop.VirtualControlLoopEvent;
+import org.onap.policy.controlloop.actor.cds.CdsActorServiceProvider.CdsActorServiceManager;
+import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants;
+import org.onap.policy.controlloop.policy.Policy;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CdsActorServiceProviderTest {
+
+ private static final String CDS_BLUEPRINT_NAME = "vfw-cds";
+ private static final String CDS_BLUEPRINT_VERSION = "1.0.0";
+ private static final UUID REQUEST_ID = UUID.randomUUID();
+ private static final String SUBREQUEST_ID = "123456";
+
+ @Rule
+ public ExpectedException exceptionRule = ExpectedException.none();
+ @Mock
+ private CdsProcessorGrpcClient cdsClient;
+ private CdsActorServiceProvider cdsActor;
+ private Policy policy;
+ private CdsServerProperties cdsProps;
+ private Map<String, String> aaiParams;
+ private VirtualControlLoopEvent onset;
+ private ControlLoopOperation operation;
+
+ /**
+ * Test setup.
+ */
+ @Before
+ public void setup() {
+ // Setup policy
+ policy = new Policy();
+ Map<String, String> payloadMap = new HashMap<String, String>() {
+ {
+ put(CdsActorConstants.KEY_CBA_NAME, CDS_BLUEPRINT_NAME);
+ put(CdsActorConstants.KEY_CBA_VERSION, CDS_BLUEPRINT_VERSION);
+ put("data", "{\"mapInfo\":{\"key\":\"val\"},\"arrayInfo\":[\"one\",\"two\"],\"paramInfo\":\"val\"}");
+ }
+ };
+ policy.setPayload(payloadMap);
+ policy.setRecipe("CDS");
+
+ // Setup the CDS properties
+ cdsProps = new CdsServerProperties();
+ cdsProps.setHost("10.10.10.10");
+ cdsProps.setPort(2000);
+ cdsProps.setUsername("testUser");
+ cdsProps.setPassword("testPassword");
+ cdsProps.setTimeout(1);
+
+ // Setup aaiParams
+ aaiParams = ImmutableMap.of("service-instance-id", "1234", "generic-vnf-id", "5678");
+
+ // Setup cdsClient
+ when(cdsClient.sendRequest(any(ExecutionServiceInput.class))).thenReturn(mock(CountDownLatch.class));
+
+ // Setup the cdsActor
+ cdsActor = new CdsActorServiceProvider();
+
+ // Setup onset event
+ onset = new VirtualControlLoopEvent();
+ onset.setRequestId(REQUEST_ID);
+
+ // Setup controlloop operation object
+ operation = new ControlLoopOperation();
+ operation.setSubRequestId(SUBREQUEST_ID);
+ }
+
+ @Test
+ public void testActor() {
+ assertEquals(cdsActor.actor(), CdsActorConstants.CDS_ACTOR);
+ }
+
+ @Test
+ public void testConstructRequest() {
+ policy.setPayload(new HashMap<>());
+ Optional<ExecutionServiceInput> cdsRequestOpt = cdsActor
+ .constructRequest(onset, operation, policy, aaiParams);
+
+ assertFalse(cdsRequestOpt.isPresent());
+ }
+
+ @Test
+ public void testConstructRequestWhenMissingCdsParamsInPolicyPayload() {
+ Optional<ExecutionServiceInput> cdsRequestOpt = cdsActor
+ .constructRequest(onset, operation, policy, aaiParams);
+
+ assertTrue(cdsRequestOpt.isPresent());
+ final ExecutionServiceInput cdsRequest = cdsRequestOpt.get();
+
+ assertTrue(cdsRequest.hasCommonHeader());
+ CommonHeader commonHeader = cdsRequest.getCommonHeader();
+ assertEquals(commonHeader.getRequestId(), REQUEST_ID.toString());
+ assertEquals(commonHeader.getSubRequestId(), SUBREQUEST_ID);
+
+ assertTrue(cdsRequest.hasPayload());
+
+ assertTrue(cdsRequest.hasActionIdentifiers());
+ ActionIdentifiers actionIdentifiers = cdsRequest.getActionIdentifiers();
+ assertEquals(actionIdentifiers.getActionName(), CdsActorConstants.CDS_ACTOR);
+ assertEquals(actionIdentifiers.getBlueprintName(), CDS_BLUEPRINT_NAME);
+ assertEquals(actionIdentifiers.getBlueprintVersion(), CDS_BLUEPRINT_VERSION);
+ }
+
+ @Test
+ public void testRecipePayloads() {
+ assertEquals(cdsActor.recipePayloads("").size(), 0);
+ }
+
+ @Test
+ public void testRecipes() {
+ assertEquals(cdsActor.recipes().size(), 0);
+ }
+
+ @Test
+ public void testRecipeTargets() {
+ assertEquals(cdsActor.recipeTargets("").size(), 0);
+ }
+
+ @Test
+ public void testSendRequestToCdsSuccess() {
+ sendRequestToCds();
+ verify(cdsClient).sendRequest(any(ExecutionServiceInput.class));
+ }
+
+ @Test
+ public void testSendRequestToCdsLatchInterrupted() throws InterruptedException {
+ // Reset cdsClient
+ CountDownLatch countDownLatch = mock(CountDownLatch.class);
+ doThrow(new InterruptedException("Test latch interrupted failure")).when(countDownLatch)
+ .await(anyLong(), any(TimeUnit.class));
+ when(cdsClient.sendRequest(any(ExecutionServiceInput.class))).thenReturn(countDownLatch);
+
+ CdsActorServiceProvider.CdsActorServiceManager cdsActorSvcMgr = cdsActor.new CdsActorServiceManager();
+ String response = cdsActorSvcMgr
+ .sendRequestToCds(cdsClient, cdsProps, ExecutionServiceInput.newBuilder().build());
+ assertTrue(Thread.interrupted());
+ assertEquals(response, CdsActorConstants.INTERRUPTED);
+ }
+
+ @Test
+ public void testSendRequestToCdsLatchTimedOut() {
+ CdsActorServiceProvider.CdsActorServiceManager cdsActorSvcMgr = cdsActor.new CdsActorServiceManager();
+ String response = cdsActorSvcMgr
+ .sendRequestToCds(cdsClient, cdsProps, ExecutionServiceInput.newBuilder().build());
+ assertEquals(response, CdsActorConstants.TIMED_OUT);
+ }
+
+ @Test
+ public void testOnMessage() throws InterruptedException {
+ ExecutionServiceOutput message = ExecutionServiceOutput.newBuilder()
+ .setStatus(Status.newBuilder().setEventType(EventType.EVENT_COMPONENT_FAILURE).build()).build();
+
+ // Test "no timeout" scenarios
+ CountDownLatch latch = mock(CountDownLatch.class);
+ when(latch.await(anyLong(), any(TimeUnit.class))).thenReturn(true);
+ when(cdsClient.sendRequest(any(ExecutionServiceInput.class))).thenReturn(latch);
+
+ CdsActorServiceManager cdsActorSvcMgr = sendRequestToCds();
+
+ // #1: Failure test
+ cdsActorSvcMgr.onMessage(message);
+ assertEquals(cdsActorSvcMgr.getCdsResponse(), CdsActorConstants.FAILED);
+
+ // #2: Success test
+ cdsActorSvcMgr = sendRequestToCds();
+ message = ExecutionServiceOutput.newBuilder()
+ .setStatus(Status.newBuilder().setEventType(EventType.EVENT_COMPONENT_EXECUTED).build()).build();
+ cdsActorSvcMgr.onMessage(message);
+ assertEquals(cdsActorSvcMgr.getCdsResponse(), CdsActorConstants.SUCCESS);
+
+ // #3: Processing test
+ cdsActorSvcMgr = sendRequestToCds();
+ message = ExecutionServiceOutput.newBuilder()
+ .setStatus(Status.newBuilder().setEventType(EventType.EVENT_COMPONENT_PROCESSING).build()).build();
+ cdsActorSvcMgr.onMessage(message);
+ assertEquals(cdsActorSvcMgr.getCdsResponse(), CdsActorConstants.PROCESSING);
+ }
+
+ private CdsActorServiceManager sendRequestToCds() {
+ CdsActorServiceManager cdsActorSvcMgr = cdsActor.new CdsActorServiceManager();
+ cdsActorSvcMgr.sendRequestToCds(cdsClient, cdsProps, ExecutionServiceInput.newBuilder().build());
+ return cdsActorSvcMgr;
+ }
+}
diff --git a/models-interactions/model-actors/pom.xml b/models-interactions/model-actors/pom.xml
index 03c6458..0f37e1a 100644
--- a/models-interactions/model-actors/pom.xml
+++ b/models-interactions/model-actors/pom.xml
@@ -38,6 +38,7 @@
<module>actor.appclcm</module>
<module>actor.sdnr</module>
<module>actor.so</module>
+ <module>actor.cds</module>
<module>actor.test</module>
</modules>
<dependencies>