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 | |
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
63 files changed, 1267 insertions, 184 deletions
diff --git a/models-interactions/model-actors/actor.aai/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor b/models-interactions/model-actors/actor.aai/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index 6a52e3f17..6a52e3f17 100644 --- a/models-interactions/model-actors/actor.aai/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor +++ b/models-interactions/model-actors/actor.aai/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor diff --git a/models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiActorServiceProviderTest.java b/models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiActorServiceProviderTest.java index 513f339fb..12b6ca44c 100644 --- a/models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiActorServiceProviderTest.java +++ b/models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiActorServiceProviderTest.java @@ -27,8 +27,9 @@ import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; import org.junit.Test; +import org.onap.policy.controlloop.actor.test.BasicActor; -public class AaiActorServiceProviderTest { +public class AaiActorServiceProviderTest extends BasicActor { @Test public void testAaiActorServiceProvider() { @@ -44,5 +45,8 @@ public class AaiActorServiceProviderTest { var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); assertEquals(expected.toString(), actual.toString()); + + // verify that it all plugs into the ActorService + verifyActorService(AaiActorServiceProvider.NAME, "service.yaml"); } } diff --git a/models-interactions/model-actors/actor.aai/src/test/resources/service.yaml b/models-interactions/model-actors/actor.aai/src/test/resources/service.yaml new file mode 100644 index 000000000..9f6561de0 --- /dev/null +++ b/models-interactions/model-actors/actor.aai/src/test/resources/service.yaml @@ -0,0 +1,33 @@ +# +# ============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: + AAI: + clientName: my-client + operations: + CustomQuery: + path: cq + Tenant: + path: tenant
\ No newline at end of file diff --git a/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcActorServiceProvider.java b/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcActorServiceProvider.java index f6a204540..76aa828c1 100644 --- a/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcActorServiceProvider.java +++ b/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcActorServiceProvider.java @@ -42,7 +42,7 @@ import org.slf4j.LoggerFactory; public class AppcActorServiceProvider extends BidirectionalTopicActor<BidirectionalTopicActorParams> { - private static final String NAME = "APPC"; + public static final String NAME = "APPC"; private static final Logger logger = LoggerFactory.getLogger(AppcActorServiceProvider.class); diff --git a/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcOperation.java b/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcOperation.java index 7d4af80ad..dc46f1253 100644 --- a/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcOperation.java +++ b/models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcOperation.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import org.onap.policy.appc.CommonHeader; import org.onap.policy.appc.Request; import org.onap.policy.appc.Response; @@ -67,6 +68,14 @@ public abstract class AppcOperation extends BidirectionalTopicOperation<Request, } /** + * Starts the GUARD. + */ + @Override + protected CompletableFuture<OperationOutcome> startPreprocessorAsync() { + return startGuardAsync(); + } + + /** * Makes a request, given the target VNF. This is a support function for * {@link #makeRequest(int)}. * @@ -104,10 +113,16 @@ public abstract class AppcOperation extends BidirectionalTopicOperation<Request, * @param source source from which to get the values * @param target where to place the decoded values */ - private static void convertPayload(Map<String, String> source, Map<String, Object> target) { - for (Entry<String, String> ent : source.entrySet()) { + private static void convertPayload(Map<String, Object> source, Map<String, Object> target) { + for (Entry<String, Object> ent : source.entrySet()) { + Object value = ent.getValue(); + if (value == null) { + target.put(ent.getKey(), null); + continue; + } + try { - target.put(ent.getKey(), coder.decode(ent.getValue(), Object.class)); + target.put(ent.getKey(), coder.decode(value.toString(), Object.class)); } catch (CoderException e) { logger.warn("cannot decode JSON value {}: {}", ent.getKey(), ent.getValue(), e); diff --git a/models-interactions/model-actors/actor.appc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor b/models-interactions/model-actors/actor.appc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index f1002a301..f1002a301 100644 --- a/models-interactions/model-actors/actor.appc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor +++ b/models-interactions/model-actors/actor.appc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor diff --git a/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcOperationTest.java b/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcOperationTest.java index 218a4e532..8b71b614d 100644 --- a/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcOperationTest.java +++ b/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcOperationTest.java @@ -63,6 +63,11 @@ public class AppcOperationTest extends BasicAppcOperation { } @Test + public void testStartPreprocessorAsync() { + assertNotNull(oper.startPreprocessorAsync()); + } + + @Test public void testMakeRequest() { Request request = oper.makeRequest(2, MY_VNF); assertEquals(DEFAULT_OPERATION, request.getAction()); @@ -106,7 +111,7 @@ public class AppcOperationTest extends BasicAppcOperation { /* * insert invalid json text into the payload. */ - Map<String, String> payload = new TreeMap<>(params.getPayload()); + Map<String, Object> payload = new TreeMap<>(params.getPayload()); payload.put("invalid-key", "{invalid json"); params = params.toBuilder().payload(payload).build(); @@ -126,6 +131,31 @@ public class AppcOperationTest extends BasicAppcOperation { KEY2, Map.of("output", "world")), request.getPayload()); // @formatter:on + + + /* + * insert null item into the payload. + */ + payload = new TreeMap<>(); + payload.put(KEY1, "abc"); + payload.put(KEY2, null); + payload.put(KEY3, "def"); + params = params.toBuilder().payload(payload).build(); + + oper = new AppcOperation(params, config) { + @Override + protected Request makeRequest(int attempt) { + return oper.makeRequest(attempt, MY_VNF); + } + }; + request = oper.makeRequest(2, MY_VNF); + + payload.put(AppcOperation.VNF_ID_KEY, MY_VNF); + payload.put(KEY1, "abc"); + payload.put(KEY2, null); + payload.put(KEY3, "def"); + + assertEquals(payload, request.getPayload()); } @Test diff --git a/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcServiceProviderTest.java b/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcServiceProviderTest.java index 305c6d7cd..99e9d824a 100644 --- a/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcServiceProviderTest.java +++ b/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/AppcServiceProviderTest.java @@ -43,6 +43,7 @@ import org.onap.policy.controlloop.ControlLoopEventStatus; import org.onap.policy.controlloop.ControlLoopOperation; import org.onap.policy.controlloop.ControlLoopTargetType; 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.controlloop.policy.TargetType; @@ -50,7 +51,7 @@ import org.onap.policy.simulators.Util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class AppcServiceProviderTest { +public class AppcServiceProviderTest extends BasicActor { private static final String GENERIC_VNF_ID = "generic-vnf.vnf-id"; @@ -74,7 +75,8 @@ public class AppcServiceProviderTest { static { /* - * Construct an onset with an AAI subtag containing generic-vnf.vnf-id and a target type of VM. + * Construct an onset with an AAI subtag containing generic-vnf.vnf-id and a + * target type of VM. */ onsetEvent = new VirtualControlLoopEvent(); onsetEvent.setClosedLoopControlName("closedLoopControlName-Test"); @@ -140,6 +142,12 @@ public class AppcServiceProviderTest { } @Test + public void testActorService() { + // verify that it all plugs into the ActorService + verifyActorService(AppcActorServiceProvider.NAME, "service.yaml"); + } + + @Test public void testConstructModifyConfigRequest() { policy.setPayload(new HashMap<>()); policy.getPayload().put(KEY1, VALUE1); diff --git a/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/BasicAppcOperation.java b/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/BasicAppcOperation.java index ed3e7a7ee..ecba91996 100644 --- a/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/BasicAppcOperation.java +++ b/models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/BasicAppcOperation.java @@ -54,6 +54,7 @@ public abstract class BasicAppcOperation extends BasicBidirectionalTopicOperatio protected static final String MY_VNF = "my-vnf"; protected static final String KEY1 = "my-key-A"; protected static final String KEY2 = "my-key-B"; + protected static final String KEY3 = "my-key-C"; protected static final String VALUE1 = "{\"input\":\"hello\"}"; protected static final String VALUE2 = "{\"output\":\"world\"}"; protected static final String RESOURCE_ID = "my-resource"; @@ -162,7 +163,7 @@ public abstract class BasicAppcOperation extends BasicBidirectionalTopicOperatio } @Override - protected Map<String, String> makePayload() { + protected Map<String, Object> makePayload() { return Map.of(KEY1, VALUE1, KEY2, VALUE2); } } 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 5ff789715..460f2c9f0 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 @@ -24,11 +24,11 @@ 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.assertNotNull; -import static org.junit.Assert.assertSame; 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.Arrays; @@ -42,6 +42,7 @@ import org.onap.policy.appc.Request; 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.policy.PolicyResult; public class ModifyConfigOperationTest extends BasicAppcOperation { @@ -64,10 +65,11 @@ public class ModifyConfigOperationTest extends BasicAppcOperation { } @Test - public void testStartPreprocessorAsync() { - CompletableFuture<OperationOutcome> future = new CompletableFuture<>(); + public void testStartPreprocessorAsync() throws Exception { + CompletableFuture<OperationOutcome> future2 = new CompletableFuture<>(); context = mock(ControlLoopEventContext.class); - when(context.obtain(eq(AaiCqResponse.CONTEXT_KEY), any())).thenReturn(future); + when(context.obtain(eq(AaiCqResponse.CONTEXT_KEY), any())).thenReturn(future2); + when(context.getEvent()).thenReturn(event); params = params.toBuilder().context(context).build(); AtomicBoolean guardStarted = new AtomicBoolean(); @@ -80,9 +82,16 @@ public class ModifyConfigOperationTest extends BasicAppcOperation { } }; - assertSame(future, oper.startPreprocessorAsync()); + CompletableFuture<OperationOutcome> future3 = oper.startPreprocessorAsync(); + assertNotNull(future3); assertFalse(future.isDone()); assertTrue(guardStarted.get()); + verify(context).obtain(eq(AaiCqResponse.CONTEXT_KEY), any()); + + future2.complete(params.makeOutcome()); + assertTrue(executor.runAll(100)); + assertTrue(future3.isDone()); + assertEquals(PolicyResult.SUCCESS, future3.get().getResult()); } @Test diff --git a/models-interactions/model-actors/actor.appc/src/test/resources/service.yaml b/models-interactions/model-actors/actor.appc/src/test/resources/service.yaml new file mode 100644 index 000000000..ab9ad98b5 --- /dev/null +++ b/models-interactions/model-actors/actor.appc/src/test/resources/service.yaml @@ -0,0 +1,38 @@ +# +# ============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======================================================== +# +topics: + topicSources: + - topicCommInfrastructure: NOOP + topic: my-source + servers: + - localhost + managed: true + topicSinks: + - topicCommInfrastructure: NOOP + topic: my-sink + servers: + - localhost + managed: true +actors: + APPC: + sinkTopic: my-sink + sourceTopic: my-source + operations: + ModifyConfig: {}
\ No newline at end of file diff --git a/models-interactions/model-actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor b/models-interactions/model-actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index 403ad9859..403ad9859 100644 --- a/models-interactions/model-actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor +++ b/models-interactions/model-actors/actor.appclcm/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor diff --git a/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProvider.java b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProvider.java index ea08d13da..e37de57bb 100644 --- a/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProvider.java +++ b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProvider.java @@ -24,10 +24,11 @@ package org.onap.policy.controlloop.actor.guard; import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor; import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator; +import org.onap.policy.controlloop.actorserviceprovider.impl.OperationPartial; public class GuardActorServiceProvider extends HttpActor<GuardActorParams> { // actor name - public static final String NAME = "GUARD"; + public static final String NAME = OperationPartial.GUARD_ACTOR_NAME; /** * Constructs the object. diff --git a/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardOperation.java b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardOperation.java index 453a3e377..a5459f660 100644 --- a/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardOperation.java +++ b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardOperation.java @@ -20,9 +20,7 @@ package org.onap.policy.controlloop.actor.guard; -import java.util.LinkedHashMap; import java.util.Map; -import java.util.Map.Entry; import java.util.UUID; import java.util.concurrent.CompletableFuture; import javax.ws.rs.client.Entity; @@ -33,13 +31,12 @@ import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType; import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; import org.onap.policy.controlloop.actorserviceprovider.Util; import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation; +import org.onap.policy.controlloop.actorserviceprovider.impl.OperationPartial; import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig; import org.onap.policy.controlloop.policy.PolicyResult; import org.onap.policy.models.decisions.concepts.DecisionRequest; import org.onap.policy.models.decisions.concepts.DecisionResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Guard Operation. The outcome message is set to the guard response. If the guard is @@ -57,17 +54,14 @@ import org.slf4j.LoggerFactory; * </dl> */ public class GuardOperation extends HttpOperation<DecisionResponse> { - private static final Logger logger = LoggerFactory.getLogger(GuardOperation.class); // operation name - public static final String NAME = "Decision"; + public static final String NAME = OperationPartial.GUARD_OPERATION_NAME; public static final String PERMIT = "Permit"; public static final String DENY = "Deny"; public static final String INDETERMINATE = "Indeterminate"; - private static final String RESOURCE = "resource"; - /** * Prefix for properties in the payload that should be copied to the "resource" field * of the request. @@ -118,34 +112,9 @@ public class GuardOperation extends HttpOperation<DecisionResponse> { throw new IllegalArgumentException("missing payload"); } - /* - * This code could be easily modified to allow the context and/or resource to be - * an encoded JSON string, that is decoded into a Map and stuffed into the - * appropriate field. - */ - Map<String, Object> req = config.makeRequest(); - Map<String, Object> resource = new LinkedHashMap<>(); - - for (Entry<String, String> ent : params.getPayload().entrySet()) { - String key = ent.getKey(); - - if (key.startsWith(RESOURCE_PREFIX)) { - // it's a resource property - put into the resource map - key = key.substring(RESOURCE_PREFIX.length()); - resource.put(key, ent.getValue()); - - } else if (key.indexOf('.') < 0) { - // it's a normal property - put into the request map - req.put(key, ent.getValue()); - - } else { - logger.warn("{}: unused key {} in payload for {}", getFullName(), key, params.getRequestId()); - } - } - + req.putAll(params.getPayload()); req.computeIfAbsent("requestId", key -> UUID.randomUUID().toString()); - req.put(RESOURCE, resource); return req; } diff --git a/models-interactions/model-actors/actor.guard/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor b/models-interactions/model-actors/actor.guard/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index dd4368504..dd4368504 100644 --- a/models-interactions/model-actors/actor.guard/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor +++ b/models-interactions/model-actors/actor.guard/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor diff --git a/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorParamsTest.java b/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorParamsTest.java index cd9f4e316..1c256090e 100644 --- a/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorParamsTest.java +++ b/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorParamsTest.java @@ -32,6 +32,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 GuardActorParamsTest { private static final String CONTAINER = "my-container"; @@ -68,13 +69,14 @@ public class GuardActorParamsTest { assertTrue(params.validate(CONTAINER).isValid()); // only a few fields are required - GuardActorParams sparse = Util.translate(CONTAINER, Map.of("operation", operations), GuardActorParams.class); + GuardActorParams sparse = Util.translate(CONTAINER, Map.of(CommonActorParams.OPERATIONS_FIELD, operations), + GuardActorParams.class); assertTrue(sparse.validate(CONTAINER).isValid()); assertEquals(GuardActorParams.DEFAULT_ACTION, sparse.getAction()); // 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)); } @@ -96,7 +98,7 @@ public class GuardActorParamsTest { GuardActorParams params2 = new GuardActorParams(); params2.setClientName(CLIENT); params2.setTimeoutSec(TIMEOUT); - params2.setOperation(operations); + params2.setOperations(operations); params2.setOnapName(ONAP_NAME); params2.setOnapComponent(ONAP_COMP); diff --git a/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProviderTest.java b/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProviderTest.java index f4ab6061e..bb5d4ddf8 100644 --- a/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProviderTest.java +++ b/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProviderTest.java @@ -25,8 +25,9 @@ import static org.junit.Assert.assertEquals; import java.util.Arrays; import java.util.stream.Collectors; import org.junit.Test; +import org.onap.policy.controlloop.actor.test.BasicActor; -public class GuardActorServiceProviderTest { +public class GuardActorServiceProviderTest extends BasicActor { @Test public void test() { @@ -37,5 +38,8 @@ public class GuardActorServiceProviderTest { var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); assertEquals(expected.toString(), actual.toString()); + + // verify that it all plugs into the ActorService + verifyActorService(GuardActorServiceProvider.NAME, "service.yaml"); } } diff --git a/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardOperationTest.java b/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardOperationTest.java index 406cdd05d..bd23a818b 100644 --- a/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardOperationTest.java +++ b/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardOperationTest.java @@ -92,14 +92,16 @@ public class GuardOperationTest extends BasicHttpOperation<DecisionRequest> { verifyPayload("makeReqStd.json", makePayload()); verifyPayload("makeReqDefault.json", new TreeMap<>()); - Map<String, String> payload = new TreeMap<>(); + Map<String, Object> payload = new TreeMap<>(); payload.put("action", "some action"); payload.put("hello", "world"); payload.put("r u there?", "yes"); payload.put("requestId", "some request id"); - payload.put("resource.abc", "def"); - payload.put("resource.ghi", "jkl"); - payload.put("some.other", "unused"); + + Map<String, Object> resource = new TreeMap<>(); + payload.put("resource", resource); + resource.put("abc", "def"); + resource.put("ghi", "jkl"); verifyPayload("makeReq.json", payload); @@ -109,7 +111,7 @@ public class GuardOperationTest extends BasicHttpOperation<DecisionRequest> { assertThatIllegalArgumentException().isThrownBy(() -> oper.makeRequest()); } - private void verifyPayload(String expectedJsonFile, Map<String, String> payload) throws CoderException { + private void verifyPayload(String expectedJsonFile, Map<String, Object> payload) throws CoderException { params.getPayload().clear(); params.getPayload().putAll(payload); @@ -150,7 +152,7 @@ public class GuardOperationTest extends BasicHttpOperation<DecisionRequest> { } @Override - protected Map<String, String> makePayload() { + protected Map<String, Object> makePayload() { DecisionRequest req = new DecisionRequest(); req.setAction("my-action"); req.setOnapComponent("my-onap-component"); @@ -158,12 +160,14 @@ public class GuardOperationTest extends BasicHttpOperation<DecisionRequest> { req.setOnapName("my-onap-name"); req.setRequestId("my-request-id"); - @SuppressWarnings("unchecked") - Map<String, String> map = Util.translate("", req, TreeMap.class); - // add resources - map.put(GuardOperation.RESOURCE_PREFIX + "actor", "resource-actor"); - map.put(GuardOperation.RESOURCE_PREFIX + "operation", "resource-operation"); + Map<String, Object> resource = new TreeMap<>(); + req.setResource(resource); + resource.put("actor", "resource-actor"); + resource.put("operation", "resource-operation"); + + @SuppressWarnings("unchecked") + Map<String, Object> map = Util.translate("", req, TreeMap.class); return map; } diff --git a/models-interactions/model-actors/actor.guard/src/test/resources/makeReqDefault.json b/models-interactions/model-actors/actor.guard/src/test/resources/makeReqDefault.json index 9e9df7b22..d757eb993 100644 --- a/models-interactions/model-actors/actor.guard/src/test/resources/makeReqDefault.json +++ b/models-interactions/model-actors/actor.guard/src/test/resources/makeReqDefault.json @@ -1,5 +1,4 @@ { "action": "guard", - "requestId": "abcdefghi", - "resource": {} + "requestId": "abcdefghi" } diff --git a/models-interactions/model-actors/actor.guard/src/test/resources/service.yaml b/models-interactions/model-actors/actor.guard/src/test/resources/service.yaml new file mode 100644 index 000000000..131cf785b --- /dev/null +++ b/models-interactions/model-actors/actor.guard/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: + GUARD: + clientName: my-client + operations: + Decision: + path: decide
\ No newline at end of file diff --git a/models-interactions/model-actors/actor.sdnc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor b/models-interactions/model-actors/actor.sdnc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index f4d1e975e..f4d1e975e 100644 --- a/models-interactions/model-actors/actor.sdnc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor +++ b/models-interactions/model-actors/actor.sdnc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor diff --git a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProviderTest.java b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProviderTest.java index ac81d49c9..752cb9125 100644 --- a/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProviderTest.java +++ b/models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncActorServiceProviderTest.java @@ -36,10 +36,11 @@ import org.junit.Test; import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; 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.sdnc.SdncRequest; -public class SdncActorServiceProviderTest { +public class SdncActorServiceProviderTest extends BasicActor { private static final String REROUTE = RerouteOperation.NAME; @@ -68,6 +69,9 @@ public class SdncActorServiceProviderTest { var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); assertEquals(expected.toString(), actual.toString()); + + // verify that it all plugs into the ActorService + verifyActorService(SdncActorServiceProvider.NAME, "service.yaml"); } @Test 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 b87ed2c80..b7f71715c 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 @@ -22,6 +22,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.assertTrue; import java.util.Map; @@ -57,6 +58,11 @@ public class SdncOperationTest extends BasicSdncOperation { } @Test + public void testStartPreprocessorAsync() { + assertNotNull(oper.startPreprocessorAsync()); + } + + @Test public void testStartOperationAsync_testStartRequestAsync() throws Exception { verifyOperation(oper); } diff --git a/models-interactions/model-actors/actor.sdnc/src/test/resources/service.yaml b/models-interactions/model-actors/actor.sdnc/src/test/resources/service.yaml new file mode 100644 index 000000000..71d9dae79 --- /dev/null +++ b/models-interactions/model-actors/actor.sdnc/src/test/resources/service.yaml @@ -0,0 +1,33 @@ +# +# ============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: + SDNC: + clientName: my-client + operations: + BandwidthOnDemand: + path: bod + Reroute: + path: reroute
\ No newline at end of file diff --git a/models-interactions/model-actors/actor.sdnr/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor b/models-interactions/model-actors/actor.sdnr/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index c8d5e4c41..c8d5e4c41 100644 --- a/models-interactions/model-actors/actor.sdnr/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor +++ b/models-interactions/model-actors/actor.sdnr/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor 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 diff --git a/models-interactions/model-actors/actor.test/pom.xml b/models-interactions/model-actors/actor.test/pom.xml index 3df35c355..86e34fa8c 100644 --- a/models-interactions/model-actors/actor.test/pom.xml +++ b/models-interactions/model-actors/actor.test/pom.xml @@ -34,6 +34,11 @@ <dependencies> <dependency> <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId> + <artifactId>aai</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId> <artifactId>events</artifactId> <version>${project.version}</version> </dependency> @@ -69,4 +74,18 @@ <scope>compile</scope> </dependency> </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <excludes> + <exclude>src/test/**</exclude> + </excludes> + </configuration> + </plugin> + </plugins> + </build> </project> diff --git a/models-interactions/model-actors/actor.test/src/main/java/org/onap/policy/controlloop/actor/test/BasicActor.java b/models-interactions/model-actors/actor.test/src/main/java/org/onap/policy/controlloop/actor/test/BasicActor.java new file mode 100644 index 000000000..1b11d0d32 --- /dev/null +++ b/models-interactions/model-actors/actor.test/src/main/java/org/onap/policy/controlloop/actor/test/BasicActor.java @@ -0,0 +1,182 @@ +/*- + * ============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.test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.FileNotFoundException; +import java.util.Map; +import lombok.Getter; +import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager; +import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams; +import org.onap.policy.common.endpoints.http.client.HttpClientConfigException; +import org.onap.policy.common.endpoints.http.client.HttpClientFactory; +import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance; +import org.onap.policy.common.endpoints.parameters.TopicParameterGroup; +import org.onap.policy.common.parameters.BeanValidationResult; +import org.onap.policy.common.parameters.BeanValidator; +import org.onap.policy.common.parameters.annotations.NotNull; +import org.onap.policy.common.utils.coder.Coder; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardYamlCoder; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.controlloop.actorserviceprovider.ActorService; +import org.onap.policy.controlloop.actorserviceprovider.Operator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Superclass for various Actor tests. + */ +public class BasicActor { + private static final Logger logger = LoggerFactory.getLogger(BasicActor.class); + private static final Coder yamlCoder = new StandardYamlCoder(); + + /** + * Reads a YAML configuration file, configures the specified topics and HTTP clients, + * and then runs the specified actor through its paces: configure(), start(), stop(), + * and shutdown(). Finally, it destroys the topics and HTTP clients. + * + * @param actorName name of the actor to be tested. + * @param yamlConfigFile YAML configuration file name + * @throws IllegalArgumentException if an error occurs + */ + protected void verifyActorService(String actorName, String yamlConfigFile) { + ActorService service = new ActorService() {}; + + // ensure the actor was loaded + assertNotNull(service.getActor(actorName)); + + try { + MyConfig config = readConfig(yamlConfigFile); + config.validate(); + + startOtherServices(config); + + // configure and verify + service.configure(config.getActors()); + for (Operator operator : service.getActor(actorName).getOperators()) { + assertTrue(operator.isConfigured()); + } + + // start and verify + service.start(); + for (Operator operator : service.getActor(actorName).getOperators()) { + assertTrue(operator.isAlive()); + } + + // stop and verify + service.stop(); + for (Operator operator : service.getActor(actorName).getOperators()) { + assertFalse(operator.isAlive()); + } + + // shut down and verify + service.shutdown(); + for (Operator operator : service.getActor(actorName).getOperators()) { + assertFalse(operator.isAlive()); + } + + } catch (HttpClientConfigException e) { + logger.error("failed to configure HTTP client(s) for actor: {}", actorName); + throw new IllegalArgumentException(e); + + } finally { + stopOtherServices(); + } + } + + /** + * Reads a YAML configuration from a file. + * + * @param yamlConfigFile YAML configuration file name + * @return the configuration that was read from the file + * @throws AssertionError if an error occurs + * @throws CoderException if an error occurs + */ + private MyConfig readConfig(String yamlConfigFile) { + try { + String yaml = ResourceUtils.getResourceAsString(yamlConfigFile); + if (yaml == null) { + throw new FileNotFoundException(yamlConfigFile); + } + + return yamlCoder.decode(yaml, MyConfig.class); + + } catch (CoderException | FileNotFoundException e) { + logger.error("cannot decode YAML file {}", yamlConfigFile); + throw new IllegalArgumentException(e); + } + } + + /** + * Starts the Topic and HTTP clients. + * + * @param config configuration + * @throws HttpClientConfigException if an error occurs + */ + private void startOtherServices(MyConfig config) throws HttpClientConfigException { + stopOtherServices(); + + if (config.getHttpClients() != null) { + HttpClientFactory factory = HttpClientFactoryInstance.getClientFactory(); + for (BusTopicParams params : config.getHttpClients()) { + factory.build(params); + } + } + + if (config.getTopics() != null) { + TopicEndpointManager.getManager().addTopics(config.getTopics()); + } + } + + /** + * Stops the Topic and HTTP clients. + */ + private void stopOtherServices() { + TopicEndpointManager.getManager().shutdown(); + HttpClientFactoryInstance.getClientFactory().destroy(); + } + + @Getter + public static class MyConfig { + private BusTopicParams[] httpClients; + private TopicParameterGroup topics; + + @NotNull + private Map<String, Map<String, Object>> actors; + + /** + * Validates the config. + */ + public void validate() { + BeanValidationResult result = new BeanValidator().validateTop(BasicActor.class.getSimpleName(), this); + if (topics != null) { + result.addResult(topics.validate()); + } + if (!result.isValid()) { + throw new IllegalArgumentException(result.getResult()); + } + } + } +} diff --git a/models-interactions/model-actors/actor.test/src/main/java/org/onap/policy/controlloop/actor/test/BasicOperation.java b/models-interactions/model-actors/actor.test/src/main/java/org/onap/policy/controlloop/actor/test/BasicOperation.java index f027c1c18..989f6a7c3 100644 --- a/models-interactions/model-actors/actor.test/src/main/java/org/onap/policy/controlloop/actor/test/BasicOperation.java +++ b/models-interactions/model-actors/actor.test/src/main/java/org/onap/policy/controlloop/actor/test/BasicOperation.java @@ -21,6 +21,8 @@ package org.onap.policy.controlloop.actor.test; import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; import java.util.Map; import java.util.TreeMap; @@ -29,6 +31,8 @@ import java.util.concurrent.CompletableFuture; import javax.ws.rs.core.Response; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.onap.policy.aai.AaiConstants; +import org.onap.policy.aai.AaiCqResponse; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; @@ -36,9 +40,14 @@ import org.onap.policy.common.utils.resources.ResourceUtils; import org.onap.policy.common.utils.time.PseudoExecutor; import org.onap.policy.controlloop.VirtualControlLoopEvent; import org.onap.policy.controlloop.actorserviceprovider.ActorService; +import org.onap.policy.controlloop.actorserviceprovider.Operation; import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.Operator; import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext; +import org.onap.policy.controlloop.actorserviceprovider.impl.OperationPartial; import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; +import org.onap.policy.controlloop.actorserviceprovider.spi.Actor; +import org.onap.policy.controlloop.policy.PolicyResult; /** * Superclass for various Operation tests. @@ -55,7 +64,22 @@ public class BasicOperation { @Mock protected ActorService service; + @Mock + protected Actor guardActor; + @Mock + protected Operator guardOperator; + @Mock + protected Operation guardOperation; + @Mock + protected Actor cqActor; + @Mock + protected Operator cqOperator; + @Mock + protected Operation cqOperation; + @Mock + protected AaiCqResponse cqResponse; + protected CompletableFuture<OperationOutcome> cqFuture; protected CompletableFuture<Response> future; protected ControlLoopOperationParams params; protected Map<String, String> enrichment; @@ -89,12 +113,28 @@ public class BasicOperation { public void setUpBasic() { MockitoAnnotations.initMocks(this); + cqFuture = new CompletableFuture<>(); future = new CompletableFuture<>(); executor = new PseudoExecutor(); makeContext(); + when(service.getActor(OperationPartial.GUARD_ACTOR_NAME)).thenReturn(guardActor); + when(guardActor.getOperator(OperationPartial.GUARD_OPERATION_NAME)).thenReturn(guardOperator); + when(guardOperator.buildOperation(any())).thenReturn(guardOperation); + + outcome = params.makeOutcome(); + outcome.setResult(PolicyResult.SUCCESS); + when(guardOperation.start()).thenReturn(CompletableFuture.completedFuture(outcome)); + + when(service.getActor(AaiConstants.ACTOR_NAME)).thenReturn(cqActor); + when(cqActor.getOperator("CustomQuery")).thenReturn(cqOperator); + when(cqOperator.buildOperation(any())).thenReturn(cqOperation); + + when(cqOperation.start()).thenReturn(cqFuture); + + // get a fresh outcome outcome = params.makeOutcome(); } @@ -133,7 +173,7 @@ public class BasicOperation { * * @return payload data */ - protected Map<String, String> makePayload() { + protected Map<String, Object> makePayload() { return null; } @@ -162,4 +202,16 @@ public class BasicOperation { assertEquals(expected, json); } + + /** + * Provides a response to a custom query. + * + * @param cq response to provide + */ + protected void provideCqResponse(AaiCqResponse cq) { + context.setProperty(AaiCqResponse.CONTEXT_KEY, cq); + OperationOutcome outcome2 = params.makeOutcome(); + outcome2.setResult(PolicyResult.SUCCESS); + cqFuture.complete(outcome2); + } } diff --git a/models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/BasicActorTest.java b/models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/BasicActorTest.java new file mode 100644 index 000000000..ef9b37ba6 --- /dev/null +++ b/models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/BasicActorTest.java @@ -0,0 +1,47 @@ +/*- + * ============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.test; + +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.Test; + +public class BasicActorTest extends BasicActor { + + @Test + public void testVerifyActorService_testStartOtherServices_testStopOtherServices() { + // mostly empty service + verifyActorService(DummyActor.NAME, "service.yaml"); + + // service with Topics and HTTP Clients + verifyActorService(DummyActor.NAME, "serviceFull.yaml"); + + assertThatIllegalArgumentException() + .isThrownBy(() -> verifyActorService(DummyActor.NAME, "serviceInvalidHttp.yaml")); + + assertThatIllegalArgumentException() + .isThrownBy(() -> verifyActorService(DummyActor.NAME, "serviceMissingActors.yaml")); + + // config file not found + assertThatThrownBy(() -> verifyActorService(DummyActor.NAME, "file-not-found.yaml")); + } +} diff --git a/models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/BasicOperationTest.java b/models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/BasicOperationTest.java index 60bb00892..5eb35e9d0 100644 --- a/models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/BasicOperationTest.java +++ b/models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/BasicOperationTest.java @@ -27,11 +27,16 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.util.Map; +import java.util.concurrent.CompletableFuture; import org.junit.Before; import org.junit.Test; +import org.onap.policy.aai.AaiCqResponse; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; import org.onap.policy.controlloop.actorserviceprovider.Util; +import org.onap.policy.controlloop.actorserviceprovider.impl.OperationPartial; +import org.onap.policy.controlloop.policy.PolicyResult; public class BasicOperationTest { private static final String ACTOR = "my-actor"; @@ -65,6 +70,12 @@ public class BasicOperationTest { assertNotNull(oper.context); assertNotNull(oper.outcome); assertNotNull(oper.executor); + assertNotNull(oper.guardOperation); + + CompletableFuture<OperationOutcome> future = oper.service.getActor(OperationPartial.GUARD_ACTOR_NAME) + .getOperator(OperationPartial.GUARD_OPERATION_NAME).buildOperation(null).start(); + assertTrue(future.isDone()); + assertEquals(PolicyResult.SUCCESS, future.get().getResult()); } @Test @@ -97,4 +108,14 @@ public class BasicOperationTest { Map<String, Object> map = Util.translateToMap("", ResourceUtils.getResourceAsString("actual.json")); oper.verifyRequest("expected.json", map, "svc-request-id", "vnf-id"); } + + @Test + public void testProvideCqResponse() throws Exception { + AaiCqResponse cq = new AaiCqResponse("{}"); + oper.provideCqResponse(cq); + + assertSame(cq, oper.context.getProperty(AaiCqResponse.CONTEXT_KEY)); + assertTrue(oper.cqFuture.isDone()); + assertEquals(PolicyResult.SUCCESS, oper.cqFuture.get().getResult()); + } } diff --git a/models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/DummyActor.java b/models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/DummyActor.java new file mode 100644 index 000000000..c862a18b7 --- /dev/null +++ b/models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/DummyActor.java @@ -0,0 +1,39 @@ +/*- + * ============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.test; + +import org.onap.policy.controlloop.actorserviceprovider.impl.ActorImpl; + +public class DummyActor extends ActorImpl { + public static final String NAME = "MyActor"; + public static final String MY_OPERATION1 = "MyOperationA"; + public static final String MY_OPERATION2 = "MyOperationB"; + + /** + * Constructs the object. + */ + public DummyActor() { + super(NAME); + + addOperator(new DummyOperator(NAME, MY_OPERATION1)); + addOperator(new DummyOperator(NAME, MY_OPERATION2)); + } +} diff --git a/models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/DummyOperator.java b/models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/DummyOperator.java new file mode 100644 index 000000000..efd3b6500 --- /dev/null +++ b/models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/DummyOperator.java @@ -0,0 +1,37 @@ +/*- + * ============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.test; + +import org.onap.policy.controlloop.actorserviceprovider.Operation; +import org.onap.policy.controlloop.actorserviceprovider.impl.OperatorPartial; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; + +public class DummyOperator extends OperatorPartial { + + public DummyOperator(String actorName, String name) { + super(actorName, name); + } + + @Override + public Operation buildOperation(ControlLoopOperationParams params) { + return null; + } +} diff --git a/models-interactions/model-actors/actor.test/src/test/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor b/models-interactions/model-actors/actor.test/src/test/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor new file mode 100644 index 000000000..f9c3bddfd --- /dev/null +++ b/models-interactions/model-actors/actor.test/src/test/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor @@ -0,0 +1 @@ +org.onap.policy.controlloop.actor.test.DummyActor
\ No newline at end of file diff --git a/models-interactions/model-actors/actor.test/src/test/resources/service.yaml b/models-interactions/model-actors/actor.test/src/test/resources/service.yaml new file mode 100644 index 000000000..49de7da51 --- /dev/null +++ b/models-interactions/model-actors/actor.test/src/test/resources/service.yaml @@ -0,0 +1,23 @@ +# +# ============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======================================================== +# +actors: + MyActor: + MyOperationA: {} + MyOperationB: {}
\ No newline at end of file diff --git a/models-interactions/model-actors/actor.test/src/test/resources/serviceFull.yaml b/models-interactions/model-actors/actor.test/src/test/resources/serviceFull.yaml new file mode 100644 index 000000000..9818215be --- /dev/null +++ b/models-interactions/model-actors/actor.test/src/test/resources/serviceFull.yaml @@ -0,0 +1,42 @@ +# +# ============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 +topics: + topicSources: + - topicCommInfrastructure: NOOP + topic: my-source + servers: + - localhost + managed: true + topicSinks: + - topicCommInfrastructure: NOOP + topic: my-sink + servers: + - localhost + managed: true +actors: + MyActor: + MyOperationA: {} + MyOperationB: {}
\ No newline at end of file diff --git a/models-interactions/model-actors/actor.test/src/test/resources/serviceInvalidHttp.yaml b/models-interactions/model-actors/actor.test/src/test/resources/serviceInvalidHttp.yaml new file mode 100644 index 000000000..b31e8e81e --- /dev/null +++ b/models-interactions/model-actors/actor.test/src/test/resources/serviceInvalidHttp.yaml @@ -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======================================================== +# +httpClients: +- clientName: my-client + hostname: localhost + port: 80 + serializationProvider: unknown.class.name + managed: true +actors: + MyActor: + MyOperationA: {} + MyOperationB: {}
\ No newline at end of file diff --git a/models-interactions/model-actors/actor.test/src/test/resources/serviceMissingActors.yaml b/models-interactions/model-actors/actor.test/src/test/resources/serviceMissingActors.yaml new file mode 100644 index 000000000..0eec84ea4 --- /dev/null +++ b/models-interactions/model-actors/actor.test/src/test/resources/serviceMissingActors.yaml @@ -0,0 +1,25 @@ +# +# ============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
\ No newline at end of file diff --git a/models-interactions/model-actors/actor.vfc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor b/models-interactions/model-actors/actor.vfc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index e43c726cf..e43c726cf 100644 --- a/models-interactions/model-actors/actor.vfc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor +++ b/models-interactions/model-actors/actor.vfc/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor diff --git a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/ActorService.java b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/ActorService.java index 24c2cfc23..22c7d3365 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/ActorService.java +++ b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/ActorService.java @@ -24,7 +24,9 @@ package org.onap.policy.controlloop.actorserviceprovider; import com.google.common.collect.ImmutableMap; import java.util.Collection; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; +import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.Set; import org.onap.policy.common.parameters.BeanValidationResult; @@ -57,7 +59,17 @@ public class ActorService extends StartConfigPartial<Map<String, Map<String, Obj Map<String, Actor> map = new HashMap<>(); - for (Actor newActor : loadActors()) { + Iterator<Actor> iter = loadActors().iterator(); + while (iter.hasNext()) { + + Actor newActor; + try { + newActor = iter.next(); + } catch (ServiceConfigurationError e) { + logger.warn("unable to load actor", e); + continue; + } + map.compute(newActor.getName(), (name, existingActor) -> { if (existingActor == null) { return newActor; @@ -168,8 +180,7 @@ public class ActorService extends StartConfigPartial<Map<String, Map<String, Obj @Override protected void doStop() { logger.info("stopping actors"); - name2actor.values() - .forEach(actor -> Util.runFunction(actor::stop, "failed to stop actor {}", actor.getName())); + name2actor.values().forEach(actor -> Util.runFunction(actor::stop, "failed to stop actor {}", actor.getName())); } @Override diff --git a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/controlloop/ControlLoopEventContext.java b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/controlloop/ControlLoopEventContext.java index 8099ea7c2..f7b58c11e 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/controlloop/ControlLoopEventContext.java +++ b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/controlloop/ControlLoopEventContext.java @@ -117,6 +117,14 @@ public class ControlLoopEventContext implements Serializable { } /** + * Removes a property. + * @param name property name + */ + public void removeProperty(String name) { + properties.remove(name); + } + + /** * Obtains the given property. * * @param name name of the desired property 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 e636228f6..c998209bc 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 @@ -23,8 +23,10 @@ package org.onap.policy.controlloop.actorserviceprovider.impl; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; +import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Queue; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; @@ -71,6 +73,8 @@ public abstract class OperationPartial implements Operation { private static final Logger logger = LoggerFactory.getLogger(OperationPartial.class); private static final Coder coder = new StandardCoder(); + public static final String GUARD_ACTOR_NAME = "GUARD"; + public static final String GUARD_OPERATION_NAME = "Decision"; public static final long DEFAULT_RETRY_WAIT_MS = 1000L; private final OperatorConfig config; @@ -187,7 +191,7 @@ public abstract class OperationPartial implements Operation { /** * Invokes the operation's preprocessor step(s) as a "future". This method simply - * invokes {@link #startGuardAsync()}. + * returns {@code null}. * <p/> * This method assumes the following: * <ul> @@ -199,12 +203,11 @@ public abstract class OperationPartial implements Operation { * {@code null} if this operation needs no preprocessor */ protected CompletableFuture<OperationOutcome> startPreprocessorAsync() { - return startGuardAsync(); + return null; } /** - * Invokes the operation's guard step(s) as a "future". This method simply returns - * {@code null}. + * Invokes the operation's guard step(s) as a "future". * <p/> * This method assumes the following: * <ul> @@ -216,7 +219,42 @@ public abstract class OperationPartial implements Operation { * {@code null} if this operation has no guard */ protected CompletableFuture<OperationOutcome> startGuardAsync() { - return null; + // get the guard payload + Map<String,Object> guardPayload = makeGuardPayload(); + + // wrap it in a "resource" + Map<String,Object> resource = new LinkedHashMap<>(); + resource.put("guard", guardPayload); + + Map<String,Object> payload = new LinkedHashMap<>(); + payload.put("resource", resource); + + /* + * Note: can't use constants from actor.guard, because that would create a + * circular dependency. + */ + return params.toBuilder().actor(GUARD_ACTOR_NAME).operation(GUARD_OPERATION_NAME).retry(null).timeoutSec(null) + .payload(payload).build().start(); + } + + /** + * Creates a payload to execute a guard operation. + * + * @return a new guard payload + */ + protected Map<String, Object> makeGuardPayload() { + Map<String, Object> guard = new LinkedHashMap<>(); + guard.put("actor", params.getActor()); + guard.put("recipe", params.getOperation()); + guard.put("target", params.getTargetEntity()); + guard.put("requestId", params.getRequestId()); + + String clname = params.getContext().getEvent().getClosedLoopControlName(); + if (clname != null) { + guard.put("clname", clname); + } + + return guard; } /** diff --git a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/CommonActorParams.java b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/CommonActorParams.java index dc6f2b657..b8218e53b 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/CommonActorParams.java +++ b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/CommonActorParams.java @@ -33,18 +33,22 @@ import org.onap.policy.controlloop.actorserviceprovider.Util; /** * Superclass for Actor parameters that have default values in "this" object, and - * operation-specific values in {@link #operation}. + * operation-specific values in {@link #operations}. */ @Getter @Setter @EqualsAndHashCode public class CommonActorParams { + /** + * Name of the "operations" field contained within actor parameters. + */ + public static final String OPERATIONS_FIELD = "operations"; /** * Maps the operation name to its parameters. */ @NotNull - protected Map<String, Map<String, Object>> operation; + protected Map<String, Map<String, Object>> operations; /** @@ -57,10 +61,10 @@ public class CommonActorParams { public Function<String, Map<String, Object>> makeOperationParameters(String name) { Map<String, Object> defaultParams = Util.translateToMap(name, this); - defaultParams.remove("operation"); + defaultParams.remove(OPERATIONS_FIELD); return operationName -> { - Map<String, Object> specificParams = operation.get(operationName); + Map<String, Object> specificParams = operations.get(operationName); if (specificParams == null) { return null; } diff --git a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/ControlLoopOperationParams.java b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/ControlLoopOperationParams.java index 925916097..7fc15c97b 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/ControlLoopOperationParams.java +++ b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/ControlLoopOperationParams.java @@ -86,7 +86,7 @@ public class ControlLoopOperationParams { /** * Payload data for the request. */ - private Map<String, String> payload; + private Map<String, Object> payload; /** * Number of retries allowed, or {@code null} if no retries. diff --git a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/controlloop/ControlLoopEventContextTest.java b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/controlloop/ControlLoopEventContextTest.java index cf2426214..0f44f4f36 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/controlloop/ControlLoopEventContextTest.java +++ b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/controlloop/ControlLoopEventContextTest.java @@ -41,6 +41,7 @@ import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; public class ControlLoopEventContextTest { + private static final String MY_KEY = "def"; private static final UUID REQ_ID = UUID.randomUUID(); private static final String ITEM_KEY = "obtain-C"; @@ -53,7 +54,7 @@ public class ControlLoopEventContextTest { */ @Before public void setUp() { - enrichment = Map.of("abc", "one", "def", "two"); + enrichment = Map.of("abc", "one", MY_KEY, "two"); event = new VirtualControlLoopEvent(); event.setRequestId(REQ_ID); @@ -81,17 +82,21 @@ public class ControlLoopEventContextTest { } @Test - public void testContains_testGetProperty_testSetProperty() { + public void testContains_testGetProperty_testSetProperty_testRemoveProperty() { context.setProperty("abc", "a string"); - context.setProperty("def", 100); + context.setProperty(MY_KEY, 100); + assertTrue(context.contains(MY_KEY)); assertFalse(context.contains("ghi")); String strValue = context.getProperty("abc"); assertEquals("a string", strValue); - int intValue = context.getProperty("def"); + int intValue = context.getProperty(MY_KEY); assertEquals(100, intValue); + + context.removeProperty(MY_KEY); + assertFalse(context.contains(MY_KEY)); } @Test diff --git a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/BidirectionalTopicActorTest.java b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/BidirectionalTopicActorTest.java index 4a4354195..dfd3f8bc6 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/BidirectionalTopicActorTest.java +++ b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/BidirectionalTopicActorTest.java @@ -172,7 +172,7 @@ public class BidirectionalTopicActorTest { new TreeMap<>(maker.apply("operB")).toString()); // with invalid actor parameters - params.setOperation(null); + params.setOperations(null); assertThatThrownBy(() -> prov.makeOperatorParameters(Util.translateToMap(prov.getName(), params))) .isInstanceOf(ParameterValidationRuntimeException.class); } @@ -212,7 +212,7 @@ public class BidirectionalTopicActorTest { params.setTimeoutSec(TIMEOUT); // @formatter:off - params.setOperation(Map.of( + params.setOperations(Map.of( "operA", Map.of(), "operB", Map.of("sourceTopic", "topicB"))); // @formatter:on diff --git a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/HttpActorTest.java b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/HttpActorTest.java index dacd3a529..a28b98c81 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/HttpActorTest.java +++ b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/HttpActorTest.java @@ -54,7 +54,7 @@ public class HttpActorTest { params.setTimeoutSec(TIMEOUT); // @formatter:off - params.setOperation(Map.of( + params.setOperations(Map.of( "operA", Map.of("path", "urlA"), "operB", Map.of("path", "urlB"))); // @formatter:on @@ -73,7 +73,7 @@ public class HttpActorTest { new TreeMap<>(maker.apply("operB")).toString()); // with invalid actor parameters - params.setOperation(null); + params.setOperations(null); assertThatThrownBy(() -> prov.makeOperatorParameters(Util.translateToMap(prov.getName(), params))) .isInstanceOf(ParameterValidationRuntimeException.class); } diff --git a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperationPartialTest.java b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperationPartialTest.java index 39564a443..2893cb627 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperationPartialTest.java +++ b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperationPartialTest.java @@ -28,6 +28,9 @@ 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.Mockito.verify; +import static org.mockito.Mockito.when; import ch.qos.logback.classic.Logger; import java.time.Instant; @@ -44,7 +47,6 @@ import java.util.concurrent.ForkJoinPool; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.function.Supplier; @@ -55,6 +57,9 @@ import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType; import org.onap.policy.common.utils.coder.Coder; @@ -64,11 +69,14 @@ import org.onap.policy.common.utils.test.log.logback.ExtractAppender; import org.onap.policy.common.utils.time.PseudoExecutor; import org.onap.policy.controlloop.ControlLoopOperation; import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actorserviceprovider.ActorService; import org.onap.policy.controlloop.actorserviceprovider.Operation; import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.Operator; import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext; import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; import org.onap.policy.controlloop.actorserviceprovider.parameters.OperatorConfig; +import org.onap.policy.controlloop.actorserviceprovider.spi.Actor; import org.onap.policy.controlloop.policy.PolicyResult; import org.slf4j.LoggerFactory; @@ -82,6 +90,7 @@ public class OperationPartialTest { private static final String OPERATION = "my-operation"; private static final String MY_SINK = "my-sink"; private static final String MY_SOURCE = "my-source"; + private static final String MY_TARGET_ENTITY = "my-entity"; private static final String TEXT = "my-text"; private static final int TIMEOUT = 1000; private static final UUID REQ_ID = UUID.randomUUID(); @@ -95,6 +104,15 @@ public class OperationPartialTest { private static final Logger logger = (Logger) LoggerFactory.getLogger(OperationPartial.class); private static final ExtractAppender appender = new ExtractAppender(); + @Mock + private ActorService service; + @Mock + private Actor guardActor; + @Mock + private Operator guardOperator; + @Mock + private Operation guardOperation; + private VirtualControlLoopEvent event; private ControlLoopEventContext context; private PseudoExecutor executor; @@ -139,6 +157,8 @@ public class OperationPartialTest { */ @Before public void setUp() { + MockitoAnnotations.initMocks(this); + event = new VirtualControlLoopEvent(); event.setRequestId(REQ_ID); @@ -146,8 +166,13 @@ public class OperationPartialTest { executor = new PseudoExecutor(); params = ControlLoopOperationParams.builder().completeCallback(this::completer).context(context) - .executor(executor).actor(ACTOR).operation(OPERATION).timeoutSec(TIMEOUT) - .startCallback(this::starter).targetEntity(MY_SINK).build(); + .executor(executor).actorService(service).actor(ACTOR).operation(OPERATION).timeoutSec(TIMEOUT) + .startCallback(this::starter).targetEntity(MY_TARGET_ENTITY).build(); + + when(service.getActor(OperationPartial.GUARD_ACTOR_NAME)).thenReturn(guardActor); + when(guardActor.getOperator(OperationPartial.GUARD_OPERATION_NAME)).thenReturn(guardOperator); + when(guardOperator.buildOperation(any())).thenReturn(guardOperation); + when(guardOperation.start()).thenReturn(CompletableFuture.completedFuture(makeSuccess())); config = new OperatorConfig(executor); @@ -189,25 +214,6 @@ public class OperationPartialTest { } /** - * Tests startOperation() when the operation has a preprocessor. - */ - @Test - public void testStartWithPreprocessor() { - AtomicInteger count = new AtomicInteger(); - - CompletableFuture<OperationOutcome> preproc = CompletableFuture.supplyAsync(() -> { - count.incrementAndGet(); - return makeSuccess(); - }, executor); - - oper.setGuard(preproc); - - verifyRun("testStartWithPreprocessor_testStartPreprocessor", 1, 1, PolicyResult.SUCCESS); - - assertEquals(1, count.get()); - } - - /** * Tests start() with multiple running requests. */ @Test @@ -232,7 +238,7 @@ public class OperationPartialTest { */ @Test public void testStartPreprocessorFailure() { - oper.setGuard(CompletableFuture.completedFuture(makeFailure())); + oper.setPreProc(CompletableFuture.completedFuture(makeFailure())); verifyRun("testStartPreprocessorFailure", 1, 0, PolicyResult.FAILURE_GUARD); } @@ -243,7 +249,7 @@ public class OperationPartialTest { @Test public void testStartPreprocessorException() { // arrange for the preprocessor to throw an exception - oper.setGuard(CompletableFuture.failedFuture(new IllegalStateException(EXPECTED_EXCEPTION))); + oper.setPreProc(CompletableFuture.failedFuture(new IllegalStateException(EXPECTED_EXCEPTION))); verifyRun("testStartPreprocessorException", 1, 0, PolicyResult.FAILURE_GUARD); } @@ -254,7 +260,7 @@ public class OperationPartialTest { @Test public void testStartPreprocessorNotRunning() { // arrange for the preprocessor to return success, which will be ignored - oper.setGuard(CompletableFuture.completedFuture(makeSuccess())); + // oper.setGuard(CompletableFuture.completedFuture(makeSuccess())); oper.start().cancel(false); assertTrue(executor.runAll(MAX_REQUESTS)); @@ -291,8 +297,49 @@ public class OperationPartialTest { } @Test - public void testStartGuardAsync() { - assertNull(oper.startGuardAsync()); + public void testStartGuardAsync() throws Exception { + CompletableFuture<OperationOutcome> future = oper.startGuardAsync(); + assertTrue(future.isDone()); + assertEquals(PolicyResult.SUCCESS, future.get().getResult()); + + // verify the parameters that were passed + ArgumentCaptor<ControlLoopOperationParams> paramsCaptor = + ArgumentCaptor.forClass(ControlLoopOperationParams.class); + verify(guardOperator).buildOperation(paramsCaptor.capture()); + + params = paramsCaptor.getValue(); + assertEquals(OperationPartial.GUARD_ACTOR_NAME, params.getActor()); + assertEquals(OperationPartial.GUARD_OPERATION_NAME, params.getOperation()); + assertNull(params.getRetry()); + assertNull(params.getTimeoutSec()); + + Map<String, Object> payload = params.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"); + assertEquals(oper.makeGuardPayload(), guard); + } + + @Test + public void testMakeGuardPayload() { + Map<String, Object> payload = oper.makeGuardPayload(); + assertSame(REQ_ID, payload.get("requestId")); + + // request id changes, so remove it + payload.remove("requestId"); + + assertEquals("{actor=my-actor, recipe=my-operation, target=my-entity}", payload.toString()); + + // repeat, but with closed loop name + event.setClosedLoopControlName("my-loop"); + payload = oper.makeGuardPayload(); + payload.remove("requestId"); + assertEquals("{actor=my-actor, recipe=my-operation, target=my-entity, clname=my-loop}", payload.toString()); } @Test @@ -541,7 +588,7 @@ public class OperationPartialTest { */ @Test public void testHandlePreprocessorFailureTrue() { - oper.setGuard(CompletableFuture.completedFuture(makeSuccess())); + oper.setPreProc(CompletableFuture.completedFuture(makeSuccess())); verifyRun("testHandlePreprocessorFailureTrue", 1, 1, PolicyResult.SUCCESS); } @@ -550,7 +597,7 @@ public class OperationPartialTest { */ @Test public void testHandlePreprocessorFailureFalse() throws Exception { - oper.setGuard(CompletableFuture.completedFuture(makeFailure())); + oper.setPreProc(CompletableFuture.completedFuture(makeFailure())); verifyRun("testHandlePreprocessorFailureFalse", 1, 0, PolicyResult.FAILURE_GUARD); } @@ -559,9 +606,8 @@ public class OperationPartialTest { */ @Test public void testHandlePreprocessorFailureNull() throws Exception { - // arrange to return null from the preprocessor - oper.setGuard(CompletableFuture.completedFuture(null)); - + // arrange to return a null outcome from the preprocessor + oper.setPreProc(CompletableFuture.completedFuture(null)); verifyRun("testHandlePreprocessorFailureNull", 1, 0, PolicyResult.FAILURE_GUARD); } @@ -1211,12 +1257,10 @@ public class OperationPartialTest { @Setter private boolean genException; - @Setter private int maxFailures = 0; - @Setter - private CompletableFuture<OperationOutcome> guard; + private CompletableFuture<OperationOutcome> preProc; public MyOper() { @@ -1242,11 +1286,6 @@ public class OperationPartialTest { } @Override - protected CompletableFuture<OperationOutcome> startGuardAsync() { - return (guard != null ? guard : super.startGuardAsync()); - } - - @Override protected long getRetryWaitMs() { /* * Sleep timers run in the background, but we want to control things via the @@ -1254,5 +1293,10 @@ public class OperationPartialTest { */ return 0L; } + + @Override + protected CompletableFuture<OperationOutcome> startPreprocessorAsync() { + return (preProc != null ? preProc : super.startPreprocessorAsync()); + } } } diff --git a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/BidirectionalTopicActorParamsTest.java b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/BidirectionalTopicActorParamsTest.java index 1f38ad371..1276950a5 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/BidirectionalTopicActorParamsTest.java +++ b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/BidirectionalTopicActorParamsTest.java @@ -76,11 +76,12 @@ public class BidirectionalTopicActorParamsTest { assertTrue(params.validate(CONTAINER).isValid()); // only a few fields are required - BidirectionalTopicActorParams sparse = Util.translate(CONTAINER, Map.of("operation", operMap, "timeoutSec", 1), - BidirectionalTopicActorParams.class); + BidirectionalTopicActorParams sparse = + Util.translate(CONTAINER, Map.of(CommonActorParams.OPERATIONS_FIELD, operMap, "timeoutSec", 1), + BidirectionalTopicActorParams.class); assertTrue(sparse.validate(CONTAINER).isValid()); - 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 @@ -111,7 +112,7 @@ public class BidirectionalTopicActorParamsTest { params2.setSinkTopic(DFLT_SINK); params2.setSourceTopic(DFLT_SOURCE); params2.setTimeoutSec(DFLT_TIMEOUT); - params2.setOperation(operMap); + params2.setOperations(operMap); return params2; } diff --git a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/CommonActorParamsTest.java b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/CommonActorParamsTest.java index 901420346..99b441064 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/CommonActorParamsTest.java +++ b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/CommonActorParamsTest.java @@ -86,7 +86,7 @@ public class CommonActorParamsTest { assertThatCode(() -> params.doValidation(CONTAINER)).doesNotThrowAnyException(); // invalid param - params.setOperation(null); + params.setOperations(null); assertThatThrownBy(() -> params.doValidation(CONTAINER)) .isInstanceOf(ParameterValidationRuntimeException.class); } @@ -96,11 +96,12 @@ public class CommonActorParamsTest { assertTrue(params.validate(CONTAINER).isValid()); // only a few fields are required - CommonActorParams sparse = Util.translate(CONTAINER, Map.of("operation", operations, "timeoutSec", 1), + CommonActorParams sparse = Util.translate(CONTAINER, + Map.of(CommonActorParams.OPERATIONS_FIELD, operations, "timeoutSec", 1), CommonActorParams.class); assertTrue(sparse.validate(CONTAINER).isValid()); - testValidateField("operation", "null", params2 -> params2.setOperation(null)); + testValidateField(CommonActorParams.OPERATIONS_FIELD, "null", params2 -> params2.setOperations(null)); } private void testValidateField(String fieldName, String expected, Consumer<CommonActorParams> makeInvalid) { @@ -119,7 +120,7 @@ public class CommonActorParamsTest { private CommonActorParams makeCommonActorParams() { MyParams params2 = new MyParams(); - params2.setOperation(operations); + params2.setOperations(operations); params2.setText1(TEXT1); params2.setText2(TEXT2); diff --git a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/ControlLoopOperationParamsTest.java b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/ControlLoopOperationParamsTest.java index a5215a48f..e4c83049b 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/ControlLoopOperationParamsTest.java +++ b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/ControlLoopOperationParamsTest.java @@ -99,7 +99,7 @@ public class ControlLoopOperationParamsTest { @Mock private Consumer<OperationOutcome> starter; - private Map<String, String> payload; + private Map<String, Object> payload; private ControlLoopOperationParams params; private OperationOutcome outcome; diff --git a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/HttpActorParamsTest.java b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/HttpActorParamsTest.java index 9e708535f..99bf63305 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/HttpActorParamsTest.java +++ b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/HttpActorParamsTest.java @@ -64,11 +64,11 @@ public class HttpActorParamsTest { assertTrue(params.validate(CONTAINER).isValid()); // only a few fields are required - HttpActorParams sparse = Util.translate(CONTAINER, Map.of("operation", operations, "timeoutSec", 1), - HttpActorParams.class); + HttpActorParams sparse = Util.translate(CONTAINER, + Map.of(CommonActorParams.OPERATIONS_FIELD, operations, "timeoutSec", 1), HttpActorParams.class); assertTrue(sparse.validate(CONTAINER).isValid()); - 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 @@ -97,7 +97,7 @@ public class HttpActorParamsTest { HttpActorParams params2 = new HttpActorParams(); params2.setClientName(CLIENT); params2.setTimeoutSec(TIMEOUT); - params2.setOperation(operations); + params2.setOperations(operations); return params2; } diff --git a/models-interactions/model-actors/actorServiceProvider/src/test/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor b/models-interactions/model-actors/actorServiceProvider/src/test/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor index 2a4bb5749..5f28cf4f2 100644 --- a/models-interactions/model-actors/actorServiceProvider/src/test/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor +++ b/models-interactions/model-actors/actorServiceProvider/src/test/resources/META-INF/services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor @@ -1 +1,2 @@ -org.onap.policy.controlloop.actorserviceprovider.DummyActor
\ No newline at end of file +org.onap.policy.controlloop.actorserviceprovider.DummyActor +org.onap.policy.controlloop.actorserviceprovider.InvalidActor
\ No newline at end of file |