diff options
author | Jim Hahn <jrh3@att.com> | 2020-02-20 19:08:55 -0500 |
---|---|---|
committer | Jim Hahn <jrh3@att.com> | 2020-02-21 20:33:06 -0500 |
commit | 7f69c5ca0a6f6018166f8fee3e811edf4dee1eb8 (patch) | |
tree | e57ab3105adbe0752b30e0e0a60ea43588cfb384 /models-interactions/model-actors/actor.so/src | |
parent | 3c8c5b2994e3f132385f0341283bc271e13cdb25 (diff) |
Change payload to Map<String,Object> so it's more versatile
This was supposed to be two separate commits, but I goofed something.
Added guard query to Operation superclass. Modified VfModuleCreate
to store the VF count, pass it to the guard, and bump it once the
create completes successfully.
Added code to check Actors for proper plug-in to ActorService.
Renamed "operation" property to "operations", to be more consistent
with other parameters (e.g., TopicParameterGroup).
The META-INF/services files for the actors had mixed case, which
did not match the package name of the Actor class, preventing the
ServiceLoader from recognizing them. Also modified the ActorService
to skip any that cannot actually be loaded, for whatever reason
(e.g., not in the classpath).
Issue-ID: POLICY-1625
Signed-off-by: Jim Hahn <jrh3@att.com>
Change-Id: Ifa97744543f2866cc553138ec5ec644b033de780
Diffstat (limited to 'models-interactions/model-actors/actor.so/src')
11 files changed, 303 insertions, 41 deletions
diff --git a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActorServiceProvider.java b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActorServiceProvider.java index 1dbad623b..9c9e6dc62 100644 --- a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActorServiceProvider.java +++ b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActorServiceProvider.java @@ -35,7 +35,7 @@ import org.onap.aai.domain.yang.Tenant; import org.onap.policy.aai.AaiCqResponse; import org.onap.policy.controlloop.ControlLoopOperation; import org.onap.policy.controlloop.VirtualControlLoopEvent; -import org.onap.policy.controlloop.actorserviceprovider.impl.ActorImpl; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor; import org.onap.policy.controlloop.policy.Policy; import org.onap.policy.so.SoCloudConfiguration; import org.onap.policy.so.SoManager; @@ -51,7 +51,7 @@ import org.onap.policy.so.util.Serialization; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class SoActorServiceProvider extends ActorImpl { +public class SoActorServiceProvider extends HttpActor<SoActorParams> { private static final Logger logger = LoggerFactory.getLogger(SoActorServiceProvider.class); public static final String NAME = "SO"; @@ -96,7 +96,7 @@ public class SoActorServiceProvider extends ActorImpl { * Constructs the object. */ public SoActorServiceProvider() { - super(NAME); + super(NAME, SoActorParams.class); addOperator(new SoOperator(NAME, VfModuleCreate.NAME, VfModuleCreate::new)); } diff --git a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoConstants.java b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoConstants.java new file mode 100644 index 000000000..faafb43a6 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoConstants.java @@ -0,0 +1,29 @@ +/*- + * ============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.so; + +public class SoConstants { + public static final String CONTEXT_KEY_VF_COUNT = "SO.VFCount"; + + private SoConstants() { + // do nothing + } +} diff --git a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoOperation.java b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoOperation.java index d8d960e54..53fb973a5 100644 --- a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoOperation.java +++ b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoOperation.java @@ -97,6 +97,23 @@ public abstract class SoOperation extends HttpOperation<SoResponse> { } /** + * Validates that the parameters contain the required target information to extract + * the VF count from the custom query. + */ + protected void validateTarget() { + verifyNotNull("Target information", params.getTarget()); + verifyNotNull("model-customization-id", params.getTarget().getModelCustomizationId()); + verifyNotNull("model-invariant-id", params.getTarget().getModelInvariantId()); + verifyNotNull("model-version-id", params.getTarget().getModelVersionId()); + } + + private void verifyNotNull(String type, Object value) { + if (value == null) { + throw new IllegalArgumentException("missing " + type + " for guard payload"); + } + } + + /** * Starts the GUARD. */ @Override @@ -105,6 +122,24 @@ public abstract class SoOperation extends HttpOperation<SoResponse> { } /** + * Stores the VF count and then runs the guard. + * + * @return a future to cancel or await the guard response + */ + protected CompletableFuture<OperationOutcome> storeVfCountRunGuard() { + String custId = params.getTarget().getModelCustomizationId(); + String invId = params.getTarget().getModelInvariantId(); + String verId = params.getTarget().getModelVersionId(); + + AaiCqResponse cq = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY); + int vfcount = cq.getVfModuleCount(custId, invId, verId); + + params.getContext().setProperty(SoConstants.CONTEXT_KEY_VF_COUNT, vfcount); + + return startGuardAsync(); + } + + /** * If the response does not indicate that the request has been completed, then sleep a * bit and issue a "get". */ @@ -116,6 +151,7 @@ public abstract class SoOperation extends HttpOperation<SoResponse> { if (rawResponse.getStatus() == 200) { String requestState = getRequestState(response); if (COMPLETE.equalsIgnoreCase(requestState)) { + successfulCompletion(); return CompletableFuture .completedFuture(setOutcome(outcome, PolicyResult.SUCCESS, rawResponse, response)); } @@ -147,6 +183,13 @@ public abstract class SoOperation extends HttpOperation<SoResponse> { } /** + * Invoked when a request completes successfully. + */ + protected void successfulCompletion() { + // do nothing + } + + /** * Issues a "get" request to see if the original request is complete yet. * * @param outcome outcome to be populated with the response @@ -251,13 +294,13 @@ public abstract class SoOperation extends HttpOperation<SoResponse> { return null; } - String json = params.getPayload().get(REQ_PARAM_NM); - if (json == null) { + Object data = params.getPayload().get(REQ_PARAM_NM); + if (data == null) { return null; } try { - return coder.decode(json, SoRequestParameters.class); + return coder.decode(data.toString(), SoRequestParameters.class); } catch (CoderException e) { throw new IllegalArgumentException("invalid payload value: " + REQ_PARAM_NM); } @@ -271,14 +314,14 @@ public abstract class SoOperation extends HttpOperation<SoResponse> { return null; } - String json = params.getPayload().get(CONFIG_PARAM_NM); - if (json == null) { + Object data = params.getPayload().get(CONFIG_PARAM_NM); + if (data == null) { return null; } try { @SuppressWarnings("unchecked") - List<Map<String, String>> result = coder.decode(json, ArrayList.class); + List<Map<String, String>> result = coder.decode(data.toString(), ArrayList.class); return result; } catch (CoderException | RuntimeException e) { throw new IllegalArgumentException("invalid payload value: " + CONFIG_PARAM_NM); 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 c17d25211..e88a10cff 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 @@ -20,6 +20,7 @@ package org.onap.policy.controlloop.actor.so; +import java.util.Map; import java.util.concurrent.CompletableFuture; import javax.ws.rs.client.Entity; import javax.ws.rs.core.MediaType; @@ -45,24 +46,61 @@ import org.onap.policy.so.SoRequest; import org.onap.policy.so.SoRequestDetails; import org.onap.policy.so.SoRequestParameters; +/** + * Operation to create a VF Module. This gets the VF count from the A&AI Custom Query + * response and stores it in the context. It also passes the count+1 to the guard. Once + * the "create" completes successfully, it bumps the VF count that's stored in the + * context. + * <p/> + * Note: currently, this only supports storing the count for a single target VF. + */ public class VfModuleCreate extends SoOperation { public static final String NAME = "VF Module Create"; + public static final String PAYLOAD_KEY_VF_COUNT = "vfCount"; + + /** + * Constructs the object. + * + * @param params operation parameters + * @param config configuration for this operation + */ public VfModuleCreate(ControlLoopOperationParams params, HttpConfig config) { super(params, config); + + // ensure we have the necessary parameters + validateTarget(); } /** - * Ensures that A&AI customer query has been performed, and then runs the guard query. + * Ensures that A&AI customer query has been performed, and then runs the guard. */ @Override @SuppressWarnings("unchecked") protected CompletableFuture<OperationOutcome> startPreprocessorAsync() { + if (params.getContext().contains(SoConstants.CONTEXT_KEY_VF_COUNT)) { + return startGuardAsync(); + } + + // need the VF count ControlLoopOperationParams cqParams = params.toBuilder().actor(AaiConstants.ACTOR_NAME) .operation(AaiCustomQueryOperation.NAME).payload(null).retry(null).timeoutSec(null).build(); - // run Custom Query and Guard, in parallel - return allOf(() -> params.getContext().obtain(AaiCqResponse.CONTEXT_KEY, cqParams), this::startGuardAsync); + // run Custom Query, extract the VF count, and then run the Guard + return sequence(() -> params.getContext().obtain(AaiCqResponse.CONTEXT_KEY, cqParams), + this::storeVfCountRunGuard); + } + + @Override + protected Map<String, Object> makeGuardPayload() { + Map<String, Object> payload = super.makeGuardPayload(); + + int vfcount = params.getContext().getProperty(SoConstants.CONTEXT_KEY_VF_COUNT); + + // run guard with the proposed vf count + payload.put(PAYLOAD_KEY_VF_COUNT, vfcount + 1); + + return payload; } @Override @@ -86,6 +124,15 @@ public class VfModuleCreate extends SoOperation { } /** + * Increments the VF count that's stored in the context. + */ + @Override + protected void successfulCompletion() { + int vfcount = params.getContext().getProperty(SoConstants.CONTEXT_KEY_VF_COUNT); + params.getContext().setProperty(SoConstants.CONTEXT_KEY_VF_COUNT, vfcount + 1); + } + + /** * Makes a request. * * @return a pair containing the request URL and the new request diff --git a/models-interactions/model-actors/actor.so/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor b/models-interactions/model-actors/actor.so/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index a955eb71c..a955eb71c 100644 --- a/models-interactions/model-actors/actor.so/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor +++ b/models-interactions/model-actors/actor.so/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/BasicSoOperation.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/BasicSoOperation.java index 3a2aaf849..35f1ef823 100644 --- a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/BasicSoOperation.java +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/BasicSoOperation.java @@ -20,6 +20,7 @@ package org.onap.policy.controlloop.actor.so; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; import java.util.Collections; @@ -28,6 +29,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import org.mockito.Mock; +import org.onap.policy.aai.AaiCqResponse; import org.onap.policy.controlloop.actor.test.BasicHttpOperation; import org.onap.policy.controlloop.actorserviceprovider.Util; import org.onap.policy.controlloop.policy.Target; @@ -52,6 +54,7 @@ public abstract class BasicSoOperation extends BasicHttpOperation<SoRequest> { public static final String PATH_GET = "my-path-get/"; public static final int MAX_GETS = 3; public static final int WAIT_SEC_GETS = 20; + public static final Integer VF_COUNT = 10; @Mock protected SoConfig config; @@ -125,8 +128,8 @@ public abstract class BasicSoOperation extends BasicHttpOperation<SoRequest> { } @Override - protected Map<String, String> makePayload() { - Map<String, String> payload = new HashMap<>(); + protected Map<String, Object> makePayload() { + Map<String, Object> payload = new HashMap<>(); // request parameters SoRequestParameters reqParams = new SoRequestParameters(); @@ -140,4 +143,9 @@ public abstract class BasicSoOperation extends BasicHttpOperation<SoRequest> { return payload; } + + protected AaiCqResponse makeCqResponse() { + when(cqResponse.getVfModuleCount(any(), any(), any())).thenReturn(VF_COUNT); + return cqResponse; + } } diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorParamsTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorParamsTest.java index f463fcb94..5fb647253 100644 --- a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorParamsTest.java +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorParamsTest.java @@ -31,6 +31,7 @@ import org.junit.Before; import org.junit.Test; import org.onap.policy.common.parameters.ValidationResult; import org.onap.policy.controlloop.actorserviceprovider.Util; +import org.onap.policy.controlloop.actorserviceprovider.parameters.CommonActorParams; public class SoActorParamsTest { @@ -67,14 +68,15 @@ public class SoActorParamsTest { assertTrue(params.validate(CONTAINER).isValid()); // only a few fields are required - SoActorParams sparse = Util.translate(CONTAINER, Map.of("operation", operations), SoActorParams.class); + SoActorParams sparse = Util.translate(CONTAINER, Map.of(CommonActorParams.OPERATIONS_FIELD, operations), + SoActorParams.class); assertTrue(sparse.validate(CONTAINER).isValid()); testValidateField("maxGets", "minimum", params2 -> params2.setMaxGets(-1)); testValidateField("waitSecGet", "minimum", params2 -> params2.setWaitSecGet(0)); // check fields from superclass - testValidateField("operation", "null", params2 -> params2.setOperation(null)); + testValidateField(CommonActorParams.OPERATIONS_FIELD, "null", params2 -> params2.setOperations(null)); testValidateField("timeoutSec", "minimum", params2 -> params2.setTimeoutSec(-1)); // check edge cases @@ -105,7 +107,7 @@ public class SoActorParamsTest { SoActorParams params2 = new SoActorParams(); params2.setClientName(CLIENT); params2.setTimeoutSec(TIMEOUT); - params2.setOperation(operations); + params2.setOperations(operations); params2.setWaitSecGet(WAIT_SEC_GETS); params2.setMaxGets(MAX_GETS); diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java index a9d5b8192..b73a65e44 100644 --- a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java @@ -23,6 +23,7 @@ package org.onap.policy.controlloop.actor.so; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; @@ -41,6 +42,7 @@ import org.junit.Test; import org.onap.policy.aai.AaiCqResponse; import org.onap.policy.controlloop.ControlLoopOperation; import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.test.BasicActor; import org.onap.policy.controlloop.policy.Policy; import org.onap.policy.controlloop.policy.Target; import org.onap.policy.so.SoOperationType; @@ -48,7 +50,7 @@ import org.onap.policy.so.SoRequest; import org.onap.policy.so.SoRequestParameters; import org.onap.policy.so.util.Serialization; -public class SoActorServiceProviderTest { +public class SoActorServiceProviderTest extends BasicActor { private static final String C_VALUE = "cvalue"; private static final String A_VALUE = "avalue"; @@ -79,8 +81,15 @@ public class SoActorServiceProviderTest { } @Test + public void testActorService() { + // verify that it all plugs into the ActorService + verifyActorService(SoActorServiceProvider.NAME, "service.yaml"); + } + + @Test public void testSendRequest() { - SoActorServiceProvider.sendRequest(UUID.randomUUID().toString(), null, null, null, null, null); + assertThatCode(() -> SoActorServiceProvider.sendRequest(UUID.randomUUID().toString(), null, null, null, null, + null)).doesNotThrowAnyException(); } @Test 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 871d37032..b2ae5727b 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 @@ -20,8 +20,10 @@ package org.onap.policy.controlloop.actor.so; +import static org.assertj.core.api.Assertions.assertThatCode; 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; @@ -35,7 +37,6 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import java.util.function.Supplier; import org.junit.Before; @@ -82,19 +83,55 @@ public class SoOperationTest extends BasicSoOperation { } @Test + public void testValidateTarget() { + // check when various fields are null + verifyNotNull("model-customization-id", target::getModelCustomizationId, target::setModelCustomizationId); + verifyNotNull("model-invariant-id", target::getModelInvariantId, target::setModelInvariantId); + verifyNotNull("model-version-id", target::getModelVersionId, target::setModelVersionId); + + // verify it's still valid + assertThatCode(() -> new VfModuleCreate(params, config)).doesNotThrowAnyException(); + + // check when Target, itself, is null + params = params.toBuilder().target(null).build(); + assertThatIllegalArgumentException().isThrownBy(() -> new VfModuleCreate(params, config)) + .withMessageContaining("Target information"); + } + + private void verifyNotNull(String expectedText, Supplier<String> getter, Consumer<String> setter) { + String originalValue = getter.get(); + + // try with null + setter.accept(null); + assertThatIllegalArgumentException().isThrownBy(() -> new VfModuleCreate(params, config)) + .withMessageContaining(expectedText); + + setter.accept(originalValue); + } + + @Test public void testStartPreprocessorAsync() { - AtomicBoolean guardStarted = new AtomicBoolean(); + assertNotNull(oper.startPreprocessorAsync()); + } - oper = new SoOperation(params, config) { - @Override - protected CompletableFuture<OperationOutcome> startGuardAsync() { - guardStarted.set(true); - return super.startGuardAsync(); - } - }; + @Test + public void testStoreVfCountRunGuard() throws Exception { + // insert CQ data so it's there for the guard + context.setProperty(AaiCqResponse.CONTEXT_KEY, makeCqResponse()); + + // cause guard to fail + OperationOutcome outcome2 = params.makeOutcome(); + outcome2.setResult(PolicyResult.FAILURE); + when(guardOperation.start()).thenReturn(CompletableFuture.completedFuture(outcome2)); + + CompletableFuture<OperationOutcome> future2 = oper.storeVfCountRunGuard(); + assertTrue(executor.runAll(100)); + assertTrue(future2.isDone()); + assertEquals(PolicyResult.FAILURE, future2.get().getResult()); - assertNull(oper.startPreprocessorAsync()); - assertTrue(guardStarted.get()); + // verify that the count was stored + Integer vfcount = context.getProperty(SoConstants.CONTEXT_KEY_VF_COUNT); + assertEquals(VF_COUNT, vfcount); } @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 6c3cfbf66..63cf744c1 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 @@ -20,15 +20,17 @@ package org.onap.policy.controlloop.actor.so; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +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.ForkJoinPool; import java.util.concurrent.TimeUnit; @@ -36,6 +38,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.lang3.tuple.Pair; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; import org.onap.aai.domain.yang.CloudRegion; import org.onap.aai.domain.yang.GenericVnf; import org.onap.aai.domain.yang.ModelVer; @@ -44,7 +47,7 @@ import org.onap.aai.domain.yang.Tenant; import org.onap.policy.aai.AaiCqResponse; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; -import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; import org.onap.policy.controlloop.policy.PolicyResult; import org.onap.policy.so.SoRequest; @@ -71,14 +74,17 @@ public class VfModuleCreateTest extends BasicSoOperation { public void testConstructor() { assertEquals(DEFAULT_ACTOR, oper.getActorName()); assertEquals(VfModuleCreate.NAME, oper.getName()); + + // verify that target validation is done + params = params.toBuilder().target(null).build(); + assertThatIllegalArgumentException().isThrownBy(() -> new VfModuleCreate(params, config)) + .withMessageContaining("Target information"); } @Test - public void testStartPreprocessorAsync() { - CompletableFuture<OperationOutcome> future = new CompletableFuture<>(); - context = mock(ControlLoopEventContext.class); - when(context.obtain(eq(AaiCqResponse.CONTEXT_KEY), any())).thenReturn(future); - params = params.toBuilder().context(context).build(); + public void testStartPreprocessorAsync() throws Exception { + // put the count in the context so that it will skip the custom query + params.getContext().setProperty(SoConstants.CONTEXT_KEY_VF_COUNT, 20); AtomicBoolean guardStarted = new AtomicBoolean(); @@ -90,13 +96,60 @@ public class VfModuleCreateTest extends BasicSoOperation { } }; - assertSame(future, oper.startPreprocessorAsync()); - assertFalse(future.isDone()); + CompletableFuture<OperationOutcome> future3 = oper.startPreprocessorAsync(); + assertNotNull(future3); assertTrue(guardStarted.get()); } @Test - public void testStartOperationAsync() throws Exception { + public void testStartGuardAsync() throws Exception { + // remove CQ data so it's forced to query + context.removeProperty(AaiCqResponse.CONTEXT_KEY); + + CompletableFuture<OperationOutcome> future2 = oper.startPreprocessorAsync(); + assertTrue(executor.runAll(100)); + assertFalse(future2.isDone()); + + provideCqResponse(makeCqResponse()); + assertTrue(executor.runAll(100)); + assertTrue(future2.isDone()); + assertEquals(PolicyResult.SUCCESS, future2.get().getResult()); + } + + @Test + public void testMakeGuardPayload() { + final int origCount = 30; + params.getContext().setProperty(SoConstants.CONTEXT_KEY_VF_COUNT, origCount); + + CompletableFuture<OperationOutcome> future2 = oper.startPreprocessorAsync(); + assertTrue(executor.runAll(100)); + assertTrue(future2.isDone()); + + // get the payload from the request + ArgumentCaptor<ControlLoopOperationParams> captor = ArgumentCaptor.forClass(ControlLoopOperationParams.class); + verify(guardOperator).buildOperation(captor.capture()); + + Map<String, Object> payload = captor.getValue().getPayload(); + assertNotNull(payload); + + @SuppressWarnings("unchecked") + Map<String, Object> resource = (Map<String, Object>) payload.get("resource"); + assertNotNull(resource); + + @SuppressWarnings("unchecked") + Map<String, Object> guard = (Map<String, Object>) resource.get("guard"); + assertNotNull(guard); + + Integer newCount = (Integer) guard.get(VfModuleCreate.PAYLOAD_KEY_VF_COUNT); + assertNotNull(newCount); + assertEquals(origCount + 1, newCount.intValue()); + } + + @Test + public void testStartOperationAsync_testSuccessfulCompletion() throws Exception { + final int origCount = 30; + params.getContext().setProperty(SoConstants.CONTEXT_KEY_VF_COUNT, origCount); + when(client.post(any(), any(), any(), any())).thenAnswer(provideResponse(rawResponse)); // use a real executor @@ -113,6 +166,9 @@ public class VfModuleCreateTest extends BasicSoOperation { outcome = future2.get(500, TimeUnit.SECONDS); assertEquals(PolicyResult.SUCCESS, outcome.getResult()); + + Integer newCount = (Integer) params.getContext().getProperty(SoConstants.CONTEXT_KEY_VF_COUNT); + assertEquals(origCount + 1, newCount.intValue()); } /** diff --git a/models-interactions/model-actors/actor.so/src/test/resources/service.yaml b/models-interactions/model-actors/actor.so/src/test/resources/service.yaml new file mode 100644 index 000000000..b1ac162a4 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/resources/service.yaml @@ -0,0 +1,31 @@ +# +# ============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======================================================== +# +httpClients: +- clientName: my-client + hostname: localhost + port: 80 + basePath: base-url + managed: true +actors: + SO: + clientName: my-client + operations: + VF Module Create: + path: create
\ No newline at end of file |