summaryrefslogtreecommitdiffstats
path: root/models-interactions/model-actors/actor.sdnc
diff options
context:
space:
mode:
Diffstat (limited to 'models-interactions/model-actors/actor.sdnc')
-rw-r--r--models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperator.java24
-rw-r--r--models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperator.java22
-rw-r--r--models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProvider.java27
-rw-r--r--models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncOperator.java132
-rw-r--r--models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperatorTest.java70
-rw-r--r--models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BasicOperator.java94
-rw-r--r--models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperatorTest.java70
-rw-r--r--models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProviderTest.java25
-rw-r--r--models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncOperatorTest.java326
-rw-r--r--models-interactions/model-actors/actor.sdnc/src/test/resources/bod.json32
-rw-r--r--models-interactions/model-actors/actor.sdnc/src/test/resources/reroute.json17
11 files changed, 730 insertions, 109 deletions
diff --git a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperator.java b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperator.java
index 0e721bf8c..2927bd85b 100644
--- a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperator.java
+++ b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperator.java
@@ -22,7 +22,7 @@ package org.onap.policy.controlloop.actor.sdnc;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
-import org.onap.policy.controlloop.VirtualControlLoopEvent;
+import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
import org.onap.policy.sdnc.SdncHealRequest;
import org.onap.policy.sdnc.SdncHealRequestHeaderInfo;
import org.onap.policy.sdnc.SdncHealRequestInfo;
@@ -37,6 +37,12 @@ import org.onap.policy.sdnc.SdncRequest;
public class BandwidthOnDemandOperator extends SdncOperator {
public static final String NAME = "BandwidthOnDemand";
+ public static final String URI = "/GENERIC-RESOURCE-API:vf-module-topology-operation";
+
+ // fields in the enrichment data
+ public static final String SERVICE_ID_KEY = "service-instance.service-instance-id";
+ public static final String VNF_ID = "vnfId";
+
/**
* Constructs the object.
*
@@ -47,19 +53,19 @@ public class BandwidthOnDemandOperator extends SdncOperator {
}
@Override
- protected SdncRequest constructRequest(VirtualControlLoopEvent onset) {
- String serviceInstance = onset.getAai().get("service-instance.service-instance-id");
+ protected SdncRequest constructRequest(ControlLoopEventContext context) {
+ String serviceInstance = context.getEnrichment().get(SERVICE_ID_KEY);
if (StringUtils.isBlank(serviceInstance)) {
- throw new IllegalArgumentException("missing enrichment data, service-instance-id");
+ throw new IllegalArgumentException("missing enrichment data, " + SERVICE_ID_KEY);
}
SdncHealVfModuleParameter bandwidth = new SdncHealVfModuleParameter();
bandwidth.setName("bandwidth");
- bandwidth.setValue(onset.getAai().get("bandwidth"));
+ bandwidth.setValue(context.getEnrichment().get("bandwidth"));
SdncHealVfModuleParameter timeStamp = new SdncHealVfModuleParameter();
timeStamp.setName("bandwidth-change-time");
- timeStamp.setValue(onset.getAai().get("bandwidth-change-time"));
+ timeStamp.setValue(context.getEnrichment().get("bandwidth-change-time"));
SdncHealVfModuleParametersInfo vfParametersInfo = new SdncHealVfModuleParametersInfo();
vfParametersInfo.addParameters(bandwidth);
@@ -80,11 +86,11 @@ public class BandwidthOnDemandOperator extends SdncOperator {
SdncRequest request = new SdncRequest();
request.setNsInstanceId(serviceInstance);
- request.setRequestId(onset.getRequestId());
- request.setUrl("/GENERIC-RESOURCE-API:vf-module-topology-operation");
+ request.setRequestId(context.getRequestId());
+ request.setUrl(URI);
SdncHealVnfInfo vnfInfo = new SdncHealVnfInfo();
- vnfInfo.setVnfId(onset.getAai().get("vnfId"));
+ vnfInfo.setVnfId(context.getEnrichment().get(VNF_ID));
SdncHealVfModuleInfo vfModuleInfo = new SdncHealVfModuleInfo();
vfModuleInfo.setVfModuleId("");
diff --git a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperator.java b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperator.java
index 59af31f4f..da400f8eb 100644
--- a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperator.java
+++ b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperator.java
@@ -22,7 +22,7 @@ package org.onap.policy.controlloop.actor.sdnc;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
-import org.onap.policy.controlloop.VirtualControlLoopEvent;
+import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
import org.onap.policy.sdnc.SdncHealNetworkInfo;
import org.onap.policy.sdnc.SdncHealRequest;
import org.onap.policy.sdnc.SdncHealRequestHeaderInfo;
@@ -33,6 +33,12 @@ import org.onap.policy.sdnc.SdncRequest;
public class RerouteOperator extends SdncOperator {
public static final String NAME = "Reroute";
+ public static final String URI = "/GENERIC-RESOURCE-API:network-topology-operation";
+
+ // fields in the enrichment data
+ public static final String SERVICE_ID_KEY = "service-instance.service-instance-id";
+ public static final String NETWORK_ID_KEY = "network-information.network-id";
+
/**
* Constructs the object.
*
@@ -43,17 +49,17 @@ public class RerouteOperator extends SdncOperator {
}
@Override
- protected SdncRequest constructRequest(VirtualControlLoopEvent onset) {
- String serviceInstance = onset.getAai().get("service-instance.service-instance-id");
+ protected SdncRequest constructRequest(ControlLoopEventContext context) {
+ String serviceInstance = context.getEnrichment().get(SERVICE_ID_KEY);
if (StringUtils.isBlank(serviceInstance)) {
- throw new IllegalArgumentException("missing enrichment data, service-instance-id");
+ throw new IllegalArgumentException("missing enrichment data, " + SERVICE_ID_KEY);
}
SdncHealServiceInfo serviceInfo = new SdncHealServiceInfo();
serviceInfo.setServiceInstanceId(serviceInstance);
- String networkId = onset.getAai().get("network-information.network-id");
+ String networkId = context.getEnrichment().get(NETWORK_ID_KEY);
if (StringUtils.isBlank(networkId)) {
- throw new IllegalArgumentException("missing enrichment data, network-id");
+ throw new IllegalArgumentException("missing enrichment data, " + NETWORK_ID_KEY);
}
SdncHealNetworkInfo networkInfo = new SdncHealNetworkInfo();
networkInfo.setNetworkId(networkId);
@@ -67,8 +73,8 @@ public class RerouteOperator extends SdncOperator {
SdncRequest request = new SdncRequest();
request.setNsInstanceId(serviceInstance);
- request.setRequestId(onset.getRequestId());
- request.setUrl("/GENERIC-RESOURCE-API:network-topology-operation");
+ request.setRequestId(context.getRequestId());
+ request.setUrl(URI);
SdncHealRequest healRequest = new SdncHealRequest();
healRequest.setRequestHeaderInfo(headerInfo);
diff --git a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProvider.java b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProvider.java
index 13276f929..8dc8ba50d 100644
--- a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProvider.java
+++ b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProvider.java
@@ -26,14 +26,10 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
import java.util.UUID;
-import java.util.function.Function;
import org.onap.policy.controlloop.ControlLoopOperation;
import org.onap.policy.controlloop.VirtualControlLoopEvent;
-import org.onap.policy.controlloop.actorserviceprovider.Util;
-import org.onap.policy.controlloop.actorserviceprovider.impl.ActorImpl;
-import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpActorParams;
+import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor;
import org.onap.policy.controlloop.policy.Policy;
import org.onap.policy.sdnc.SdncHealNetworkInfo;
import org.onap.policy.sdnc.SdncHealRequest;
@@ -49,7 +45,7 @@ import org.onap.policy.sdnc.SdncRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class SdncActorServiceProvider extends ActorImpl {
+public class SdncActorServiceProvider extends HttpActor {
private static final Logger logger = LoggerFactory.getLogger(SdncActorServiceProvider.class);
public static final String NAME = "SDNC";
@@ -78,23 +74,10 @@ public class SdncActorServiceProvider extends ActorImpl {
* Constructs the object.
*/
public SdncActorServiceProvider() {
- // @formatter:off
- super(NAME,
- new RerouteOperator(NAME),
- new BandwidthOnDemandOperator(NAME));
+ super(NAME);
- // @formatter:on
- }
-
- @Override
- protected Function<String, Map<String, Object>> makeOperatorParameters(Map<String, Object> actorParameters) {
- String actorName = getName();
-
- // @formatter:off
- return Util.translate(actorName, actorParameters, HttpActorParams.class)
- .doValidation(actorName)
- .makeOperationParameters(actorName);
- // @formatter:on
+ addOperator(new RerouteOperator(NAME));
+ addOperator(new BandwidthOnDemandOperator(NAME));
}
diff --git a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncOperator.java b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncOperator.java
index c2e4c8f8b..479ee908d 100644
--- a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncOperator.java
+++ b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncOperator.java
@@ -22,45 +22,31 @@ package org.onap.policy.controlloop.actor.sdnc;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.CompletableFuture;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
-import lombok.AccessLevel;
-import lombok.Getter;
-import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
import org.onap.policy.common.endpoints.http.client.HttpClient;
-import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
-import org.onap.policy.common.endpoints.utils.NetLoggerUtil;
-import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
-import org.onap.policy.common.parameters.ValidationResult;
-import org.onap.policy.controlloop.ControlLoopOperation;
-import org.onap.policy.controlloop.VirtualControlLoopEvent;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.controlloop.actorserviceprovider.AsyncResponseHandler;
+import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
import org.onap.policy.controlloop.actorserviceprovider.Util;
-import org.onap.policy.controlloop.actorserviceprovider.impl.OperatorPartial;
+import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
+import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
-import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams;
-import org.onap.policy.controlloop.actorserviceprovider.parameters.ParameterValidationRuntimeException;
import org.onap.policy.controlloop.policy.PolicyResult;
import org.onap.policy.sdnc.SdncRequest;
import org.onap.policy.sdnc.SdncResponse;
-import org.onap.policy.sdnc.util.Serialization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Superclass for SDNC Operators.
*/
-public abstract class SdncOperator extends OperatorPartial {
+public abstract class SdncOperator extends HttpOperator {
private static final Logger logger = LoggerFactory.getLogger(SdncOperator.class);
- @Getter(AccessLevel.PROTECTED)
- private HttpClient client;
-
- /**
- * URI path for this particular operation.
- */
- private String path;
-
/**
* Constructs the object.
*
@@ -71,74 +57,92 @@ public abstract class SdncOperator extends OperatorPartial {
super(actorName, name);
}
- // TODO add a junit for this and for plug-in via ActorService
@Override
- protected void doConfigure(Map<String, Object> parameters) {
- HttpParams params = Util.translate(getFullName(), parameters, HttpParams.class);
- ValidationResult result = params.validate(getFullName());
- if (!result.isValid()) {
- throw new ParameterValidationRuntimeException("invalid parameters", result);
- }
+ protected CompletableFuture<OperationOutcome> startOperationAsync(ControlLoopOperationParams params, int attempt,
+ OperationOutcome outcome) {
- client = HttpClientFactoryInstance.getClientFactory().get(params.getClientName());
- path = params.getPath();
- }
-
- @Override
- protected ControlLoopOperation doOperation(ControlLoopOperationParams params, int attempt,
- ControlLoopOperation operation) {
-
- SdncRequest request = constructRequest(params.getContext().getEvent());
- PolicyResult result = doRequest(request);
-
- return setOutcome(params, operation, result);
+ SdncRequest request = constructRequest(params.getContext());
+ return postRequest(params, outcome, request);
}
/**
* Constructs the request.
*
- * @param onset event for which the request should be constructed
+ * @param context associated event context
* @return a new request
*/
- protected abstract SdncRequest constructRequest(VirtualControlLoopEvent onset);
+ protected abstract SdncRequest constructRequest(ControlLoopEventContext context);
/**
- * Posts the request and retrieves the response.
+ * Posts the request and and arranges to retrieve the response.
*
+ * @param params operation parameters
+ * @param outcome updated with the response
* @param sdncRequest request to be posted
* @return the result of the request
*/
- private PolicyResult doRequest(SdncRequest sdncRequest) {
+ private CompletableFuture<OperationOutcome> postRequest(ControlLoopOperationParams params, OperationOutcome outcome,
+ SdncRequest sdncRequest) {
Map<String, Object> headers = new HashMap<>();
headers.put("Accept", "application/json");
- String sdncUrl = client.getBaseUrl();
-
- String sdncRequestJson = Serialization.gsonPretty.toJson(sdncRequest);
+ String sdncUrl = getClient().getBaseUrl();
- // TODO move this into a utility
- NetLoggerUtil.log(EventType.OUT, CommInfrastructure.REST, sdncUrl, sdncRequestJson);
- logger.info("[OUT|{}|{}|]{}{}", CommInfrastructure.REST, sdncUrl, NetLoggerUtil.SYSTEM_LS, sdncRequestJson);
+ Util.logRestRequest(sdncUrl, sdncRequest);
Entity<SdncRequest> entity = Entity.entity(sdncRequest, MediaType.APPLICATION_JSON);
- // TODO modify this to use asynchronous client operations
- Response rawResponse = client.post(path, entity, headers);
- String strResponse = HttpClient.getBody(rawResponse, String.class);
+ ResponseHandler handler = new ResponseHandler(params, outcome, sdncUrl);
+ return handler.handle(getClient().post(handler, getPath(), entity, headers));
+ }
+
+ private class ResponseHandler extends AsyncResponseHandler<Response> {
+ private final String sdncUrl;
- // TODO move this into a utility
- NetLoggerUtil.log(EventType.IN, CommInfrastructure.REST, sdncUrl, strResponse);
- logger.info("[IN|{}|{}|]{}{}", "Sdnc", sdncUrl, NetLoggerUtil.SYSTEM_LS, strResponse);
- logger.info("Response to Sdnc Heal post:");
- logger.info(strResponse);
+ public ResponseHandler(ControlLoopOperationParams params, OperationOutcome outcome, String sdncUrl) {
+ super(params, outcome);
+ this.sdncUrl = sdncUrl;
+ }
- SdncResponse response = Serialization.gsonPretty.fromJson(strResponse, SdncResponse.class);
+ /**
+ * Handles the response.
+ */
+ @Override
+ protected OperationOutcome doComplete(Response rawResponse) {
+ String strResponse = HttpClient.getBody(rawResponse, String.class);
+
+ Util.logRestResponse(sdncUrl, strResponse);
+
+ SdncResponse response;
+ try {
+ response = makeDecoder().decode(strResponse, SdncResponse.class);
+ } catch (CoderException e) {
+ logger.warn("Sdnc Heal cannot decode response with http error code {}", rawResponse.getStatus(), e);
+ return SdncOperator.this.setOutcome(getParams(), getOutcome(), PolicyResult.FAILURE_EXCEPTION);
+ }
+
+ if (response.getResponseOutput() != null && "200".equals(response.getResponseOutput().getResponseCode())) {
+ return SdncOperator.this.setOutcome(getParams(), getOutcome(), PolicyResult.SUCCESS);
+
+ } else {
+ logger.info("Sdnc Heal Restcall failed with http error code {}", rawResponse.getStatus());
+ return SdncOperator.this.setOutcome(getParams(), getOutcome(), PolicyResult.FAILURE);
+ }
+ }
- if (response.getResponseOutput() == null || !"200".equals(response.getResponseOutput().getResponseCode())) {
- logger.info("Sdnc Heal Restcall failed with http error code {}", rawResponse.getStatus());
- return PolicyResult.FAILURE;
+ /**
+ * Handles exceptions.
+ */
+ @Override
+ protected OperationOutcome doFailed(Throwable thrown) {
+ logger.info("Sdnc Heal Restcall threw an exception", thrown);
+ return SdncOperator.this.setOutcome(getParams(), getOutcome(), PolicyResult.FAILURE_EXCEPTION);
}
+ }
+
+ // these may be overridden by junit tests
- return PolicyResult.SUCCESS;
+ protected StandardCoder makeDecoder() {
+ return new StandardCoder();
}
}
diff --git a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperatorTest.java b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperatorTest.java
new file mode 100644
index 000000000..02931a4f1
--- /dev/null
+++ b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperatorTest.java
@@ -0,0 +1,70 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.sdnc;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.sdnc.SdncRequest;
+
+public class BandwidthOnDemandOperatorTest extends BasicOperator {
+
+ private BandwidthOnDemandOperator oper;
+
+
+ /**
+ * Set up.
+ */
+ @Before
+ public void setUp() {
+ makeContext();
+ oper = new BandwidthOnDemandOperator(ACTOR);
+ }
+
+ @Test
+ public void testBandwidthOnDemandOperator() {
+ assertEquals(ACTOR, oper.getActorName());
+ assertEquals(BandwidthOnDemandOperator.NAME, oper.getName());
+ }
+
+ @Test
+ public void testConstructRequest() throws CoderException {
+ SdncRequest request = oper.constructRequest(context);
+ assertEquals("my-service", request.getNsInstanceId());
+ assertEquals(REQ_ID, request.getRequestId());
+ assertEquals(BandwidthOnDemandOperator.URI, request.getUrl());
+ assertNotNull(request.getHealRequest().getRequestHeaderInfo().getSvcRequestId());
+
+ verifyRequest("bod.json", request);
+
+ verifyMissing(oper, BandwidthOnDemandOperator.SERVICE_ID_KEY, "service");
+ }
+
+ @Override
+ protected Map<String, String> makeEnrichment() {
+ return Map.of(BandwidthOnDemandOperator.SERVICE_ID_KEY, "my-service", BandwidthOnDemandOperator.VNF_ID,
+ "my-vnf");
+ }
+}
diff --git a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BasicOperator.java b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BasicOperator.java
new file mode 100644
index 000000000..b9028d462
--- /dev/null
+++ b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BasicOperator.java
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.sdnc;
+
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.UUID;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.controlloop.VirtualControlLoopEvent;
+import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
+
+/**
+ * Superclass for various operator tests.
+ */
+public abstract class BasicOperator {
+ protected static final UUID REQ_ID = UUID.randomUUID();
+ protected static final String ACTOR = "my-actor";
+
+ protected Map<String, String> enrichment;
+ protected VirtualControlLoopEvent event;
+ protected ControlLoopEventContext context;
+
+ /**
+ * Pretty-prints a request and verifies that the result matches the expected JSON.
+ *
+ * @param <T> request type
+ * @param expectedJsonFile name of the file containing the expected JSON
+ * @param request request to verify
+ * @throws CoderException if the request cannot be pretty-printed
+ */
+ protected <T> void verifyRequest(String expectedJsonFile, T request) throws CoderException {
+ String json = new StandardCoder().encode(request, true);
+ String expected = ResourceUtils.getResourceAsString(expectedJsonFile);
+
+ // strip request id, because it changes each time
+ final String stripper = "svc-request-id[^,]*";
+ json = json.replaceFirst(stripper, "").trim();
+ expected = expected.replaceFirst(stripper, "").trim();
+
+ assertEquals(expected, json);
+ }
+
+ /**
+ * Verifies that an exception is thrown if a field is missing from the enrichment
+ * data.
+ *
+ * @param oper operator to construct the request
+ * @param fieldName name of the field to be removed from the enrichment data
+ * @param expectedText text expected in the exception message
+ */
+ protected void verifyMissing(SdncOperator oper, String fieldName, String expectedText) {
+ makeContext();
+ enrichment.remove(fieldName);
+
+ assertThatIllegalArgumentException().isThrownBy(() -> oper.constructRequest(context))
+ .withMessageContaining("missing").withMessageContaining(expectedText);
+ }
+
+ protected void makeContext() {
+ // need a mutable map, so make a copy
+ enrichment = new TreeMap<>(makeEnrichment());
+
+ event = new VirtualControlLoopEvent();
+ event.setRequestId(REQ_ID);
+ event.setAai(enrichment);
+
+ context = new ControlLoopEventContext(event);
+ }
+
+ protected abstract Map<String, String> makeEnrichment();
+}
diff --git a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperatorTest.java b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperatorTest.java
new file mode 100644
index 000000000..0a7bcad6f
--- /dev/null
+++ b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperatorTest.java
@@ -0,0 +1,70 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.sdnc;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.sdnc.SdncRequest;
+
+public class RerouteOperatorTest extends BasicOperator {
+
+ private RerouteOperator oper;
+
+
+ /**
+ * Set up.
+ */
+ @Before
+ public void setUp() {
+ makeContext();
+ oper = new RerouteOperator(ACTOR);
+ }
+
+ @Test
+ public void testRerouteOperator() {
+ assertEquals(ACTOR, oper.getActorName());
+ assertEquals(RerouteOperator.NAME, oper.getName());
+ }
+
+ @Test
+ public void testConstructRequest() throws CoderException {
+ SdncRequest request = oper.constructRequest(context);
+ assertEquals("my-service", request.getNsInstanceId());
+ assertEquals(REQ_ID, request.getRequestId());
+ assertEquals(RerouteOperator.URI, request.getUrl());
+ assertNotNull(request.getHealRequest().getRequestHeaderInfo().getSvcRequestId());
+
+ verifyRequest("reroute.json", request);
+
+ verifyMissing(oper, RerouteOperator.SERVICE_ID_KEY, "service");
+ verifyMissing(oper, RerouteOperator.NETWORK_ID_KEY, "network");
+ }
+
+ @Override
+ protected Map<String, String> makeEnrichment() {
+ return Map.of(RerouteOperator.SERVICE_ID_KEY, "my-service", RerouteOperator.NETWORK_ID_KEY, "my-network");
+ }
+}
diff --git a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProviderTest.java b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProviderTest.java
index 9739c7145..08655c349 100644
--- a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProviderTest.java
+++ b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProviderTest.java
@@ -3,7 +3,7 @@
* TestSdncActorServiceProvider
* ================================================================================
* Copyright (C) 2018-2019 Huawei. All rights reserved.
- * Modifications Copyright (C) 2018-2019 AT&T Corp. All rights reserved.
+ * Modifications Copyright (C) 2018-2020 AT&T Corp. All rights reserved.
* Modifications Copyright (C) 2019 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,8 +26,10 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import java.util.Arrays;
import java.util.Objects;
import java.util.UUID;
+import java.util.stream.Collectors;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -36,19 +38,19 @@ import org.onap.policy.controlloop.ControlLoopOperation;
import org.onap.policy.controlloop.VirtualControlLoopEvent;
import org.onap.policy.controlloop.policy.Policy;
import org.onap.policy.sdnc.SdncRequest;
-import org.onap.policy.simulators.Util;
public class SdncActorServiceProviderTest {
- private static final String REROUTE = "Reroute";
+ private static final String REROUTE = RerouteOperator.NAME;
/**
* Set up before test class.
+ *
* @throws Exception if the A&AI simulator cannot be started
*/
@BeforeClass
public static void setUpSimulator() throws Exception {
- Util.buildAaiSim();
+ org.onap.policy.simulators.Util.buildAaiSim();
}
@AfterClass
@@ -57,6 +59,18 @@ public class SdncActorServiceProviderTest {
}
@Test
+ public void testSdncActorServiceProvider() {
+ final SdncActorServiceProvider prov = new SdncActorServiceProvider();
+
+ // verify that it has the operators we expect
+ var expected = Arrays.asList(BandwidthOnDemandOperator.NAME, RerouteOperator.NAME).stream().sorted()
+ .collect(Collectors.toList());
+ var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList());
+
+ assertEquals(expected.toString(), actual.toString());
+ }
+
+ @Test
public void testConstructRequest() {
VirtualControlLoopEvent onset = new VirtualControlLoopEvent();
ControlLoopOperation operation = new ControlLoopOperation();
@@ -84,8 +98,7 @@ public class SdncActorServiceProviderTest {
policy.setRecipe(REROUTE);
assertNotNull(provider.constructRequest(onset, operation, policy));
- SdncRequest request =
- provider.constructRequest(onset, operation, policy);
+ SdncRequest request = provider.constructRequest(onset, operation, policy);
assertEquals(requestId, Objects.requireNonNull(request).getRequestId());
assertEquals("reoptimize", request.getHealRequest().getRequestHeaderInfo().getSvcAction());
diff --git a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncOperatorTest.java b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncOperatorTest.java
new file mode 100644
index 000000000..25d383eb8
--- /dev/null
+++ b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncOperatorTest.java
@@ -0,0 +1,326 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.sdnc;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import lombok.Setter;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams;
+import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams.TopicParamsBuilder;
+import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
+import org.onap.policy.common.endpoints.http.server.HttpServletServer;
+import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance;
+import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
+import org.onap.policy.common.gson.GsonMessageBodyHandler;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.common.utils.network.NetworkUtil;
+import org.onap.policy.controlloop.VirtualControlLoopEvent;
+import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
+import org.onap.policy.controlloop.actorserviceprovider.Util;
+import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams;
+import org.onap.policy.controlloop.policy.PolicyResult;
+import org.onap.policy.sdnc.SdncHealRequest;
+import org.onap.policy.sdnc.SdncRequest;
+import org.onap.policy.sdnc.SdncResponse;
+import org.onap.policy.sdnc.SdncResponseOutput;
+
+public class SdncOperatorTest {
+ public static final String MEDIA_TYPE_APPLICATION_JSON = "application/json";
+ private static final String EXPECTED_EXCEPTION = "expected exception";
+ public static final String HTTP_CLIENT = "my-http-client";
+ public static final String HTTP_NO_SERVER = "my-http-no-server-client";
+ private static final String ACTOR = "my-actor";
+ private static final String OPERATION = "my-operation";
+
+ /**
+ * Outcome to be added to the response.
+ */
+ @Setter
+ private static SdncResponseOutput output;
+
+
+ private VirtualControlLoopEvent event;
+ private ControlLoopEventContext context;
+ private MyOper oper;
+
+ /**
+ * Starts the SDNC simulator.
+ */
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ // allocate a port
+ int port = NetworkUtil.allocPort();
+
+ /*
+ * Start the simulator. Must use "Properties" to configure it, otherwise the
+ * server will use the wrong serialization provider.
+ */
+ Properties svrprops = getServerProperties("my-server", port);
+ HttpServletServerFactoryInstance.getServerFactory().build(svrprops).forEach(HttpServletServer::start);
+
+ /*
+ * Start the clients, one to the server, and one to a non-existent server.
+ */
+ TopicParamsBuilder builder = BusTopicParams.builder().managed(true).hostname("localhost").basePath("sdnc")
+ .serializationProvider(GsonMessageBodyHandler.class.getName());
+
+ HttpClientFactoryInstance.getClientFactory().build(builder.clientName(HTTP_CLIENT).port(port).build());
+
+ HttpClientFactoryInstance.getClientFactory()
+ .build(builder.clientName(HTTP_NO_SERVER).port(NetworkUtil.allocPort()).build());
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() {
+ HttpClientFactoryInstance.getClientFactory().destroy();
+ HttpServletServerFactoryInstance.getServerFactory().destroy();
+ }
+
+ /**
+ * Initializes {@link #oper} and sets {@link #output} to a success code.
+ */
+ @Before
+ public void setUp() {
+ event = new VirtualControlLoopEvent();
+ context = new ControlLoopEventContext(event);
+
+ initOper(HTTP_CLIENT);
+
+ output = new SdncResponseOutput();
+ output.setResponseCode("200");
+ }
+
+ @After
+ public void tearDown() {
+ oper.shutdown();
+ }
+
+ @Test
+ public void testSdncOperator() {
+ assertEquals(ACTOR, oper.getActorName());
+ assertEquals(OPERATION, oper.getName());
+ assertEquals(ACTOR + "." + OPERATION, oper.getFullName());
+ }
+
+ @Test
+ public void testGetClient() {
+ assertNotNull(oper.getTheClient());
+ }
+
+ @Test
+ public void testStartOperationAsync_testPostRequest() throws Exception {
+ OperationOutcome outcome = runOperation();
+ assertNotNull(outcome);
+ assertEquals(PolicyResult.SUCCESS, outcome.getResult());
+ }
+
+ /**
+ * Tests postRequest() when decode() throws an exception.
+ */
+ @Test
+ public void testPostRequestDecodeException() throws Exception {
+
+ oper.setDecodeFailure(true);
+
+ OperationOutcome outcome = runOperation();
+ assertNotNull(outcome);
+ assertEquals(PolicyResult.FAILURE_EXCEPTION, outcome.getResult());
+ }
+
+ /**
+ * Tests postRequest() when there is no "output" field in the response.
+ */
+ @Test
+ public void testPostRequestNoOutput() throws Exception {
+
+ setOutput(null);
+
+ OperationOutcome outcome = runOperation();
+ assertNotNull(outcome);
+ assertEquals(PolicyResult.FAILURE, outcome.getResult());
+ }
+
+ /**
+ * Tests postRequest() when the output is not a success.
+ */
+ @Test
+ public void testPostRequestOutputFailure() throws Exception {
+
+ output.setResponseCode(null);
+
+ OperationOutcome outcome = runOperation();
+ assertNotNull(outcome);
+ assertEquals(PolicyResult.FAILURE, outcome.getResult());
+ }
+
+ /**
+ * Tests postRequest() when the post() request throws an exception retrieving the
+ * response.
+ */
+ @Test
+ public void testPostRequestException() throws Exception {
+
+ // reset "oper" to point to a non-existent server
+ oper.shutdown();
+ initOper(HTTP_NO_SERVER);
+
+ OperationOutcome outcome = runOperation();
+ assertNotNull(outcome);
+ assertEquals(PolicyResult.FAILURE_EXCEPTION, outcome.getResult());
+ }
+
+ private static Properties getServerProperties(String name, int port) {
+ final Properties props = new Properties();
+ props.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES, name);
+
+ final String svcpfx = PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + name;
+
+ props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX, Server.class.getName());
+ props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX, "localhost");
+ props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, String.valueOf(port));
+ props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, "true");
+ props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX, "false");
+
+ props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SERIALIZATION_PROVIDER,
+ GsonMessageBodyHandler.class.getName());
+ return props;
+ }
+
+ /**
+ * Initializes {@link #oper}.
+ *
+ * @param clientName name of the client which it should use
+ */
+ private void initOper(String clientName) {
+ oper = new MyOper();
+
+ HttpParams params = HttpParams.builder().clientName(clientName).path("request").build();
+ Map<String, Object> mapParams = Util.translateToMap(OPERATION, params);
+ oper.configure(mapParams);
+ oper.start();
+ }
+
+ /**
+ * Runs the operation.
+ *
+ * @return the outcome of the operation, or {@code null} if it does not complete in
+ * time
+ */
+ private OperationOutcome runOperation() throws InterruptedException, ExecutionException, TimeoutException {
+ ControlLoopOperationParams params =
+ ControlLoopOperationParams.builder().actor(ACTOR).operation(OPERATION).context(context).build();
+
+ CompletableFuture<OperationOutcome> future = oper.startOperationAsync(params, 1, params.makeOutcome());
+
+ return future.get(5, TimeUnit.SECONDS);
+ }
+
+
+ private class MyOper extends SdncOperator {
+
+ /**
+ * Set to {@code true} to cause the decoder to throw an exception.
+ */
+ @Setter
+ private boolean decodeFailure = false;
+
+ public MyOper() {
+ super(ACTOR, OPERATION);
+ }
+
+ protected HttpClient getTheClient() {
+ return getClient();
+ }
+
+ @Override
+ protected SdncRequest constructRequest(ControlLoopEventContext context) {
+ SdncRequest request = new SdncRequest();
+
+ SdncHealRequest heal = new SdncHealRequest();
+ request.setHealRequest(heal);
+
+ return request;
+ }
+
+ @Override
+ protected StandardCoder makeDecoder() {
+ if (decodeFailure) {
+ // return a coder that throws exceptions when decode() is invoked
+ return new StandardCoder() {
+ @Override
+ public <T> T decode(String json, Class<T> clazz) throws CoderException {
+ throw new CoderException(EXPECTED_EXCEPTION);
+ }
+ };
+
+ } else {
+ return super.makeDecoder();
+ }
+ }
+ }
+
+ /**
+ * SDNC Simulator.
+ */
+ @Path("/sdnc")
+ @Produces(MEDIA_TYPE_APPLICATION_JSON)
+ public static class Server {
+
+ /**
+ * Generates a response.
+ *
+ * @param request incoming request
+ * @return resulting response
+ */
+ @POST
+ @Path("/request")
+ @Consumes(value = {MEDIA_TYPE_APPLICATION_JSON})
+ public Response postRequest(SdncRequest request) {
+
+ SdncResponse response = new SdncResponse();
+ response.setResponseOutput(output);
+
+ return Response.status(Status.OK).entity(response).build();
+ }
+ }
+}
diff --git a/models-interactions/model-actors/actor.sdnc/src/test/resources/bod.json b/models-interactions/model-actors/actor.sdnc/src/test/resources/bod.json
new file mode 100644
index 000000000..8c60bbdd8
--- /dev/null
+++ b/models-interactions/model-actors/actor.sdnc/src/test/resources/bod.json
@@ -0,0 +1,32 @@
+{
+ "input": {
+ "sdnc-request-header": {
+ "svc-request-id": "076b243e-9236-4409-973d-dd318dcab3e9",
+ "svc-action": "update"
+ },
+ "request-information": {
+ "request-action": "SdwanBandwidthChange"
+ },
+ "service-information": {
+ "service-instance-id": "my-service"
+ },
+ "vnf-information": {
+ "vnf-id": "my-vnf"
+ },
+ "vf-module-information": {
+ "vf-module-id": ""
+ },
+ "vf-module-request-input": {
+ "vf-module-input-parameters": {
+ "param": [
+ {
+ "name": "bandwidth"
+ },
+ {
+ "name": "bandwidth-change-time"
+ }
+ ]
+ }
+ }
+ }
+}
diff --git a/models-interactions/model-actors/actor.sdnc/src/test/resources/reroute.json b/models-interactions/model-actors/actor.sdnc/src/test/resources/reroute.json
new file mode 100644
index 000000000..da70a55a3
--- /dev/null
+++ b/models-interactions/model-actors/actor.sdnc/src/test/resources/reroute.json
@@ -0,0 +1,17 @@
+{
+ "input": {
+ "sdnc-request-header": {
+ "svc-request-id": "66087b39-8606-4367-9ac8-bdf64e162f29",
+ "svc-action": "reoptimize"
+ },
+ "request-information": {
+ "request-action": "ReoptimizeSOTNInstance"
+ },
+ "service-information": {
+ "service-instance-id": "my-service"
+ },
+ "network-information": {
+ "network-id": "my-network"
+ }
+ }
+}