diff options
Diffstat (limited to 'models-interactions/model-actors/actor.sdnc')
12 files changed, 399 insertions, 608 deletions
diff --git a/models-interactions/model-actors/actor.sdnc/pom.xml b/models-interactions/model-actors/actor.sdnc/pom.xml index 04040dbbf..4bb03ecec 100644 --- a/models-interactions/model-actors/actor.sdnc/pom.xml +++ b/models-interactions/model-actors/actor.sdnc/pom.xml @@ -19,58 +19,71 @@ ============LICENSE_END========================================================= --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + 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.2.1-SNAPSHOT</version> - </parent> + <parent> + <groupId>org.onap.policy.models.policy-models-interactions.model-actors</groupId> + <artifactId>model-actors</artifactId> + <version>2.2.1-SNAPSHOT</version> + </parent> - <artifactId>actor.sdnc</artifactId> + <artifactId>actor.sdnc</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>sdnc</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.model-impl</groupId> - <artifactId>aai</artifactId> - <version>${project.version}</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.onap.policy.common</groupId> - <artifactId>policy-endpoints</artifactId> - <version>${policy.common.version}</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.onap.policy.models.policy-models-interactions</groupId> - <artifactId>simulators</artifactId> - <version>${project.version}</version> - <scope>test</scope> - </dependency> - </dependencies> + <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>sdnc</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.model-impl</groupId> + <artifactId>aai</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.common</groupId> + <artifactId>policy-endpoints</artifactId> + <version>${policy.common.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.models.policy-models-interactions.model-actors</groupId> + <artifactId>actor.test</artifactId> + <version>${project.version}</version> + <scope>test</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.powermock</groupId> + <artifactId>powermock-api-mockito2</artifactId> + <scope>test</scope> + </dependency> + </dependencies> </project> 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/BandwidthOnDemandOperation.java index 2927bd85b..26cdfada3 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/BandwidthOnDemandOperation.java @@ -23,6 +23,8 @@ package org.onap.policy.controlloop.actor.sdnc; import java.util.UUID; import org.apache.commons.lang3.StringUtils; 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.sdnc.SdncHealRequest; import org.onap.policy.sdnc.SdncHealRequestHeaderInfo; import org.onap.policy.sdnc.SdncHealRequestInfo; @@ -34,7 +36,7 @@ import org.onap.policy.sdnc.SdncHealVfModuleRequestInput; import org.onap.policy.sdnc.SdncHealVnfInfo; import org.onap.policy.sdnc.SdncRequest; -public class BandwidthOnDemandOperator extends SdncOperator { +public class BandwidthOnDemandOperation extends SdncOperation { public static final String NAME = "BandwidthOnDemand"; public static final String URI = "/GENERIC-RESOURCE-API:vf-module-topology-operation"; @@ -46,14 +48,17 @@ public class BandwidthOnDemandOperator extends SdncOperator { /** * Constructs the object. * - * @param actorName name of the actor with which this operator is associated + * @param params operation parameters + * @param operator operator that created this operation */ - public BandwidthOnDemandOperator(String actorName) { - super(actorName, NAME); + public BandwidthOnDemandOperation(ControlLoopOperationParams params, HttpOperator operator) { + super(params, operator); } @Override - protected SdncRequest constructRequest(ControlLoopEventContext context) { + protected SdncRequest makeRequest(int attempt) { + ControlLoopEventContext context = params.getContext(); + String serviceInstance = context.getEnrichment().get(SERVICE_ID_KEY); if (StringUtils.isBlank(serviceInstance)) { throw new IllegalArgumentException("missing enrichment data, " + SERVICE_ID_KEY); 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/RerouteOperation.java index da400f8eb..f255f3e84 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/RerouteOperation.java @@ -23,6 +23,8 @@ package org.onap.policy.controlloop.actor.sdnc; import java.util.UUID; import org.apache.commons.lang3.StringUtils; 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.sdnc.SdncHealNetworkInfo; import org.onap.policy.sdnc.SdncHealRequest; import org.onap.policy.sdnc.SdncHealRequestHeaderInfo; @@ -30,7 +32,7 @@ import org.onap.policy.sdnc.SdncHealRequestInfo; import org.onap.policy.sdnc.SdncHealServiceInfo; import org.onap.policy.sdnc.SdncRequest; -public class RerouteOperator extends SdncOperator { +public class RerouteOperation extends SdncOperation { public static final String NAME = "Reroute"; public static final String URI = "/GENERIC-RESOURCE-API:network-topology-operation"; @@ -42,14 +44,17 @@ public class RerouteOperator extends SdncOperator { /** * Constructs the object. * - * @param actorName name of the actor with which this operator is associated + * @param params operation parameters + * @param operator operator that created this operation */ - public RerouteOperator(String actorName) { - super(actorName, NAME); + public RerouteOperation(ControlLoopOperationParams params, HttpOperator operator) { + super(params, operator); } @Override - protected SdncRequest constructRequest(ControlLoopEventContext context) { + protected SdncRequest makeRequest(int attempt) { + ControlLoopEventContext context = params.getContext(); + String serviceInstance = context.getEnrichment().get(SERVICE_ID_KEY); if (StringUtils.isBlank(serviceInstance)) { throw new IllegalArgumentException("missing enrichment data, " + SERVICE_ID_KEY); 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 8dc8ba50d..99a4fdadd 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 @@ -30,6 +30,7 @@ import java.util.UUID; import org.onap.policy.controlloop.ControlLoopOperation; import org.onap.policy.controlloop.VirtualControlLoopEvent; import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator; import org.onap.policy.controlloop.policy.Policy; import org.onap.policy.sdnc.SdncHealNetworkInfo; import org.onap.policy.sdnc.SdncHealRequest; @@ -76,8 +77,11 @@ public class SdncActorServiceProvider extends HttpActor { public SdncActorServiceProvider() { super(NAME); - addOperator(new RerouteOperator(NAME)); - addOperator(new BandwidthOnDemandOperator(NAME)); + addOperator(HttpOperator.makeOperator(NAME, RerouteOperation.NAME, + RerouteOperation::new)); + + addOperator(HttpOperator.makeOperator(NAME, BandwidthOnDemandOperation.NAME, + BandwidthOnDemandOperation::new)); } diff --git a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncOperation.java b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncOperation.java new file mode 100644 index 000000000..9d42c49d9 --- /dev/null +++ b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncOperation.java @@ -0,0 +1,85 @@ +/*- + * ============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 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 org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; +import org.onap.policy.sdnc.SdncRequest; +import org.onap.policy.sdnc.SdncResponse; + +/** + * Superclass for SDNC Operators. + */ +public abstract class SdncOperation extends HttpOperation<SdncResponse> { + + /** + * Constructs the object. + * + * @param params operation parameters + * @param operator operator that created this operation + */ + public SdncOperation(ControlLoopOperationParams params, HttpOperator operator) { + super(params, operator, SdncResponse.class); + } + + @Override + protected CompletableFuture<OperationOutcome> startOperationAsync(int attempt, OperationOutcome outcome) { + + SdncRequest request = makeRequest(attempt); + + Entity<SdncRequest> entity = Entity.entity(request, MediaType.APPLICATION_JSON); + + Map<String, Object> headers = makeHeaders(); + + headers.put("Accept", MediaType.APPLICATION_JSON); + String url = makeUrl(); + + logRestRequest(url, request); + + // @formatter:off + return handleResponse(outcome, url, + callback -> operator.getClient().post(callback, makePath(), entity, headers)); + // @formatter:on + } + + /** + * Makes the request. + * + * @param attempt current attempt, starting with "1" + * @return a new request to be posted + */ + protected abstract SdncRequest makeRequest(int attempt); + + /** + * Checks that the response has an "output" and that the output indicates success. + */ + @Override + protected boolean isSuccess(Response rawResponse, SdncResponse response) { + return response.getResponseOutput() != null && "200".equals(response.getResponseOutput().getResponseCode()); + } +} 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 deleted file mode 100644 index 479ee908d..000000000 --- a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncOperator.java +++ /dev/null @@ -1,148 +0,0 @@ -/*- - * ============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 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 org.onap.policy.common.endpoints.http.client.HttpClient; -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.controlloop.ControlLoopEventContext; -import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator; -import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; -import org.onap.policy.controlloop.policy.PolicyResult; -import org.onap.policy.sdnc.SdncRequest; -import org.onap.policy.sdnc.SdncResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Superclass for SDNC Operators. - */ -public abstract class SdncOperator extends HttpOperator { - private static final Logger logger = LoggerFactory.getLogger(SdncOperator.class); - - /** - * Constructs the object. - * - * @param actorName name of the actor with which this operator is associated - * @param name operation name - */ - public SdncOperator(String actorName, String name) { - super(actorName, name); - } - - @Override - protected CompletableFuture<OperationOutcome> startOperationAsync(ControlLoopOperationParams params, int attempt, - OperationOutcome outcome) { - - SdncRequest request = constructRequest(params.getContext()); - return postRequest(params, outcome, request); - } - - /** - * Constructs the request. - * - * @param context associated event context - * @return a new request - */ - protected abstract SdncRequest constructRequest(ControlLoopEventContext context); - - /** - * 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 CompletableFuture<OperationOutcome> postRequest(ControlLoopOperationParams params, OperationOutcome outcome, - SdncRequest sdncRequest) { - Map<String, Object> headers = new HashMap<>(); - - headers.put("Accept", "application/json"); - String sdncUrl = getClient().getBaseUrl(); - - Util.logRestRequest(sdncUrl, sdncRequest); - - Entity<SdncRequest> entity = Entity.entity(sdncRequest, MediaType.APPLICATION_JSON); - - 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; - - public ResponseHandler(ControlLoopOperationParams params, OperationOutcome outcome, String sdncUrl) { - super(params, outcome); - this.sdncUrl = sdncUrl; - } - - /** - * 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); - } - } - - /** - * 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 - - 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 index 02931a4f1..0623df2f5 100644 --- 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 @@ -26,45 +26,51 @@ 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 { +public class BandwidthOnDemandOperatorTest extends BasicSdncOperator { - private BandwidthOnDemandOperator oper; + private BandwidthOnDemandOperation oper; + public BandwidthOnDemandOperatorTest() { + super(DEFAULT_ACTOR, BandwidthOnDemandOperation.NAME); + } /** * Set up. */ @Before - public void setUp() { - makeContext(); - oper = new BandwidthOnDemandOperator(ACTOR); + public void setUp() throws Exception { + super.setUp(); + oper = new BandwidthOnDemandOperation(params, operator); } @Test public void testBandwidthOnDemandOperator() { - assertEquals(ACTOR, oper.getActorName()); - assertEquals(BandwidthOnDemandOperator.NAME, oper.getName()); + assertEquals(DEFAULT_ACTOR, oper.getActorName()); + assertEquals(BandwidthOnDemandOperation.NAME, oper.getName()); } @Test - public void testConstructRequest() throws CoderException { - SdncRequest request = oper.constructRequest(context); + public void testMakeRequest() throws Exception { + SdncRequest request = oper.makeRequest(1); assertEquals("my-service", request.getNsInstanceId()); assertEquals(REQ_ID, request.getRequestId()); - assertEquals(BandwidthOnDemandOperator.URI, request.getUrl()); + assertEquals(BandwidthOnDemandOperation.URI, request.getUrl()); assertNotNull(request.getHealRequest().getRequestHeaderInfo().getSvcRequestId()); verifyRequest("bod.json", request); - verifyMissing(oper, BandwidthOnDemandOperator.SERVICE_ID_KEY, "service"); + verifyMissing(BandwidthOnDemandOperation.SERVICE_ID_KEY, "service", BandwidthOnDemandOperation::new); + + // perform the operation + makeContext(); + verifyRequest("bod.json", verifyOperation(oper)); } @Override protected Map<String, String> makeEnrichment() { - return Map.of(BandwidthOnDemandOperator.SERVICE_ID_KEY, "my-service", BandwidthOnDemandOperator.VNF_ID, + return Map.of(BandwidthOnDemandOperation.SERVICE_ID_KEY, "my-service", BandwidthOnDemandOperation.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 deleted file mode 100644 index b9028d462..000000000 --- a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BasicOperator.java +++ /dev/null @@ -1,94 +0,0 @@ -/*- - * ============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/BasicSdncOperator.java b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BasicSdncOperator.java new file mode 100644 index 000000000..d8c707cc3 --- /dev/null +++ b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BasicSdncOperator.java @@ -0,0 +1,148 @@ +/*- + * ============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 static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.BiFunction; +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.actor.test.BasicHttpOperation; +import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; +import org.onap.policy.controlloop.policy.PolicyResult; +import org.onap.policy.sdnc.SdncRequest; +import org.onap.policy.sdnc.SdncResponse; +import org.onap.policy.sdnc.SdncResponseOutput; +import org.powermock.reflect.Whitebox; + +/** + * Superclass for various operator tests. + */ +public abstract class BasicSdncOperator extends BasicHttpOperation<SdncRequest> { + + protected SdncResponse response; + + /** + * Constructs the object using a default actor and operation name. + */ + public BasicSdncOperator() { + super(); + } + + /** + * Constructs the object. + * + * @param actor actor name + * @param operation operation name + */ + public BasicSdncOperator(String actor, String operation) { + super(actor, operation); + } + + /** + * Initializes mocks and sets up. + */ + public void setUp() throws Exception { + super.setUp(); + + response = new SdncResponse(); + + SdncResponseOutput output = new SdncResponseOutput(); + response.setResponseOutput(output); + output.setResponseCode("200"); + + when(rawResponse.readEntity(String.class)).thenReturn(new StandardCoder().encode(response)); + } + + /** + * Runs the operation and verifies that the response is successful. + * + * @param operation operation to run + * @return the request that was posted + */ + protected SdncRequest verifyOperation(SdncOperation operation) + throws InterruptedException, ExecutionException, TimeoutException { + + CompletableFuture<OperationOutcome> future2 = operation.startOperationAsync(1, outcome); + assertFalse(future2.isDone()); + + verify(client).post(callbackCaptor.capture(), any(), requestCaptor.capture(), any()); + callbackCaptor.getValue().completed(rawResponse); + + assertEquals(PolicyResult.SUCCESS, future2.get(5, TimeUnit.SECONDS).getResult()); + + return requestCaptor.getValue().getEntity(); + } + + /** + * 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 fieldName name of the field to be removed from the enrichment data + * @param expectedText text expected in the exception message + */ + protected void verifyMissing(String fieldName, String expectedText, + BiFunction<ControlLoopOperationParams,HttpOperator,SdncOperation> maker) { + + makeContext(); + enrichment.remove(fieldName); + + SdncOperation oper = maker.apply(params, operator); + + assertThatIllegalArgumentException().isThrownBy(() -> Whitebox.invokeMethod(oper, "makeRequest", 1)) + .withMessageContaining("missing").withMessageContaining(expectedText); + } + + 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 index 0a7bcad6f..7fc5ee7c2 100644 --- 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 @@ -26,45 +26,51 @@ 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 { +public class RerouteOperatorTest extends BasicSdncOperator { - private RerouteOperator oper; + private RerouteOperation oper; + public RerouteOperatorTest() { + super(DEFAULT_ACTOR, RerouteOperation.NAME); + } /** * Set up. */ @Before - public void setUp() { - makeContext(); - oper = new RerouteOperator(ACTOR); + public void setUp() throws Exception { + super.setUp(); + oper = new RerouteOperation(params, operator); } @Test public void testRerouteOperator() { - assertEquals(ACTOR, oper.getActorName()); - assertEquals(RerouteOperator.NAME, oper.getName()); + assertEquals(DEFAULT_ACTOR, oper.getActorName()); + assertEquals(RerouteOperation.NAME, oper.getName()); } @Test - public void testConstructRequest() throws CoderException { - SdncRequest request = oper.constructRequest(context); + public void testMakeRequest() throws Exception { + SdncRequest request = oper.makeRequest(1); assertEquals("my-service", request.getNsInstanceId()); assertEquals(REQ_ID, request.getRequestId()); - assertEquals(RerouteOperator.URI, request.getUrl()); + assertEquals(RerouteOperation.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"); + verifyMissing(RerouteOperation.SERVICE_ID_KEY, "service", RerouteOperation::new); + verifyMissing(RerouteOperation.NETWORK_ID_KEY, "network", RerouteOperation::new); + + // perform the operation + makeContext(); + verifyRequest("reroute.json", verifyOperation(oper)); } @Override protected Map<String, String> makeEnrichment() { - return Map.of(RerouteOperator.SERVICE_ID_KEY, "my-service", RerouteOperator.NETWORK_ID_KEY, "my-network"); + return Map.of(RerouteOperation.SERVICE_ID_KEY, "my-service", RerouteOperation.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 08655c349..ac81d49c9 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 @@ -41,7 +41,7 @@ import org.onap.policy.sdnc.SdncRequest; public class SdncActorServiceProviderTest { - private static final String REROUTE = RerouteOperator.NAME; + private static final String REROUTE = RerouteOperation.NAME; /** * Set up before test class. @@ -63,7 +63,7 @@ public class SdncActorServiceProviderTest { final SdncActorServiceProvider prov = new SdncActorServiceProvider(); // verify that it has the operators we expect - var expected = Arrays.asList(BandwidthOnDemandOperator.NAME, RerouteOperator.NAME).stream().sorted() + var expected = Arrays.asList(BandwidthOnDemandOperation.NAME, RerouteOperation.NAME).stream().sorted() .collect(Collectors.toList()); var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); 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 index 25d383eb8..4bc514c08 100644 --- 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 @@ -21,306 +21,67 @@ package org.onap.policy.controlloop.actor.sdnc; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; 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 java.util.TreeMap; 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; +public class SdncOperatorTest extends BasicSdncOperator { - - private VirtualControlLoopEvent event; - private ControlLoopEventContext context; - private MyOper oper; + private SdncRequest request; + private SdncOperation 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. + * Sets up. */ @Before - public void setUp() { - event = new VirtualControlLoopEvent(); - context = new ControlLoopEventContext(event); - - initOper(HTTP_CLIENT); + public void setUp() throws Exception { + super.setUp(); - output = new SdncResponseOutput(); - output.setResponseCode("200"); - } - - @After - public void tearDown() { - oper.shutdown(); + oper = new SdncOperation(params, operator) { + @Override + protected SdncRequest makeRequest(int attempt) { + return request; + } + }; } @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()); + assertEquals(DEFAULT_ACTOR, oper.getActorName()); + assertEquals(DEFAULT_OPERATION, oper.getName()); } - /** - * 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()); + public void testStartOperationAsync_testStartRequestAsync() throws Exception { + verifyOperation(oper); } - /** - * 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(); - } + public void testIsSuccess() { + // success case + response.getResponseOutput().setResponseCode("200"); + assertTrue(oper.isSuccess(null, response)); - /** - * 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(); + // failure code + response.getResponseOutput().setResponseCode("555"); + assertFalse(oper.isSuccess(null, response)); - CompletableFuture<OperationOutcome> future = oper.startOperationAsync(params, 1, params.makeOutcome()); + // null code + response.getResponseOutput().setResponseCode(null); + assertFalse(oper.isSuccess(null, response)); - return future.get(5, TimeUnit.SECONDS); + // null output + response.setResponseOutput(null); + assertFalse(oper.isSuccess(null, response)); } - - 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(); - } + @Override + protected Map<String, String> makeEnrichment() { + return new TreeMap<>(); } } |