From: Pamela Dragosh Date: Fri, 7 Aug 2020 22:02:24 +0000 (+0000) Subject: Merge "Modify Actors to use properties when provided" X-Git-Tag: 2.3.1~22 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=00e48acdc51fa2a64b0f7fdc221c28308d7f214d;hp=5cbc856cdef0f1775ae4acdfa08345325c737234;p=policy%2Fmodels.git Merge "Modify Actors to use properties when provided" --- diff --git a/models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiCustomQueryOperation.java b/models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiCustomQueryOperation.java index 151f7a214..c8e087036 100644 --- a/models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiCustomQueryOperation.java +++ b/models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiCustomQueryOperation.java @@ -29,7 +29,6 @@ import javax.ws.rs.client.Invocation.Builder; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import lombok.Getter; import org.apache.commons.lang3.StringUtils; import org.onap.policy.aai.AaiConstants; import org.onap.policy.aai.AaiCqResponse; @@ -64,9 +63,6 @@ public class AaiCustomQueryOperation extends HttpOperation { // TODO make this configurable private static final String PREFIX = "/aai/v16"; - @Getter - private final String vserver; - /** * Constructs the object. * @@ -75,11 +71,20 @@ public class AaiCustomQueryOperation extends HttpOperation { */ public AaiCustomQueryOperation(ControlLoopOperationParams params, HttpConfig config) { super(params, config, String.class, PROPERTY_NAMES); + } - this.vserver = params.getContext().getEnrichment().get(VSERVER_VSERVER_NAME); - if (StringUtils.isBlank(this.vserver)) { + /** + * Gets the vserver name from the enrichment data. + * + * @return the vserver name + */ + protected String getVserver() { + String vserver = this.params.getContext().getEnrichment().get(VSERVER_VSERVER_NAME); + if (StringUtils.isBlank(vserver)) { throw new IllegalArgumentException("missing " + VSERVER_VSERVER_NAME + " in enrichment data"); } + + return vserver; } /** @@ -91,6 +96,7 @@ public class AaiCustomQueryOperation extends HttpOperation { return null; } + String vserver = getVserver(); ControlLoopOperationParams tenantParams = params.toBuilder().actor(AaiConstants.ACTOR_NAME).operation(AaiGetTenantOperation.NAME) .targetEntity(vserver).payload(null).retry(null).timeoutSec(null).build(); @@ -146,16 +152,33 @@ public class AaiCustomQueryOperation extends HttpOperation { * Constructs the custom query using the previously retrieved tenant data. */ private Map makeRequest() { + return Map.of("start", getVserverLink(), "query", "query/closed-loop"); + } + + /** + * Gets the vserver link, first checking the properties, and then the tenant data. + * + * @return the vserver link + */ + protected String getVserverLink() { + String resourceLink = getProperty(OperationProperties.AAI_VSERVER_LINK); + if (resourceLink != null) { + return resourceLink; + } + + String vserver = getVserver(); StandardCoderObject tenant = params.getContext().getProperty(AaiGetTenantOperation.getKey(vserver)); + if (tenant == null) { + throw new IllegalStateException("cannot perform custom query - cannot determine resource-link"); + } - String resourceLink = tenant.getString(RESULT_DATA, 0, RESOURCE_LINK); + resourceLink = tenant.getString(RESULT_DATA, 0, RESOURCE_LINK); if (resourceLink == null) { throw new IllegalArgumentException("cannot perform custom query - no resource-link"); } resourceLink = resourceLink.replace(PREFIX, ""); - - return Map.of("start", resourceLink, "query", "query/closed-loop"); + return resourceLink; } @Override diff --git a/models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiCustomQueryOperationTest.java b/models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiCustomQueryOperationTest.java index 476e6432d..f1225373e 100644 --- a/models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiCustomQueryOperationTest.java +++ b/models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiCustomQueryOperationTest.java @@ -23,6 +23,7 @@ package org.onap.policy.controlloop.actor.aai; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; @@ -113,11 +114,12 @@ public class AaiCustomQueryOperationTest extends BasicAaiOperation { HttpParams opParams = HttpParams.builder().clientName(MY_CLIENT).path("v16/query").build(); config = new HttpConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory()); - preloadTenantData(); - - params = params.toBuilder().targetEntity(SIM_VSERVER).retry(0).timeoutSec(5).executor(blockingExecutor).build(); + params = params.toBuilder().targetEntity(SIM_VSERVER).retry(0).timeoutSec(5).executor(blockingExecutor) + .preprocessed(true).build(); oper = new AaiCustomQueryOperation(params, config); + oper.setProperty(OperationProperties.AAI_VSERVER_LINK, MY_LINK); + outcome = oper.start().get(); assertEquals(PolicyResult.SUCCESS, outcome.getResult()); @@ -129,15 +131,19 @@ public class AaiCustomQueryOperationTest extends BasicAaiOperation { public void testConstructor() { assertEquals(AaiConstants.ACTOR_NAME, oper.getActorName()); assertEquals(AaiCustomQueryOperation.NAME, oper.getName()); - assertEquals(MY_VSERVER, oper.getVserver()); // verify that it works with an empty target entity params = params.toBuilder().targetEntity("").build(); assertThatCode(() -> new AaiCustomQueryOperation(params, config)).doesNotThrowAnyException(); + } + + @Test + public void testGetVserver() { + assertEquals(MY_VSERVER, oper.getVserver()); // try without enrichment data params.getContext().getEnrichment().remove(AaiCustomQueryOperation.VSERVER_VSERVER_NAME); - assertThatIllegalArgumentException().isThrownBy(() -> new AaiCustomQueryOperation(params, config)) + assertThatIllegalArgumentException().isThrownBy(() -> oper.getVserver()) .withMessage("missing " + AaiCustomQueryOperation.VSERVER_VSERVER_NAME + " in enrichment data"); } @@ -215,7 +221,7 @@ public class AaiCustomQueryOperationTest extends BasicAaiOperation { @Test @SuppressWarnings("unchecked") - public void testMakeRequest() throws Exception { + public void testMakeRequest_testGetVserverLink() throws Exception { // preload preloadTenantData(); @@ -237,17 +243,24 @@ public class AaiCustomQueryOperationTest extends BasicAaiOperation { } @Test - @SuppressWarnings("unchecked") - public void testMakeRequestNoResourceLink() throws Exception { - // pre-load EMPTY tenant data - preloadTenantData(new StandardCoderObject()); + public void testGetVserverLinkViaProperty() throws Exception { + oper.setProperty(OperationProperties.AAI_VSERVER_LINK, MY_LINK); + assertEquals(MY_LINK, oper.getVserverLink()); + } - when(rawResponse.readEntity(String.class)).thenReturn(makeCqReply()); - when(webAsync.put(any(), any(InvocationCallback.class))).thenAnswer(provideResponse(rawResponse, 1)); + @Test + public void testGetVserverLinkNoTenantData() throws Exception { + assertThatIllegalStateException().isThrownBy(() -> oper.getVserverLink()) + .withMessage("cannot perform custom query - cannot determine resource-link"); + } - CompletableFuture future2 = oper.start(); + @Test + public void testGetVserverLinkNoResourceLink() throws Exception { + // pre-load EMPTY tenant data + preloadTenantData(new StandardCoderObject()); - assertEquals(PolicyResult.FAILURE_EXCEPTION, getResult(future2)); + assertThatIllegalArgumentException().isThrownBy(() -> oper.getVserverLink()) + .withMessage("cannot perform custom query - no resource-link"); } private String makeTenantReply() throws Exception { diff --git a/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/ModifyConfigOperation.java b/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/ModifyConfigOperation.java index 680bd9cc7..13ddaf4a9 100644 --- a/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/ModifyConfigOperation.java +++ b/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/ModifyConfigOperation.java @@ -69,7 +69,19 @@ public class ModifyConfigOperation extends AppcOperation { @Override protected Request makeRequest(int attempt) { + return makeRequest(attempt, getVnfId()); + } + + protected String getVnfId() { + GenericVnf vnf = this.getProperty(OperationProperties.AAI_RESOURCE_VNF); + if (vnf != null) { + return vnf.getVnfId(); + } + AaiCqResponse cq = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY); + if (cq == null) { + throw new IllegalStateException("target vnf-id could not be determined"); + } GenericVnf genvnf = cq.getGenericVnfByModelInvariantId(params.getTarget().getResourceID()); if (genvnf == null) { @@ -77,6 +89,6 @@ public class ModifyConfigOperation extends AppcOperation { throw new IllegalArgumentException("target vnf-id could not be found"); } - return makeRequest(attempt, genvnf.getVnfId()); + return genvnf.getVnfId(); } } diff --git a/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/ModifyConfigOperationTest.java b/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/ModifyConfigOperationTest.java index 9c602f52e..3b63514e9 100644 --- a/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/ModifyConfigOperationTest.java +++ b/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/ModifyConfigOperationTest.java @@ -22,6 +22,7 @@ package org.onap.policy.controlloop.actor.appc; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -42,6 +43,7 @@ import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.Mock; import org.onap.aai.domain.yang.GenericVnf; import org.onap.policy.aai.AaiCqResponse; import org.onap.policy.appc.Request; @@ -56,8 +58,14 @@ import org.onap.policy.controlloop.policy.PolicyResult; public class ModifyConfigOperationTest extends BasicAppcOperation { + @Mock + private GenericVnf genvnf; + @Mock + private AaiCqResponse cq; + private ModifyConfigOperation oper; + public ModifyConfigOperationTest() { super(DEFAULT_ACTOR, ModifyConfigOperation.NAME); } @@ -77,6 +85,9 @@ public class ModifyConfigOperationTest extends BasicAppcOperation { @Override public void setUp() throws Exception { super.setUp(); + when(genvnf.getVnfId()).thenReturn(MY_VNF); + when(cq.getGenericVnfByModelInvariantId(any())).thenReturn(genvnf); + oper = new ModifyConfigOperation(params, config); } @@ -95,14 +106,9 @@ public class ModifyConfigOperationTest extends BasicAppcOperation { BidirectionalTopicParams.builder().sinkTopic(MY_SINK).sourceTopic(MY_SINK).build(); config = new BidirectionalTopicConfig(blockingExecutor, opParams, topicMgr, AppcOperation.SELECTOR_KEYS); - AaiCqResponse cq = mock(AaiCqResponse.class); - GenericVnf genvnf = mock(GenericVnf.class); - when(genvnf.getVnfId()).thenReturn(MY_VNF); - when(cq.getGenericVnfByModelInvariantId(any())).thenReturn(genvnf); - params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq); - params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).build(); + params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).preprocessed(true).build(); oper = new ModifyConfigOperation(params, config) { @Override @@ -111,6 +117,8 @@ public class ModifyConfigOperationTest extends BasicAppcOperation { } }; + oper.setProperty(OperationProperties.AAI_RESOURCE_VNF, genvnf); + outcome = oper.start().get(); assertEquals(PolicyResult.SUCCESS, outcome.getResult()); assertTrue(outcome.getResponse() instanceof Response); @@ -168,23 +176,41 @@ public class ModifyConfigOperationTest extends BasicAppcOperation { @Test public void testMakeRequest() throws CoderException { - AaiCqResponse cq = new AaiCqResponse("{}"); + oper.setProperty(OperationProperties.AAI_RESOURCE_VNF, genvnf); + + oper.generateSubRequestId(2); + Request request = oper.makeRequest(2); + assertNotNull(request); + assertEquals(MY_VNF, request.getPayload().get(ModifyConfigOperation.VNF_ID_KEY)); + + verifyRequest("modifyConfig.json", request, IGNORE_FIELDS); + } + + @Test + public void testGetVnfIdViaProperty() throws CoderException { + oper.setProperty(OperationProperties.AAI_RESOURCE_VNF, genvnf); + assertEquals(MY_VNF, oper.getVnfId()); + } + + @Test + public void testGetVnfId() throws CoderException { + // no CQ data + assertThatIllegalStateException().isThrownBy(() -> oper.getVnfId()) + .withMessage("target vnf-id could not be determined"); + + cq = new AaiCqResponse("{}"); // missing vnf-id params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq); - assertThatIllegalArgumentException().isThrownBy(() -> oper.makeRequest(1)); + assertThatIllegalArgumentException().isThrownBy(() -> oper.getVnfId()) + .withMessage("target vnf-id could not be found"); // populate the CQ data with a vnf-id - GenericVnf genvnf = new GenericVnf(); + genvnf = new GenericVnf(); genvnf.setVnfId(MY_VNF); genvnf.setModelInvariantId(RESOURCE_ID); cq.setInventoryResponseItems(Arrays.asList(genvnf)); - oper.generateSubRequestId(2); - Request request = oper.makeRequest(2); - assertNotNull(request); - assertEquals(MY_VNF, request.getPayload().get(ModifyConfigOperation.VNF_ID_KEY)); - - verifyRequest("modifyConfig.json", request, IGNORE_FIELDS); + assertEquals(MY_VNF, oper.getVnfId()); } } diff --git a/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/GrpcOperation.java b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/GrpcOperation.java index ec8f2ac12..d3842441d 100644 --- a/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/GrpcOperation.java +++ b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/GrpcOperation.java @@ -44,7 +44,6 @@ import org.onap.policy.aai.AaiConstants; import org.onap.policy.aai.AaiCqResponse; import org.onap.policy.cds.client.CdsProcessorGrpcClient; import org.onap.policy.common.utils.coder.CoderException; -import org.onap.policy.common.utils.coder.StandardCoderObject; import org.onap.policy.controlloop.actor.aai.AaiCustomQueryOperation; import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation; import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants; @@ -91,13 +90,15 @@ public class GrpcOperation extends OperationPartial { // @formatter:off private static final List PNF_PROPERTY_NAMES = List.of( OperationProperties.AAI_PNF, - OperationProperties.EVENT_ADDITIONAL_PARAMS); + OperationProperties.EVENT_ADDITIONAL_PARAMS, + OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES); private static final List VNF_PROPERTY_NAMES = List.of( - OperationProperties.AAI_MODEL_INVARIANT_GENERIC_VNF, - OperationProperties.AAI_RESOURCE_SERVICE_INSTANCE, - OperationProperties.EVENT_ADDITIONAL_PARAMS); + OperationProperties.AAI_RESOURCE_VNF, + OperationProperties.AAI_SERVICE, + OperationProperties.EVENT_ADDITIONAL_PARAMS, + OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES); // @formatter:on /** @@ -177,11 +178,15 @@ public class GrpcOperation extends OperationPartial { * @return a map of the PNF data */ private Map convertPnfToAaiProperties() { + Map result = this.getProperty(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES); + if (result != null) { + return result; + } + // convert PNF data to a Map - StandardCoderObject pnf = params.getContext().getProperty(AaiGetPnfOperation.getKey(params.getTargetEntity())); - Map source = Util.translateToMap(getFullName(), pnf); + Map source = Util.translateToMap(getFullName(), getPnfData()); - Map result = new LinkedHashMap<>(); + result = new LinkedHashMap<>(); for (Entry ent : source.entrySet()) { result.put(AAI_PNF_PREFIX + ent.getKey(), ent.getValue().toString()); @@ -190,6 +195,26 @@ public class GrpcOperation extends OperationPartial { return result; } + /** + * Gets the PNF from the operation properties, if it exists, or from the context + * properties otherwise. + * + * @return the PNF item + */ + protected Object getPnfData() { + Object pnf = getProperty(OperationProperties.AAI_PNF); + if (pnf != null) { + return pnf; + } + + pnf = params.getContext().getProperty(AaiGetPnfOperation.getKey(params.getTargetEntity())); + if (pnf == null) { + throw new IllegalArgumentException("missing PNF data"); + } + + return pnf; + } + /** * Converts the A&AI Custom Query data to a map suitable for passing via the * "aaiProperties" field in the CDS request. @@ -197,24 +222,49 @@ public class GrpcOperation extends OperationPartial { * @return a map of the custom query data */ private Map convertCqToAaiProperties() { - AaiCqResponse aaicq = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY); + Map result = this.getProperty(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES); + if (result != null) { + return result; + } - Map result = new LinkedHashMap<>(); + result = new LinkedHashMap<>(); + + result.put(AAI_SERVICE_INSTANCE_ID_KEY, getServiceInstanceId()); + result.put(AAI_VNF_ID_KEY, getVnfId()); + + return result; + } - ServiceInstance serviceInstance = aaicq.getServiceInstance(); + protected String getServiceInstanceId() { + ServiceInstance serviceInstance = getProperty(OperationProperties.AAI_SERVICE); + if (serviceInstance != null) { + return serviceInstance.getServiceInstanceId(); + } + + AaiCqResponse aaicq = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY); + + serviceInstance = aaicq.getServiceInstance(); if (serviceInstance == null) { throw new IllegalArgumentException("Target service instance could not be found"); } - GenericVnf genericVnf = aaicq.getGenericVnfByModelInvariantId(params.getTarget().getResourceID()); + return serviceInstance.getServiceInstanceId(); + } + + protected String getVnfId() { + GenericVnf genericVnf = getProperty(OperationProperties.AAI_RESOURCE_VNF); + if (genericVnf != null) { + return genericVnf.getVnfId(); + } + + AaiCqResponse aaicq = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY); + + genericVnf = aaicq.getGenericVnfByModelInvariantId(params.getTarget().getResourceID()); if (genericVnf == null) { throw new IllegalArgumentException("Target generic vnf could not be found"); } - result.put(AAI_SERVICE_INSTANCE_ID_KEY, serviceInstance.getServiceInstanceId()); - result.put(AAI_VNF_ID_KEY, genericVnf.getVnfId()); - - return result; + return genericVnf.getVnfId(); } @Override @@ -232,7 +282,7 @@ public class GrpcOperation extends OperationPartial { * construct the request first so that we don't have to clean up the "client" if * an exception is thrown */ - ExecutionServiceInput request = constructRequest(params); + ExecutionServiceInput request = constructRequest(); CompletableFuture future = new CompletableFuture<>(); @@ -255,10 +305,9 @@ public class GrpcOperation extends OperationPartial { * enriched parameters. TO-DO: Avoid leaking Exceptions to the Kie Session thread. TBD * item for Frankfurt release. * - * @param params the control loop parameters specifying the onset, payload, etc. * @return an ExecutionServiceInput instance. */ - public ExecutionServiceInput constructRequest(ControlLoopOperationParams params) { + public ExecutionServiceInput constructRequest() { // For the current operational TOSCA policy model (yaml) CBA name and version are // embedded in the payload @@ -295,8 +344,9 @@ public class GrpcOperation extends OperationPartial { request.setAaiProperties(aaiConverter.get()); // Inject any additional event parameters that may be present in the onset event - if (params.getContext().getEvent().getAdditionalEventParams() != null) { - request.setAdditionalEventParams(params.getContext().getEvent().getAdditionalEventParams()); + Map additionalParams = getAdditionalEventParams(); + if (additionalParams != null) { + request.setAdditionalEventParams(additionalParams); } Builder struct = Struct.newBuilder(); @@ -324,6 +374,14 @@ public class GrpcOperation extends OperationPartial { .setPayload(struct.build()).build(); } + protected Map getAdditionalEventParams() { + if (containsProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS)) { + return getProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS); + } + + return params.getContext().getEvent().getAdditionalEventParams(); + } + private Map convertPayloadMap(Map payload) { Map convertedPayload = new HashMap<>(); for (Entry entry : payload.entrySet()) { diff --git a/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/GrpcOperationTest.java b/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/GrpcOperationTest.java index 06f239b63..2e9935f82 100644 --- a/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/GrpcOperationTest.java +++ b/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/GrpcOperationTest.java @@ -24,6 +24,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -31,6 +32,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -49,6 +51,7 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.aai.domain.yang.GenericVnf; +import org.onap.aai.domain.yang.Pnf; import org.onap.aai.domain.yang.ServiceInstance; import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput; import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput; @@ -187,6 +190,37 @@ public class GrpcOperationTest { assertTrue(outcome.getResponse() instanceof ExecutionServiceOutput); } + /** + * Tests "success" case with simulator using properties. + */ + @Test + public void testSuccessViaProperties() throws Exception { + ControlLoopEventContext context = new ControlLoopEventContext(onset); + loadCqData(context); + + Map payload = Map.of("artifact_name", "my_artifact", "artifact_version", "1.0"); + + params = ControlLoopOperationParams.builder() + .actor(CdsActorConstants.CDS_ACTOR).operation("subscribe").context(context) + .actorService(new ActorService()).targetEntity(TARGET_ENTITY).target(target).retry(0) + .timeoutSec(5).executor(blockingExecutor).payload(payload).preprocessed(true).build(); + + cdsProps.setHost("localhost"); + cdsProps.setPort(sim.getPort()); + cdsProps.setTimeout(3); + + GrpcConfig config = new GrpcConfig(blockingExecutor, cdsProps); + + operation = new GrpcOperation(params, config); + + // set the properties + operation.setProperty(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES, Collections.emptyMap()); + + OperationOutcome outcome = operation.start().get(); + assertEquals(PolicyResult.SUCCESS, outcome.getResult()); + assertTrue(outcome.getResponse() instanceof ExecutionServiceOutput); + } + @Test public void testGetPropertyNames() { @@ -198,9 +232,10 @@ public class GrpcOperationTest { // @formatter:off assertThat(operation.getPropertyNames()).isEqualTo( List.of( - OperationProperties.AAI_MODEL_INVARIANT_GENERIC_VNF, - OperationProperties.AAI_RESOURCE_SERVICE_INSTANCE, - OperationProperties.EVENT_ADDITIONAL_PARAMS)); + OperationProperties.AAI_RESOURCE_VNF, + OperationProperties.AAI_SERVICE, + OperationProperties.EVENT_ADDITIONAL_PARAMS, + OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES)); // @formatter:on /* @@ -213,10 +248,76 @@ public class GrpcOperationTest { assertThat(operation.getPropertyNames()).isEqualTo( List.of( OperationProperties.AAI_PNF, - OperationProperties.EVENT_ADDITIONAL_PARAMS)); + OperationProperties.EVENT_ADDITIONAL_PARAMS, + OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES)); // @formatter:on } + @Test + public void testGetPnf() { + ControlLoopEventContext context = new ControlLoopEventContext(onset); + params = params.toBuilder().context(context).build(); + operation = new GrpcOperation(params, config); + + // in neither property nor context + assertThatIllegalArgumentException().isThrownBy(() -> operation.getPnfData()) + .withMessage("missing PNF data"); + + // only in context + Pnf pnf = new Pnf(); + params.getContext().setProperty(AaiGetPnfOperation.getKey(params.getTargetEntity()), pnf); + assertSame(pnf, operation.getPnfData()); + + // both - should choose the property + Pnf pnf2 = new Pnf(); + operation.setProperty(OperationProperties.AAI_PNF, pnf2); + assertSame(pnf2, operation.getPnfData()); + } + + @Test + public void testGetServiceInstanceId() { + ControlLoopEventContext context = new ControlLoopEventContext(onset); + params = params.toBuilder().context(context).build(); + operation = new GrpcOperation(params, config); + + // in neither property nor custom query + context.setProperty(AaiCqResponse.CONTEXT_KEY, mock(AaiCqResponse.class)); + assertThatIllegalArgumentException().isThrownBy(() -> operation.getServiceInstanceId()) + .withMessage("Target service instance could not be found"); + + // only in custom query + loadCqData(params.getContext()); + assertEquals(MY_SVC_ID, operation.getServiceInstanceId()); + + // both - should choose the property + ServiceInstance serviceInstance = new ServiceInstance(); + serviceInstance.setServiceInstanceId("another-service-id"); + operation.setProperty(OperationProperties.AAI_SERVICE, serviceInstance); + assertEquals("another-service-id", operation.getServiceInstanceId()); + } + + @Test + public void testGetVnfId() { + ControlLoopEventContext context = new ControlLoopEventContext(onset); + params = params.toBuilder().context(context).build(); + operation = new GrpcOperation(params, config); + + // in neither property nor custom query + context.setProperty(AaiCqResponse.CONTEXT_KEY, mock(AaiCqResponse.class)); + assertThatIllegalArgumentException().isThrownBy(() -> operation.getVnfId()) + .withMessage("Target generic vnf could not be found"); + + // only in custom query + loadCqData(params.getContext()); + assertEquals(MY_VNF, operation.getVnfId()); + + // both - should choose the property + GenericVnf vnf = new GenericVnf(); + vnf.setVnfId("another-vnf-id"); + operation.setProperty(OperationProperties.AAI_RESOURCE_VNF, vnf); + assertEquals("another-vnf-id", operation.getVnfId()); + } + @Test public void testStartPreprocessorAsync() throws InterruptedException, ExecutionException, TimeoutException { AtomicBoolean guardStarted = new AtomicBoolean(); @@ -317,6 +418,29 @@ public class GrpcOperationTest { assertThatIllegalArgumentException().isThrownBy(() -> operation.startOperationAsync(1, params.makeOutcome())); } + @Test + public void testGetAdditionalEventParams() { + operation = new GrpcOperation(params, config); + + // in neither property nor context + assertNull(operation.getAdditionalEventParams()); + + final Map eventParams = Collections.emptyMap(); + + // only in context + onset.setAdditionalEventParams(eventParams); + assertSame(eventParams, operation.getAdditionalEventParams()); + + // both - should choose the property, even if it's null + operation.setProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS, null); + assertNull(operation.getAdditionalEventParams()); + + // both - should choose the property + final Map propParams = Collections.emptyMap(); + operation.setProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS, propParams); + assertSame(propParams, operation.getAdditionalEventParams()); + } + private void verifyOperation(ControlLoopEventContext context) { Map payloadMap = Map.of(CdsActorConstants.KEY_CBA_NAME, CDS_BLUEPRINT_NAME, diff --git a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperation.java b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperation.java index 434b3b985..d2a153641 100644 --- a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperation.java +++ b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperation.java @@ -23,7 +23,6 @@ package org.onap.policy.controlloop.actor.sdnc; import java.util.List; import org.apache.commons.lang3.StringUtils; import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; -import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext; import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig; import org.onap.policy.sdnc.SdncHealRequest; @@ -38,15 +37,18 @@ import org.onap.policy.sdnc.SdncHealVnfInfo; import org.onap.policy.sdnc.SdncRequest; public class BandwidthOnDemandOperation extends SdncOperation { + public static final String NAME = "BandwidthOnDemand"; // fields in the enrichment data public static final String SERVICE_ID_KEY = "service-instance.service-instance-id"; + public static final String BANDWIDTH = "bandwidth"; + public static final String BANDWIDTH_CHANGE_TIME = "bandwidth-change-time"; public static final String VNF_ID = "vnfId"; // @formatter:off private static final List PROPERTY_NAMES = List.of( - OperationProperties.ENRICHMENT_SERVICE_INSTANCE_ID, + OperationProperties.ENRICHMENT_SERVICE_ID, OperationProperties.ENRICHMENT_BANDWIDTH, OperationProperties.ENRICHMENT_BANDWIDTH_CHANGE_TIME, OperationProperties.ENRICHMENT_VNF_ID); @@ -64,20 +66,18 @@ public class BandwidthOnDemandOperation extends SdncOperation { @Override protected SdncRequest makeRequest(int attempt) { - ControlLoopEventContext context = params.getContext(); - - String serviceInstance = context.getEnrichment().get(SERVICE_ID_KEY); + String serviceInstance = getOptProperty(OperationProperties.ENRICHMENT_SERVICE_ID, SERVICE_ID_KEY); if (StringUtils.isBlank(serviceInstance)) { throw new IllegalArgumentException("missing enrichment data, " + SERVICE_ID_KEY); } SdncHealVfModuleParameter bandwidth = new SdncHealVfModuleParameter(); - bandwidth.setName("bandwidth"); - bandwidth.setValue(context.getEnrichment().get("bandwidth")); + bandwidth.setName(BANDWIDTH); + bandwidth.setValue(getOptProperty(OperationProperties.ENRICHMENT_BANDWIDTH, BANDWIDTH)); SdncHealVfModuleParameter timeStamp = new SdncHealVfModuleParameter(); - timeStamp.setName("bandwidth-change-time"); - timeStamp.setValue(context.getEnrichment().get("bandwidth-change-time")); + timeStamp.setName(BANDWIDTH_CHANGE_TIME); + timeStamp.setValue(getOptProperty(OperationProperties.ENRICHMENT_BANDWIDTH_CHANGE_TIME, BANDWIDTH_CHANGE_TIME)); SdncHealVfModuleParametersInfo vfParametersInfo = new SdncHealVfModuleParametersInfo(); vfParametersInfo.addParameters(bandwidth); @@ -102,7 +102,7 @@ public class BandwidthOnDemandOperation extends SdncOperation { request.setUrl("/" + getPath()); SdncHealVnfInfo vnfInfo = new SdncHealVnfInfo(); - vnfInfo.setVnfId(context.getEnrichment().get(VNF_ID)); + vnfInfo.setVnfId(getOptProperty(OperationProperties.ENRICHMENT_VNF_ID, 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/RerouteOperation.java b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperation.java index d26fad8c7..105a27601 100644 --- a/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperation.java +++ b/models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperation.java @@ -23,7 +23,6 @@ package org.onap.policy.controlloop.actor.sdnc; import java.util.List; import org.apache.commons.lang3.StringUtils; import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; -import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext; import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig; import org.onap.policy.sdnc.SdncHealNetworkInfo; @@ -58,16 +57,14 @@ public class RerouteOperation extends SdncOperation { @Override protected SdncRequest makeRequest(int attempt) { - ControlLoopEventContext context = params.getContext(); - - String serviceInstance = context.getEnrichment().get(SERVICE_ID_KEY); + String serviceInstance = getOptProperty(OperationProperties.ENRICHMENT_SERVICE_ID, SERVICE_ID_KEY); if (StringUtils.isBlank(serviceInstance)) { throw new IllegalArgumentException("missing enrichment data, " + SERVICE_ID_KEY); } SdncHealServiceInfo serviceInfo = new SdncHealServiceInfo(); serviceInfo.setServiceInstanceId(serviceInstance); - String networkId = context.getEnrichment().get(NETWORK_ID_KEY); + String networkId = getOptProperty(OperationProperties.ENRICHMENT_NETWORK_ID, NETWORK_ID_KEY); if (StringUtils.isBlank(networkId)) { throw new IllegalArgumentException("missing enrichment data, " + NETWORK_ID_KEY); } 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 index 4d8e35e71..defbcfbc9 100644 --- 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 @@ -96,4 +96,21 @@ public abstract class SdncOperation extends HttpOperation { protected boolean isSuccess(Response rawResponse, SdncResponse response) { return response.getResponseOutput() != null && "200".equals(response.getResponseOutput().getResponseCode()); } + + /** + * Gets an optional property, first checking the properties, then checking the + * enrichment data. + * + * @param propName property name + * @param enrichmentName property name within the enrichment data + * @return the property's value, or {@code null} if it is not found + */ + protected String getOptProperty(String propName, String enrichmentName) { + if (containsProperty(propName)) { + // return the value, even if it's null + return getProperty(propName); + } + + return params.getContext().getEnrichment().get(enrichmentName); + } } diff --git a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperationTest.java b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperationTest.java index 56b64e491..f80299f93 100644 --- a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperationTest.java +++ b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperationTest.java @@ -32,6 +32,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance; import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; +import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext; import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig; import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams; import org.onap.policy.controlloop.policy.PolicyResult; @@ -39,6 +40,10 @@ import org.onap.policy.sdnc.SdncRequest; import org.onap.policy.sdnc.SdncResponse; public class BandwidthOnDemandOperationTest extends BasicSdncOperation { + private static final String MY_SERVICE = "my-service"; + private static final String MY_VNF = "my-vnf"; + private static final String MY_BANDWIDTH = "my-bandwidth"; + private static final String MY_CHANGE_TIME = "my-change-time"; private BandwidthOnDemandOperation oper; @@ -76,7 +81,7 @@ public class BandwidthOnDemandOperationTest extends BasicSdncOperation { // @formatter:off assertThat(oper.getPropertyNames()).isEqualTo( List.of( - OperationProperties.ENRICHMENT_SERVICE_INSTANCE_ID, + OperationProperties.ENRICHMENT_SERVICE_ID, OperationProperties.ENRICHMENT_BANDWIDTH, OperationProperties.ENRICHMENT_BANDWIDTH_CHANGE_TIME, OperationProperties.ENRICHMENT_VNF_ID)); @@ -93,9 +98,14 @@ public class BandwidthOnDemandOperationTest extends BasicSdncOperation { .path("GENERIC-RESOURCE-API:vf-module-topology-operation").build(); config = new HttpConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory()); - params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).build(); + params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).preprocessed(true).build(); oper = new BandwidthOnDemandOperation(params, config); + oper.setProperty(OperationProperties.ENRICHMENT_SERVICE_ID, MY_SERVICE); + oper.setProperty(OperationProperties.ENRICHMENT_BANDWIDTH, MY_BANDWIDTH); + oper.setProperty(OperationProperties.ENRICHMENT_BANDWIDTH_CHANGE_TIME, MY_CHANGE_TIME); + oper.setProperty(OperationProperties.ENRICHMENT_VNF_ID, MY_VNF); + outcome = oper.start().get(); assertEquals(PolicyResult.SUCCESS, outcome.getResult()); assertTrue(outcome.getResponse() instanceof SdncResponse); @@ -105,7 +115,7 @@ public class BandwidthOnDemandOperationTest extends BasicSdncOperation { public void testMakeRequest() throws Exception { oper.generateSubRequestId(1); SdncRequest request = oper.makeRequest(1); - assertEquals("my-service", request.getNsInstanceId()); + assertEquals(MY_SERVICE, request.getNsInstanceId()); assertEquals(REQ_ID, request.getRequestId()); assertEquals("/my-path/", request.getUrl()); assertEquals(oper.getSubRequestId(), request.getHealRequest().getRequestHeaderInfo().getSvcRequestId()); @@ -119,9 +129,26 @@ public class BandwidthOnDemandOperationTest extends BasicSdncOperation { verifyRequest("bod.json", verifyOperation(oper), IGNORE_FIELDS); } + @Test + public void testMakeRequestViaProperties() throws Exception { + // clear the enrichment data and remake the operation + event.setAai(null); + context = new ControlLoopEventContext(event); + params = params.toBuilder().context(context).build(); + oper = new BandwidthOnDemandOperation(params, config); + + oper.setProperty(OperationProperties.ENRICHMENT_SERVICE_ID, MY_SERVICE); + oper.setProperty(OperationProperties.ENRICHMENT_BANDWIDTH, MY_BANDWIDTH); + oper.setProperty(OperationProperties.ENRICHMENT_BANDWIDTH_CHANGE_TIME, MY_CHANGE_TIME); + oper.setProperty(OperationProperties.ENRICHMENT_VNF_ID, MY_VNF); + + verifyRequest("bod.json", verifyOperation(oper), IGNORE_FIELDS); + } + @Override protected Map makeEnrichment() { - return Map.of(BandwidthOnDemandOperation.SERVICE_ID_KEY, "my-service", BandwidthOnDemandOperation.VNF_ID, - "my-vnf"); + return Map.of(BandwidthOnDemandOperation.SERVICE_ID_KEY, MY_SERVICE, BandwidthOnDemandOperation.BANDWIDTH, + MY_BANDWIDTH, BandwidthOnDemandOperation.BANDWIDTH_CHANGE_TIME, MY_CHANGE_TIME, + BandwidthOnDemandOperation.VNF_ID, MY_VNF); } } diff --git a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperationTest.java b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperationTest.java index 9f06805f6..b71e567bf 100644 --- a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperationTest.java +++ b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperationTest.java @@ -32,6 +32,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance; import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; +import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext; import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig; import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams; import org.onap.policy.controlloop.policy.PolicyResult; @@ -39,6 +40,8 @@ import org.onap.policy.sdnc.SdncRequest; import org.onap.policy.sdnc.SdncResponse; public class RerouteOperationTest extends BasicSdncOperation { + private static final String MY_SERVICE = "my-service"; + private static final String MY_NETWORK = "my-network"; private RerouteOperation oper; @@ -74,9 +77,12 @@ public class RerouteOperationTest extends BasicSdncOperation { .path("GENERIC-RESOURCE-API:network-topology-operation").build(); config = new HttpConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory()); - params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).build(); + params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).preprocessed(true).build(); oper = new RerouteOperation(params, config); + oper.setProperty(OperationProperties.ENRICHMENT_SERVICE_ID, MY_SERVICE); + oper.setProperty(OperationProperties.ENRICHMENT_NETWORK_ID, MY_NETWORK); + outcome = oper.start().get(); assertEquals(PolicyResult.SUCCESS, outcome.getResult()); assertTrue(outcome.getResponse() instanceof SdncResponse); @@ -102,7 +108,7 @@ public class RerouteOperationTest extends BasicSdncOperation { public void testMakeRequest() throws Exception { oper.generateSubRequestId(1); SdncRequest request = oper.makeRequest(1); - assertEquals("my-service", request.getNsInstanceId()); + assertEquals(MY_SERVICE, request.getNsInstanceId()); assertEquals(REQ_ID, request.getRequestId()); assertEquals("/my-path/", request.getUrl()); assertEquals(oper.getSubRequestId(), request.getHealRequest().getRequestHeaderInfo().getSvcRequestId()); @@ -117,8 +123,22 @@ public class RerouteOperationTest extends BasicSdncOperation { verifyRequest("reroute.json", verifyOperation(oper), IGNORE_FIELDS); } + @Test + public void testMakeRequestViaProperties() throws Exception { + // clear the enrichment data and remake the operation + event.setAai(null); + context = new ControlLoopEventContext(event); + params = params.toBuilder().context(context).build(); + oper = new RerouteOperation(params, config); + + oper.setProperty(OperationProperties.ENRICHMENT_SERVICE_ID, MY_SERVICE); + oper.setProperty(OperationProperties.ENRICHMENT_NETWORK_ID, MY_NETWORK); + + verifyRequest("reroute.json", verifyOperation(oper), IGNORE_FIELDS); + } + @Override protected Map makeEnrichment() { - return Map.of(RerouteOperation.SERVICE_ID_KEY, "my-service", RerouteOperation.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/SdncOperationTest.java b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncOperationTest.java index fb9f71b05..4ba12c6ca 100644 --- a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncOperationTest.java +++ b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncOperationTest.java @@ -23,6 +23,7 @@ package org.onap.policy.controlloop.actor.sdnc; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.Collections; @@ -30,6 +31,7 @@ import java.util.Map; import java.util.TreeMap; import org.junit.Before; import org.junit.Test; +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.SdncRequest; @@ -101,6 +103,44 @@ public class SdncOperationTest extends BasicSdncOperation { assertFalse(oper.isSuccess(null, response)); } + @Test + public void testGetOptProperty() { + // in neither property nor enrichment + assertNull(oper.getOptProperty("propA", "propA2")); + + // both - should choose the property + remakeOper(Map.of("propB2", "valueB2")); + oper.setProperty("propB", "valueB"); + assertEquals("valueB", oper.getOptProperty("propB", "propB2")); + + // both - should choose the property, even if it's null + remakeOper(Map.of("propC2", "valueC2")); + oper.setProperty("propC", null); + assertNull(oper.getOptProperty("propC", "propC2")); + + // only in enrichment data + remakeOper(Map.of("propD2", "valueD2")); + assertEquals("valueD2", oper.getOptProperty("propD", "propD2")); + } + + /** + * Remakes the operation, with the specified A&AI enrichment data. + * + * @param aai A&AI enrichment data + */ + private void remakeOper(Map aai) { + event.setAai(aai); + context = new ControlLoopEventContext(event); + params = params.toBuilder().context(context).build(); + + oper = new SdncOperation(params, config, Collections.emptyList()) { + @Override + protected SdncRequest makeRequest(int attempt) { + return request; + } + }; + } + @Override protected Map makeEnrichment() { return new TreeMap<>(); 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 index 8c60bbdd8..8d3545e41 100644 --- a/models-interactions/model-actors/actor.sdnc/src/test/resources/bod.json +++ b/models-interactions/model-actors/actor.sdnc/src/test/resources/bod.json @@ -20,10 +20,12 @@ "vf-module-input-parameters": { "param": [ { - "name": "bandwidth" + "name": "bandwidth", + "value": "my-bandwidth" }, { - "name": "bandwidth-change-time" + "name": "bandwidth-change-time", + "value": "my-change-time" } ] } diff --git a/models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrOperation.java b/models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrOperation.java index f88f3c300..4511cc3c5 100644 --- a/models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrOperation.java +++ b/models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrOperation.java @@ -46,7 +46,7 @@ public class SdnrOperation extends BidirectionalTopicOperation PROPERTY_NAMES = List.of(OperationProperties.AAI_VSERVER_LINK); + private static final List PROPERTY_NAMES = List.of(OperationProperties.EVENT_PAYLOAD); /** * Keys used to match the response with the request listener. The sub request ID is a @@ -156,7 +156,7 @@ public class SdnrOperation extends BidirectionalTopicOperation { } protected int getVfCount() { + if (containsProperty(OperationProperties.DATA_VF_COUNT)) { + return getProperty(OperationProperties.DATA_VF_COUNT); + } + return params.getContext().getProperty(vfCountKey); } protected void setVfCount(int vfCount) { + if (containsProperty(OperationProperties.DATA_VF_COUNT)) { + setProperty(OperationProperties.DATA_VF_COUNT, vfCount); + return; + } + params.getContext().setProperty(vfCountKey, vfCount); } @@ -370,45 +382,77 @@ public abstract class SoOperation extends HttpOperation { return headers; } - /* - * These methods extract data from the Custom Query and throw an - * IllegalArgumentException if the desired data item is not found. + /** + * Gets an item from a property. If the property is not found, then it invokes the + * given function to retrieve it from the custom query data. If that fails as well, + * then an exception is thrown. + * + * @param propName property name + * @param getter method to extract the value from the custom query data + * @param errmsg error message to include in any exception + * @return the retrieved item */ + protected T getItem(String propName, Function getter, String errmsg) { + if (containsProperty(propName)) { + return getProperty(propName); + } - protected GenericVnf getVnfItem(AaiCqResponse aaiCqResponse, SoModelInfo soModelInfo) { - GenericVnf vnf = aaiCqResponse.getGenericVnfByVfModuleModelInvariantId(soModelInfo.getModelInvariantId()); - if (vnf == null) { - throw new IllegalArgumentException("missing generic VNF"); + final AaiCqResponse aaiCqResponse = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY); + T item = getter.apply(aaiCqResponse); + if (item == null) { + throw new IllegalArgumentException(errmsg); } - return vnf; + return item; } - protected ServiceInstance getServiceInstance(AaiCqResponse aaiCqResponse) { - ServiceInstance vnfService = aaiCqResponse.getServiceInstance(); - if (vnfService == null) { - throw new IllegalArgumentException("missing VNF Service Item"); - } + /* + * These methods extract data from the Custom Query and throw an + * IllegalArgumentException if the desired data item is not found. + */ - return vnfService; + protected GenericVnf getVnfItem(SoModelInfo soModelInfo) { + // @formatter:off + return getItem(OperationProperties.AAI_VNF, + cq -> cq.getGenericVnfByVfModuleModelInvariantId(soModelInfo.getModelInvariantId()), + "missing generic VNF"); + // @formatter:on } - protected Tenant getDefaultTenant(AaiCqResponse aaiCqResponse) { - Tenant tenant = aaiCqResponse.getDefaultTenant(); - if (tenant == null) { - throw new IllegalArgumentException("missing Tenant Item"); - } + protected ServiceInstance getServiceInstance() { + return getItem(OperationProperties.AAI_SERVICE, AaiCqResponse::getServiceInstance, "missing VNF Service Item"); + } - return tenant; + protected Tenant getDefaultTenant() { + // @formatter:off + return getItem(OperationProperties.AAI_DEFAULT_TENANT, + AaiCqResponse::getDefaultTenant, + "missing Default Tenant Item"); + // @formatter:on } - protected CloudRegion getDefaultCloudRegion(AaiCqResponse aaiCqResponse) { - CloudRegion cloudRegion = aaiCqResponse.getDefaultCloudRegion(); - if (cloudRegion == null) { - throw new IllegalArgumentException("missing Cloud Region"); - } + protected CloudRegion getDefaultCloudRegion() { + // @formatter:off + return getItem(OperationProperties.AAI_DEFAULT_CLOUD_REGION, + AaiCqResponse::getDefaultCloudRegion, + "missing Default Cloud Region"); + // @formatter:on + } + + protected ModelVer getVnfModel(GenericVnf vnfItem) { + // @formatter:off + return getItem(OperationProperties.AAI_VNF_MODEL, + cq -> cq.getModelVerByVersionId(vnfItem.getModelVersionId()), + "missing generic VNF Model"); + // @formatter:on + } - return cloudRegion; + protected ModelVer getServiceModel(ServiceInstance vnfServiceItem) { + // @formatter:off + return getItem(OperationProperties.AAI_SERVICE_MODEL, + cq -> cq.getModelVerByVersionId(vnfServiceItem.getModelVersionId()), + "missing Service Model"); + // @formatter:on } // these may be overridden by junit tests diff --git a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleCreate.java b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleCreate.java index 4bae1e84d..7e95bda03 100644 --- a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleCreate.java +++ b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleCreate.java @@ -29,6 +29,7 @@ import javax.ws.rs.core.Response; import org.apache.commons.lang3.tuple.Pair; import org.onap.aai.domain.yang.CloudRegion; import org.onap.aai.domain.yang.GenericVnf; +import org.onap.aai.domain.yang.ModelVer; import org.onap.aai.domain.yang.ServiceInstance; import org.onap.aai.domain.yang.Tenant; import org.onap.policy.aai.AaiConstants; @@ -61,10 +62,12 @@ public class VfModuleCreate extends SoOperation { // @formatter:off private static final List PROPERTY_NAMES = List.of( - OperationProperties.AAI_MODEL_SERVICE, - OperationProperties.AAI_MODEL_VNF, - OperationProperties.AAI_MODEL_CLOUD_REGION, - OperationProperties.AAI_MODEL_TENANT, + OperationProperties.AAI_SERVICE, + OperationProperties.AAI_SERVICE_MODEL, + OperationProperties.AAI_VNF, + OperationProperties.AAI_VNF_MODEL, + OperationProperties.AAI_DEFAULT_CLOUD_REGION, + OperationProperties.AAI_DEFAULT_TENANT, OperationProperties.DATA_VF_COUNT); // @formatter:off @@ -156,12 +159,13 @@ public class VfModuleCreate extends SoOperation { * @return a pair containing the request URL and the new request */ protected Pair makeRequest() { - final AaiCqResponse aaiCqResponse = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY); final SoModelInfo soModelInfo = prepareSoModelInfo(); - final GenericVnf vnfItem = getVnfItem(aaiCqResponse, soModelInfo); - final ServiceInstance vnfServiceItem = getServiceInstance(aaiCqResponse); - final Tenant tenantItem = getDefaultTenant(aaiCqResponse); - final CloudRegion cloudRegionItem = getDefaultCloudRegion(aaiCqResponse); + final GenericVnf vnfItem = getVnfItem(soModelInfo); + final ServiceInstance vnfServiceItem = getServiceInstance(); + final Tenant tenantItem = getDefaultTenant(); + final CloudRegion cloudRegionItem = getDefaultCloudRegion(); + final ModelVer vnfModel = getVnfModel(vnfItem); + final ModelVer vnfServiceModel = getServiceModel(vnfServiceItem); SoRequest request = new SoRequest(); request.setOperationType(SoOperationType.SCALE_OUT); @@ -198,10 +202,8 @@ public class VfModuleCreate extends SoOperation { .setModelInvariantId(vnfServiceItem.getModelInvariantId()); relatedInstanceListElement1.getRelatedInstance().getModelInfo() .setModelVersionId(vnfServiceItem.getModelVersionId()); - relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelName( - aaiCqResponse.getModelVerByVersionId(vnfServiceItem.getModelVersionId()).getModelName()); - relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelVersion( - aaiCqResponse.getModelVerByVersionId(vnfServiceItem.getModelVersionId()).getModelVersion()); + relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelName(vnfModel.getModelName()); + relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelVersion(vnfModel.getModelVersion()); // VNF Item relatedInstanceListElement2.getRelatedInstance().setInstanceId(vnfItem.getVnfId()); @@ -211,10 +213,9 @@ public class VfModuleCreate extends SoOperation { .setModelInvariantId(vnfItem.getModelInvariantId()); relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersionId(vnfItem.getModelVersionId()); + relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelName(vnfServiceModel.getModelName()); relatedInstanceListElement2.getRelatedInstance().getModelInfo() - .setModelName(aaiCqResponse.getModelVerByVersionId(vnfItem.getModelVersionId()).getModelName()); - relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersion( - aaiCqResponse.getModelVerByVersionId(vnfItem.getModelVersionId()).getModelVersion()); + .setModelVersion(vnfServiceModel.getModelVersion()); relatedInstanceListElement2.getRelatedInstance().getModelInfo() .setModelCustomizationId(vnfItem.getModelCustomizationId()); diff --git a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleDelete.java b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleDelete.java index 7db76d2d1..0ff833c59 100644 --- a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleDelete.java +++ b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleDelete.java @@ -70,10 +70,10 @@ public class VfModuleDelete extends SoOperation { // @formatter:off private static final List PROPERTY_NAMES = List.of( - OperationProperties.AAI_MODEL_SERVICE, - OperationProperties.AAI_MODEL_VNF, - OperationProperties.AAI_MODEL_CLOUD_REGION, - OperationProperties.AAI_MODEL_TENANT, + OperationProperties.AAI_SERVICE, + OperationProperties.AAI_VNF, + OperationProperties.AAI_DEFAULT_CLOUD_REGION, + OperationProperties.AAI_DEFAULT_TENANT, OperationProperties.DATA_VF_COUNT); // @formatter:on @@ -239,12 +239,11 @@ public class VfModuleDelete extends SoOperation { * @return a pair containing the request URL and the new request */ protected Pair makeRequest() { - final AaiCqResponse aaiCqResponse = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY); final SoModelInfo soModelInfo = prepareSoModelInfo(); - final GenericVnf vnfItem = getVnfItem(aaiCqResponse, soModelInfo); - final ServiceInstance vnfServiceItem = getServiceInstance(aaiCqResponse); - final Tenant tenantItem = getDefaultTenant(aaiCqResponse); - final CloudRegion cloudRegionItem = getDefaultCloudRegion(aaiCqResponse); + final GenericVnf vnfItem = getVnfItem(soModelInfo); + final ServiceInstance vnfServiceItem = getServiceInstance(); + final Tenant tenantItem = getDefaultTenant(); + final CloudRegion cloudRegionItem = getDefaultCloudRegion(); SoRequest request = new SoRequest(); request.setOperationType(SoOperationType.DELETE_VF_MODULE); diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperationTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperationTest.java index 7314c59fa..e364246e4 100644 --- a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperationTest.java +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperationTest.java @@ -36,12 +36,14 @@ import java.time.Month; import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Supplier; import org.junit.Before; import org.junit.Test; import org.onap.aai.domain.yang.CloudRegion; import org.onap.aai.domain.yang.GenericVnf; +import org.onap.aai.domain.yang.ModelVer; import org.onap.aai.domain.yang.ServiceInstance; import org.onap.aai.domain.yang.Tenant; import org.onap.policy.aai.AaiCqResponse; @@ -49,6 +51,7 @@ import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.controlloop.ControlLoopOperation; import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; import org.onap.policy.controlloop.policy.PolicyResult; import org.onap.policy.so.SoModelInfo; import org.onap.policy.so.SoRequest; @@ -63,6 +66,8 @@ public class SoOperationTest extends BasicSoOperation { private static final List PROP_NAMES = Collections.emptyList(); + private static final String VERSION_ID = "1.2.3"; + private SoOperation oper; /** @@ -139,6 +144,24 @@ public class SoOperationTest extends BasicSoOperation { assertEquals(VF_COUNT + 1, oper.getVfCount()); } + /** + * Tests the VF Count methods when properties are being used. + * @throws Exception if an error occurs + */ + @Test + public void testGetVfCount_testSetVfCount_ViaProperties() throws Exception { + oper.setProperty(OperationProperties.DATA_VF_COUNT, VF_COUNT); + + // verify that the count was stored + assertEquals(VF_COUNT.intValue(), oper.getVfCount()); + + oper.setVfCount(VF_COUNT + 1); + + int count = oper.getProperty(OperationProperties.DATA_VF_COUNT); + assertEquals(VF_COUNT + 1, count); + assertEquals(VF_COUNT + 1, oper.getVfCount()); + } + /** * Tests obtainVfCount() when it actually has to query. */ @@ -286,55 +309,114 @@ public class SoOperationTest extends BasicSoOperation { } @Test - public void testGetVnfItem() { - // missing data + public void testGetItem() { AaiCqResponse cq = mock(AaiCqResponse.class); - assertThatIllegalArgumentException().isThrownBy(() -> oper.getVnfItem(cq, oper.prepareSoModelInfo())) - .withMessage("missing generic VNF"); + params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq); - // valid data - GenericVnf vnf = new GenericVnf(); - when(cq.getGenericVnfByVfModuleModelInvariantId(MODEL_INVAR_ID)).thenReturn(vnf); - assertSame(vnf, oper.getVnfItem(cq, oper.prepareSoModelInfo())); + // in neither property nor custom query + assertThatIllegalArgumentException().isThrownBy(() -> oper.getItem("propA", cq2 -> null, "not found")) + .withMessage("not found"); + + // only in custom query + assertEquals("valueB", oper.getItem("propB", cq2 -> "valueB", "failureB")); + + // both - should choose the property + oper.setProperty("propC", "valueC"); + assertEquals("valueC", oper.getItem("propC", cq2 -> "valueC2", "failureC")); + + // both - should choose the property, even if it's null + oper.setProperty("propD", null); + assertNull(oper.getItem("propD", cq2 -> "valueD2", "failureD")); } @Test - public void testGetServiceInstance() { - // missing data - AaiCqResponse cq = mock(AaiCqResponse.class); - assertThatIllegalArgumentException().isThrownBy(() -> oper.getServiceInstance(cq)) - .withMessage("missing VNF Service Item"); + public void testGetVnfItem() { + // @formatter:off + verifyItems(OperationProperties.AAI_VNF, GenericVnf::new, + (cq, instance) -> when(cq.getGenericVnfByVfModuleModelInvariantId(MODEL_INVAR_ID)).thenReturn(instance), + () -> oper.getVnfItem(oper.prepareSoModelInfo()), + "missing generic VNF"); + // @formatter:on + } - // valid data - ServiceInstance instance = new ServiceInstance(); - when(cq.getServiceInstance()).thenReturn(instance); - assertSame(instance, oper.getServiceInstance(cq)); + @Test + public void testGetServiceInstance() { + // @formatter:off + verifyItems(OperationProperties.AAI_SERVICE, ServiceInstance::new, + (cq, instance) -> when(cq.getServiceInstance()).thenReturn(instance), + () -> oper.getServiceInstance(), + "missing VNF Service Item"); + // @formatter:on } @Test public void testGetDefaultTenant() { - // missing data - AaiCqResponse cq = mock(AaiCqResponse.class); - assertThatIllegalArgumentException().isThrownBy(() -> oper.getDefaultTenant(cq)) - .withMessage("missing Tenant Item"); + // @formatter:off + verifyItems(OperationProperties.AAI_DEFAULT_TENANT, Tenant::new, + (cq, tenant) -> when(cq.getDefaultTenant()).thenReturn(tenant), + () -> oper.getDefaultTenant(), + "missing Default Tenant Item"); + // @formatter:on + } - // valid data - Tenant tenant = new Tenant(); - when(cq.getDefaultTenant()).thenReturn(tenant); - assertSame(tenant, oper.getDefaultTenant(cq)); + @Test + public void testGetVnfModel() { + GenericVnf vnf = new GenericVnf(); + vnf.setModelVersionId(VERSION_ID); + + // @formatter:off + verifyItems(OperationProperties.AAI_VNF_MODEL, ModelVer::new, + (cq, model) -> when(cq.getModelVerByVersionId(VERSION_ID)).thenReturn(model), + () -> oper.getVnfModel(vnf), + "missing generic VNF Model"); + // @formatter:on + } + + @Test + public void testGetServiceModel() { + ServiceInstance service = new ServiceInstance(); + service.setModelVersionId(VERSION_ID); + + // @formatter:off + verifyItems(OperationProperties.AAI_SERVICE_MODEL, ModelVer::new, + (cq, model) -> when(cq.getModelVerByVersionId(VERSION_ID)).thenReturn(model), + () -> oper.getServiceModel(service), + "missing Service Model"); + // @formatter:on } @Test public void testGetDefaultCloudRegion() { - // missing data + // @formatter:off + verifyItems(OperationProperties.AAI_DEFAULT_CLOUD_REGION, CloudRegion::new, + (cq, region) -> when(cq.getDefaultCloudRegion()).thenReturn(region), + () -> oper.getDefaultCloudRegion(), + "missing Default Cloud Region"); + // @formatter:on + } + + private void verifyItems(String propName, Supplier maker, BiConsumer setter, + Supplier getter, String errmsg) { + AaiCqResponse cq = mock(AaiCqResponse.class); - assertThatIllegalArgumentException().isThrownBy(() -> oper.getDefaultCloudRegion(cq)) - .withMessage("missing Cloud Region"); + params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq); - // valid data - CloudRegion region = new CloudRegion(); - when(cq.getDefaultCloudRegion()).thenReturn(region); - assertSame(region, oper.getDefaultCloudRegion(cq)); + // in neither property nor custom query + assertThatIllegalArgumentException().isThrownBy(getter::get).withMessage(errmsg); + + // only in custom query + final T item1 = maker.get(); + setter.accept(cq, item1); + assertSame(item1, getter.get()); + + // both - should choose the property + final T item2 = maker.get(); + oper.setProperty(propName, item2); + assertSame(item2, getter.get()); + + // both - should choose the property, even if it's null + oper.setProperty(propName, null); + assertNull(getter.get()); } @Test diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleCreateTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleCreateTest.java index 012f8deff..9d80343e6 100644 --- a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleCreateTest.java +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleCreateTest.java @@ -108,6 +108,51 @@ public class VfModuleCreateTest extends BasicSoOperation { assertTrue(outcome.getResponse() instanceof SoResponse); } + /** + * Tests "success" case with simulator, using properties instead of custom query data. + */ + @Test + public void testSuccessViaProperties() throws Exception { + HttpPollingParams opParams = HttpPollingParams.builder().clientName(MY_CLIENT) + .path("serviceInstantiation/v7/serviceInstances").pollPath("orchestrationRequests/v5/") + .maxPolls(2).build(); + config = new HttpPollingConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory()); + + params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).preprocessed(true).build(); + params.getContext().removeProperty(AaiCqResponse.CONTEXT_KEY); + + oper = new VfModuleCreate(params, config); + + // set the properties + ServiceInstance instance = new ServiceInstance(); + instance.setServiceInstanceId(SVC_INSTANCE_ID); + oper.setProperty(OperationProperties.AAI_SERVICE, instance); + + ModelVer modelVers = new ModelVer(); + modelVers.setModelName(MODEL_NAME2); + modelVers.setModelVersion(MODEL_VERS2); + + oper.setProperty(OperationProperties.AAI_SERVICE_MODEL, modelVers); + oper.setProperty(OperationProperties.AAI_VNF_MODEL, modelVers); + + GenericVnf vnf = new GenericVnf(); + vnf.setVnfId(VNF_ID); + oper.setProperty(OperationProperties.AAI_VNF, vnf); + + oper.setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, new CloudRegion()); + oper.setProperty(OperationProperties.AAI_DEFAULT_TENANT, new Tenant()); + + oper.setProperty(OperationProperties.DATA_VF_COUNT, VF_COUNT); + + // run the operation + outcome = oper.start().get(); + assertEquals(PolicyResult.SUCCESS, outcome.getResult()); + assertTrue(outcome.getResponse() instanceof SoResponse); + + int count = oper.getProperty(OperationProperties.DATA_VF_COUNT); + assertEquals(VF_COUNT + 1, count); + } + @Test public void testConstructor() { assertEquals(DEFAULT_ACTOR, oper.getActorName()); @@ -124,10 +169,12 @@ public class VfModuleCreateTest extends BasicSoOperation { // @formatter:off assertThat(oper.getPropertyNames()).isEqualTo( List.of( - OperationProperties.AAI_MODEL_SERVICE, - OperationProperties.AAI_MODEL_VNF, - OperationProperties.AAI_MODEL_CLOUD_REGION, - OperationProperties.AAI_MODEL_TENANT, + OperationProperties.AAI_SERVICE, + OperationProperties.AAI_SERVICE_MODEL, + OperationProperties.AAI_VNF, + OperationProperties.AAI_VNF_MODEL, + OperationProperties.AAI_DEFAULT_CLOUD_REGION, + OperationProperties.AAI_DEFAULT_TENANT, OperationProperties.DATA_VF_COUNT)); // @formatter:on } diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleDeleteTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleDeleteTest.java index cc2aafa74..9335f0141 100644 --- a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleDeleteTest.java +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleDeleteTest.java @@ -137,6 +137,43 @@ public class VfModuleDeleteTest extends BasicSoOperation { assertTrue(outcome.getResponse() instanceof SoResponse); } + /** + * Tests "success" case with simulator, using properties instead of custom query data. + */ + @Test + public void testSuccessViaProperties() throws Exception { + HttpPollingParams opParams = HttpPollingParams.builder().clientName(MY_CLIENT).path("serviceInstances/v7") + .pollPath("orchestrationRequests/v5/").maxPolls(2).build(); + config = new HttpPollingConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory()); + + params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).preprocessed(true).build(); + params.getContext().removeProperty(AaiCqResponse.CONTEXT_KEY); + + oper = new VfModuleDelete(params, config); + + // set the properties + ServiceInstance instance = new ServiceInstance(); + instance.setServiceInstanceId(SVC_INSTANCE_ID); + oper.setProperty(OperationProperties.AAI_SERVICE, instance); + + GenericVnf vnf = new GenericVnf(); + vnf.setVnfId(VNF_ID); + oper.setProperty(OperationProperties.AAI_VNF, vnf); + + oper.setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, new CloudRegion()); + oper.setProperty(OperationProperties.AAI_DEFAULT_TENANT, new Tenant()); + + oper.setProperty(OperationProperties.DATA_VF_COUNT, VF_COUNT); + + // run the operation + outcome = oper.start().get(); + assertEquals(PolicyResult.SUCCESS, outcome.getResult()); + assertTrue(outcome.getResponse() instanceof SoResponse); + + int count = oper.getProperty(OperationProperties.DATA_VF_COUNT); + assertEquals(VF_COUNT - 1, count); + } + @Test public void testConstructor() { assertEquals(DEFAULT_ACTOR, oper.getActorName()); @@ -153,10 +190,10 @@ public class VfModuleDeleteTest extends BasicSoOperation { // @formatter:off assertThat(oper.getPropertyNames()).isEqualTo( List.of( - OperationProperties.AAI_MODEL_SERVICE, - OperationProperties.AAI_MODEL_VNF, - OperationProperties.AAI_MODEL_CLOUD_REGION, - OperationProperties.AAI_MODEL_TENANT, + OperationProperties.AAI_SERVICE, + OperationProperties.AAI_VNF, + OperationProperties.AAI_DEFAULT_CLOUD_REGION, + OperationProperties.AAI_DEFAULT_TENANT, OperationProperties.DATA_VF_COUNT)); // @formatter:on } diff --git a/models-interactions/model-actors/actor.vfc/src/main/java/org/onap/policy/controlloop/actor/vfc/VfcOperation.java b/models-interactions/model-actors/actor.vfc/src/main/java/org/onap/policy/controlloop/actor/vfc/VfcOperation.java index 8bd4630d6..bb23fdcc5 100644 --- a/models-interactions/model-actors/actor.vfc/src/main/java/org/onap/policy/controlloop/actor/vfc/VfcOperation.java +++ b/models-interactions/model-actors/actor.vfc/src/main/java/org/onap/policy/controlloop/actor/vfc/VfcOperation.java @@ -26,7 +26,6 @@ import javax.ws.rs.core.Response; import org.apache.commons.lang3.StringUtils; import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; -import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext; import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation; import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig; @@ -48,7 +47,7 @@ public abstract class VfcOperation extends HttpOperation { // @formatter:off private static final List PROPERTY_NAMES = List.of( - OperationProperties.ENRICHMENT_SERVICE_INSTANCE_ID, + OperationProperties.ENRICHMENT_SERVICE_ID, OperationProperties.ENRICHMENT_VSERVER_ID, OperationProperties.ENRICHMENT_VSERVER_NAME, OperationProperties.ENRICHMENT_GENERIC_VNF_ID); @@ -133,7 +132,7 @@ public abstract class VfcOperation extends HttpOperation { */ protected String getRequestState(VfcResponse response) { if (response == null || response.getResponseDescriptor() == null - || StringUtils.isBlank(response.getResponseDescriptor().getStatus())) { + || StringUtils.isBlank(response.getResponseDescriptor().getStatus())) { return null; } return response.getResponseDescriptor().getStatus(); @@ -153,7 +152,7 @@ public abstract class VfcOperation extends HttpOperation { */ @Override public OperationOutcome setOutcome(OperationOutcome outcome, PolicyResult result, Response rawResponse, - VfcResponse response) { + VfcResponse response) { // set default result and message setOutcome(outcome, result); @@ -171,14 +170,16 @@ public abstract class VfcOperation extends HttpOperation { * @return request */ protected VfcRequest constructVfcRequest() { - ControlLoopEventContext context = params.getContext(); - String serviceInstance = context.getEnrichment().get("service-instance.service-instance-id"); - String vmId = context.getEnrichment().get("vserver.vserver-id"); - String vmName = context.getEnrichment().get("vserver.vserver-name"); + final String serviceInstance = getOptProperty(OperationProperties.ENRICHMENT_SERVICE_ID, + "service-instance.service-instance-id"); + final String vmId = getOptProperty(OperationProperties.ENRICHMENT_VSERVER_ID, "vserver.vserver-id"); + final String vmName = getOptProperty(OperationProperties.ENRICHMENT_VSERVER_NAME, "vserver.vserver-name"); + final String vnfId = getOptProperty(OperationProperties.ENRICHMENT_GENERIC_VNF_ID, GENERIC_VNF_ID); if (StringUtils.isBlank(serviceInstance) || StringUtils.isBlank(vmId) || StringUtils.isBlank(vmName)) { + // original code did not check the VNF id, so we won't check it either throw new IllegalArgumentException( - "Cannot extract enrichment data for service instance, server id, or server name."); + "Cannot extract enrichment data for service instance, server id, or server name."); } VfcHealActionVmInfo vmActionInfo = new VfcHealActionVmInfo(); @@ -190,7 +191,7 @@ public abstract class VfcOperation extends HttpOperation { additionalParams.setActionInfo(vmActionInfo); VfcHealRequest healRequest = new VfcHealRequest(); - healRequest.setVnfInstanceId(params.getContext().getEnrichment().get(GENERIC_VNF_ID)); + healRequest.setVnfInstanceId(vnfId); healRequest.setCause(getName()); healRequest.setAdditionalParams(additionalParams); @@ -201,4 +202,21 @@ public abstract class VfcOperation extends HttpOperation { return request; } + + /** + * Gets an optional property, first checking the properties, then checking the + * enrichment data. + * + * @param propName property name + * @param enrichmentName property name within the enrichment data + * @return the property's value, or {@code null} if it is not found + */ + protected String getOptProperty(String propName, String enrichmentName) { + if (containsProperty(propName)) { + // return the value, even if it's null + return getProperty(propName); + } + + return params.getContext().getEnrichment().get(enrichmentName); + } } diff --git a/models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/RestartTest.java b/models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/RestartTest.java index 46666456a..068ffdaab 100644 --- a/models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/RestartTest.java +++ b/models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/RestartTest.java @@ -32,6 +32,7 @@ import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.onap.policy.aai.AaiCqResponse; import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance; import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; @@ -42,8 +43,14 @@ import org.onap.policy.vfc.VfcRequest; import org.onap.policy.vfc.VfcResponse; public class RestartTest extends BasicVfcOperation { + private static final String TEST_SERVICE_INSTANCE_ID = "test-service-instance-id"; + private static final String TEST_VSERVER_ID = "test-vserver-id"; + private static final String TEST_VSERVER_NAME = "test-vserver-name"; + private static final String TEST_GENERIC_VNF_ID = "test-generic-vnf-id"; + private Restart restartOper; + @BeforeClass public static void setUpBeforeClass() throws Exception { initBeforeClass(); @@ -60,9 +67,9 @@ public class RestartTest extends BasicVfcOperation { @Before public void setup() throws Exception { super.setUp(); - params.getContext().getEnrichment().put("service-instance.service-instance-id", "test-service-instance-id"); - params.getContext().getEnrichment().put("vserver.vserver-id", "test-vserver-id"); - params.getContext().getEnrichment().put("vserver.vserver-name", "test-vserver-name"); + params.getContext().getEnrichment().put("service-instance.service-instance-id", TEST_SERVICE_INSTANCE_ID); + params.getContext().getEnrichment().put("vserver.vserver-id", TEST_VSERVER_ID); + params.getContext().getEnrichment().put("vserver.vserver-name", TEST_VSERVER_NAME); restartOper = new Restart(params, config); } @@ -84,6 +91,32 @@ public class RestartTest extends BasicVfcOperation { assertTrue(outcome.getResponse() instanceof VfcResponse); } + /** + * Tests "success" case with simulator, using properties instead of custom query data. + */ + @Test + public void testSuccessViaProperties() throws Exception { + HttpPollingParams opParams = HttpPollingParams.builder().clientName(MY_CLIENT).path("ns").pollPath("jobs") + .maxPolls(1).build(); + config = new HttpPollingConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory()); + + params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).preprocessed(true).build(); + params.getContext().removeProperty(AaiCqResponse.CONTEXT_KEY); + + restartOper = new Restart(params, config); + + // set the properties + restartOper.setProperty(OperationProperties.ENRICHMENT_SERVICE_ID, TEST_SERVICE_INSTANCE_ID); + restartOper.setProperty(OperationProperties.ENRICHMENT_VSERVER_ID, TEST_VSERVER_ID); + restartOper.setProperty(OperationProperties.ENRICHMENT_VSERVER_NAME, TEST_VSERVER_NAME); + restartOper.setProperty(OperationProperties.ENRICHMENT_GENERIC_VNF_ID, TEST_GENERIC_VNF_ID); + + // run the operation + outcome = restartOper.start().get(); + assertEquals(PolicyResult.SUCCESS, outcome.getResult()); + assertTrue(outcome.getResponse() instanceof VfcResponse); + } + @Test public void testConstructor() { CompletableFuture futureRes = restartOper.startOperationAsync(1, outcome); @@ -96,7 +129,7 @@ public class RestartTest extends BasicVfcOperation { // @formatter:off assertThat(restartOper.getPropertyNames()).isEqualTo( List.of( - OperationProperties.ENRICHMENT_SERVICE_INSTANCE_ID, + OperationProperties.ENRICHMENT_SERVICE_ID, OperationProperties.ENRICHMENT_VSERVER_ID, OperationProperties.ENRICHMENT_VSERVER_NAME, OperationProperties.ENRICHMENT_GENERIC_VNF_ID)); diff --git a/models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/VfcOperationTest.java b/models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/VfcOperationTest.java index 425ff91b1..6f8956f6f 100644 --- a/models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/VfcOperationTest.java +++ b/models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/VfcOperationTest.java @@ -26,9 +26,11 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import java.util.Map; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext; import org.onap.policy.vfc.VfcResponse; import org.onap.policy.vfc.VfcResponseDescriptor; @@ -87,4 +89,36 @@ public class VfcOperationTest extends BasicVfcOperation { assertTrue(oper.isSuccess(rawResponse, response)); } + @Test + public void testGetOptProperty() { + // in neither property nor enrichment + assertNull(oper.getOptProperty("propA", "propA2")); + + // both - should choose the property + remakeOper(Map.of("propB2", "valueB2")); + oper.setProperty("propB", "valueB"); + assertEquals("valueB", oper.getOptProperty("propB", "propB2")); + + // both - should choose the property, even if it's null + remakeOper(Map.of("propC2", "valueC2")); + oper.setProperty("propC", null); + assertNull(oper.getOptProperty("propC", "propC2")); + + // only in enrichment data + remakeOper(Map.of("propD2", "valueD2")); + assertEquals("valueD2", oper.getOptProperty("propD", "propD2")); + } + + /** + * Remakes the operation, with the specified A&AI enrichment data. + * + * @param aai A&AI enrichment data + */ + private void remakeOper(Map aai) { + event.setAai(aai); + context = new ControlLoopEventContext(event); + params = params.toBuilder().context(context).build(); + + oper = new VfcOperation(params, config) {}; + } } diff --git a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/OperationProperties.java b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/OperationProperties.java index 42846460d..c36b61e8b 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/OperationProperties.java +++ b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/OperationProperties.java @@ -25,28 +25,112 @@ package org.onap.policy.controlloop.actorserviceprovider; * exhaustive, as additional property names may be returned by company-defined Actors. */ public class OperationProperties { - public static final String AAI_MODEL_CLOUD_REGION = "AAI/modelInvariantId/cloudRegion"; - public static final String AAI_MODEL_INVARIANT_GENERIC_VNF = "AAI/modelInvariantId/genericVnf"; - public static final String AAI_MODEL_SERVICE = "AAI/modelInvariantId/service"; - public static final String AAI_MODEL_TENANT = "AAI/modelInvariantId/tenant"; - public static final String AAI_MODEL_VNF = "AAI/modelInvariantId/vnf"; - public static final String AAI_RESOURCE_SERVICE_INSTANCE = "AAI/resourceId/serviceInstanceId"; - public static final String AAI_RESOURCE_VNF = "AAI/resourceId/modelInvariantId/vnf"; + + /** + * A&AI Default Cloud Region. Obtained as follows: + *
    + *
  1. invoke the custom query getDefaultCloudRegion() method
  2. + *
+ */ + public static final String AAI_DEFAULT_CLOUD_REGION = "AAI/defaultCloudRegion"; + + /** + * A&AI Default Tenant. Obtained as follows: + *
    + *
  1. invoke the custom query getDefaultTenant() method
  2. + *
+ */ + public static final String AAI_DEFAULT_TENANT = "AAI/defaultTenant"; + + /** + * A&AI Service instance. Obtained as follows: + *
    + *
  1. invoke the custom query getServiceInstance() method
  2. + *
+ */ + public static final String AAI_SERVICE = "AAI/service"; + + /** + * A&AI Service model. Obtained as follows: + *
    + *
  1. invoke the custom query getServiceInstance() method
  2. + *
  3. using the service instance, invoke the getModelVersionId() method
  4. + *
+ */ + public static final String AAI_SERVICE_MODEL = "AAI/service/model"; + + /** + * A&AI VNF. Obtained as follows: + *
    + *
  1. using the target model invariant ID, invoke the custom query + * getGenericVnfByModelInvariantId() method to get the VNF
  2. + *
  3. using the VNF item, invoke the getModelVersionId() method to get the + * version
  4. + *
+ */ + public static final String AAI_VNF = "AAI/vnf"; + + /** + * A&AI VNF Model. Obtained as follows: + *
    + *
  1. using the target model invariant ID, invoke the custom query + * getGenericVnfByModelInvariantId() method to get the VNF
  2. + *
  3. using the VNF item, invoke the getModelVersionId() method to get the + * version
  4. + *
  5. using the version, invoke the custom query getModelVerByVersionId() method
  6. + *
+ */ + public static final String AAI_VNF_MODEL = "AAI/vnf/model"; + + /** + * A&AI VNF id for the target resource ID. Obtained as follows: + *
    + *
  1. using the target resource ID, invoke the custom query + * getGenericVnfByModelInvariantId() method to get the generic VNF
  2. + *
+ */ + public static final String AAI_RESOURCE_VNF = "AAI/resourceId/vnf"; + + /** + * A&AI PNF. Obtained as follows: + *
    + *
  1. using the target entity, invoke AaiGetPnfOperation
  2. + *
+ */ public static final String AAI_PNF = "AAI/pnf"; + + /** + * A&AI link to the vserver. Obtained as follows: + *
    + *
  1. using the vserver name from the enrichment data, perform an A&AI tenant + * query
  2. + *
  3. get the "result-data" field from the tenant output
  4. + *
  5. get the "resource-link" field from that
  6. + *
  7. strip off the "/aai/v16" prefix
  8. + *
+ */ public static final String AAI_VSERVER_LINK = "AAI/vserver/link"; + /** + * Optional A&AI properties (Map-String-String) for CDS GRPC. If an application + * provides this, it will be used instead of constructing the map from the other + * properties. + */ + public static final String OPT_CDS_GRPC_AAI_PROPERTIES = "cds/grpc/aai/properties"; + /* * These are typically extracted from the event or from the event's enrichment data. + * + * NOTE: all of the values must be of the form "enrichment/{enrichment-field-name}". */ public static final String ENRICHMENT_BANDWIDTH = "enrichment/bandwidth"; - public static final String ENRICHMENT_BANDWIDTH_CHANGE_TIME = "enrichment/bandwidth/changeTime"; - public static final String ENRICHMENT_GENERIC_VNF_ID = "enrichment/genericVnf/id"; - public static final String ENRICHMENT_NETWORK_ID = "enrichment/network/id"; - public static final String ENRICHMENT_SERVICE_ID = "enrichment/service/id"; - public static final String ENRICHMENT_SERVICE_INSTANCE_ID = "enrichment/serviceInstance/id"; - public static final String ENRICHMENT_VNF_ID = "enrichment/vnf/id"; - public static final String ENRICHMENT_VSERVER_ID = "enrichment/vserver/id"; - public static final String ENRICHMENT_VSERVER_NAME = "enrichment/vserver/name"; + public static final String ENRICHMENT_BANDWIDTH_CHANGE_TIME = "enrichment/bandwidth-change-time"; + public static final String ENRICHMENT_GENERIC_VNF_ID = "enrichment/generic-vnf.vnf-id"; + public static final String ENRICHMENT_NETWORK_ID = "enrichment/network-information.network-id"; + public static final String ENRICHMENT_SERVICE_ID = "enrichment/service-instance.service-instance-id"; + public static final String ENRICHMENT_VNF_ID = "enrichment/vnfId"; + public static final String ENRICHMENT_VSERVER_ID = "enrichment/vserver.vserver-id"; + public static final String ENRICHMENT_VSERVER_NAME = "enrichment/vserver.vserver-name"; public static final String EVENT_ADDITIONAL_PARAMS = "event/additionalParams"; public static final String EVENT_PAYLOAD = "event/payload"; @@ -54,6 +138,10 @@ public class OperationProperties { /* * These are data computed and/or tracked by the invoker. */ + + /** + * An Integer containing the count. + */ public static final String DATA_VF_COUNT = "data/vfCount"; diff --git a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperationPartial.java b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperationPartial.java index 9ce53aa7a..0aa112234 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperationPartial.java +++ b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperationPartial.java @@ -139,6 +139,17 @@ public abstract class OperationPartial implements Operation { return params.getOperation(); } + /** + * Determines if a property has been assigned for the operation. + * + * @param name property name + * @return {@code true} if the given property has been assigned for the operation, + * {@code false} otherwise + */ + public boolean containsProperty(String name) { + return properties.containsKey(name); + } + /** * Sets a property. * @@ -326,6 +337,7 @@ public abstract class OperationPartial implements Operation { /** * Generates and sets {@link #subRequestId} to a new subrequest ID. + * * @param attempt attempt number, typically starting with 1 */ public void generateSubRequestId(int attempt) {