From 09f593ae4faca45070f26a5eaafd765eadb08801 Mon Sep 17 00:00:00 2001 From: jhh Date: Tue, 14 Apr 2020 12:36:49 -0500 Subject: native controller generates invalid properties Additional instrumetation and tests have been added as well. Issue-ID: POLICY-2489 Signed-off-by: jhh Change-Id: I65df586f3a44acf3d6f825ebfb8bd73107255a1f Signed-off-by: jhh --- .../PolicyTypeNativeDroolsController.java | 10 +- .../server/restful/RestLifecycleManager.java | 27 ++++- .../lifecycle/LifecycleStateRunningTest.java | 2 + .../PolicyTypeNativeDroolsControllerTest.java | 125 ++++++++++++++++++--- .../server/restful/RestLifecycleManagerTest.java | 20 +++- .../tosca-policy-native-controller-example.json | 18 +-- 6 files changed, 166 insertions(+), 36 deletions(-) (limited to 'feature-lifecycle') diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsController.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsController.java index 9a11955a..65ed3501 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsController.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsController.java @@ -96,7 +96,7 @@ public class PolicyTypeNativeDroolsController implements PolicyTypeController { try { controller.start(); } catch (RuntimeException e) { - logger.warn("failed deploy (cannot start ontroller) for policy: {}", policy, e); + logger.warn("failed deploy (cannot start controller) for policy: {}", policy, e); PolicyEngineConstants.getManager().removePolicyController(controller); return false; } @@ -199,7 +199,7 @@ public class PolicyTypeNativeDroolsController implements PolicyTypeController { private void configTopic( String configCommPrefix, String topicName, List events, Properties controllerProps) { - String configTopicPrefix = configCommPrefix + "." + topicName; + String configTopicPrefix = configCommPrefix + ".topics." + topicName; configTopics(configCommPrefix, topicName, controllerProps); for (ControllerEvent configEvent : events) { configEvent(configTopicPrefix, configEvent, controllerProps); @@ -213,7 +213,6 @@ public class PolicyTypeNativeDroolsController implements PolicyTypeController { private void configEvent(String propPrefix, ControllerEvent configEvent, Properties controllerProps) { String eventPropPrefix = propPrefix + ".events"; - controllerProps.setProperty(eventPropPrefix, configEvent.getEventClass()); if (configEvent.getEventFilter() != null) { controllerProps.setProperty( eventPropPrefix + "." + configEvent.getEventClass() + ".filter", configEvent.getEventFilter()); @@ -225,10 +224,11 @@ public class PolicyTypeNativeDroolsController implements PolicyTypeController { } private void configTopicItemList(String itemPrefix, String item, Properties controllerProps) { - if (controllerProps.getProperty(itemPrefix) == null) { + String itemValue = controllerProps.getProperty(itemPrefix); + if (itemValue == null) { controllerProps.setProperty(itemPrefix, item); } else { - controllerProps.setProperty(itemPrefix, "," + item); + controllerProps.setProperty(itemPrefix, itemValue + "," + item); } } diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/server/restful/RestLifecycleManager.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/server/restful/RestLifecycleManager.java index 5c8f9dc2..4093b510 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/server/restful/RestLifecycleManager.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/server/restful/RestLifecycleManager.java @@ -18,9 +18,11 @@ package org.onap.policy.drools.server.restful; +import com.worldturner.medeia.api.ValidationFailedException; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; +import java.util.Collections; import java.util.List; import java.util.Properties; import java.util.stream.Collectors; @@ -356,7 +358,7 @@ public class RestLifecycleManager { @Path("policies/operations") @ApiOperation(value = "Gets Policy Operations", responseContainer = "List") public Response policiesOperations() { - return Response.status(Response.Status.OK).entity(List.of("deployment", "undeployment")).build(); + return Response.status(Response.Status.OK).entity(List.of("deployment", "undeployment", "validation")).build(); } /** @@ -381,6 +383,29 @@ public class RestLifecycleManager { return deployUndeployOperation(policy, false); } + /** + * POST a policy for validation. + */ + + @POST + @Path("policies/operations/validation") + @ApiOperation(value = "Validates a policy", responseContainer = "List") + public Response validateOperation(@ApiParam(value = "Tosca Policy", required = true) String policy) { + ToscaPolicy toscaPolicy = getToscaPolicy(policy); + if (toscaPolicy == null) { + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } + + try { + LifecycleFeature.fsm.getDomainMaker().conformance(toscaPolicy); + } catch (ValidationFailedException v) { + logger.trace("policy {} validation errors: {}", toscaPolicy, v.getMessage(), v); + return Response.status(Response.Status.NOT_ACCEPTABLE).entity(v.getFailures()).build(); + } + + return Response.status(Response.Status.OK).entity(Collections.emptyList()).build(); + } + private Response deployUndeployOperation(String policy, boolean deploy) { ToscaPolicy toscaPolicy = getToscaPolicy(policy); if (toscaPolicy == null) { diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateRunningTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateRunningTest.java index 16474785..50f35e3e 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateRunningTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateRunningTest.java @@ -34,6 +34,7 @@ import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.time.PseudoScheduledExecutorService; import org.onap.policy.common.utils.time.TestTimeMulti; import org.onap.policy.drools.persistence.SystemPersistenceConstants; +import org.onap.policy.drools.system.PolicyControllerConstants; import org.onap.policy.drools.utils.logging.LoggerUtil; import org.onap.policy.models.pdp.concepts.PdpStatus; import org.onap.policy.models.pdp.enums.PdpMessageType; @@ -69,6 +70,7 @@ public abstract class LifecycleStateRunningTest { controllerSupport.destroyController(); NoopTopicFactories.getSourceFactory().destroy(); NoopTopicFactories.getSinkFactory().destroy(); + PolicyControllerConstants.getFactory().destroy(); try { Files.deleteIfExists(Paths.get(SystemPersistenceConstants.getManager().getConfigurationPath().toString(), CONTROLLER_NAME + "-controller.properties.bak")); diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsControllerTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsControllerTest.java index a230ced8..caab9657 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsControllerTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsControllerTest.java @@ -21,7 +21,9 @@ package org.onap.policy.drools.lifecycle; 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.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; @@ -32,60 +34,155 @@ import org.junit.Test; import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager; import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.common.utils.resources.ResourceUtils; import org.onap.policy.drools.domain.models.controller.ControllerPolicy; import org.onap.policy.drools.system.PolicyControllerConstants; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; /** * Native Controller Policy Test. */ public class PolicyTypeNativeDroolsControllerTest extends LifecycleStateRunningTest { - // Native Drools Policy private static final String EXAMPLE_NATIVE_DROOLS_POLICY_NAME = "example.controller"; private static final String EXAMPLE_NATIVE_DROOLS_POLICY_JSON = "src/test/resources/tosca-policy-native-controller-example.json"; - private ToscaPolicy policy; - private ControllerPolicy controllerPolicy; - private PolicyTypeNativeDroolsController controller; - /** * Test initialization. */ @Before public void init() throws IOException, CoderException { fsm = makeFsmWithPseudoTime(); - policy = getPolicyFromFile(EXAMPLE_NATIVE_DROOLS_POLICY_JSON, EXAMPLE_NATIVE_DROOLS_POLICY_NAME); - controllerPolicy = fsm.getDomainMaker().convertTo(policy, ControllerPolicy.class); - controller = new PolicyTypeNativeDroolsController(fsm, policy.getTypeIdentifier()); + } + + @Test + public void testDeployUndeploy() throws IOException, CoderException { + fsm = makeFsmWithPseudoTime(); assertTrue(controllerSupport.getController().getDrools().isBrained()); assertFalse(controllerSupport.getController().isAlive()); assertFalse(controllerSupport.getController().getDrools().isAlive()); assertSame(controllerSupport.getController(), PolicyControllerConstants.getFactory().get("lifecycle")); - /* start controller */ assertTrue(controllerSupport.getController().start()); assertTrue(controllerSupport.getController().isAlive()); assertTrue(controllerSupport.getController().getDrools().isAlive()); assertTrue(controllerSupport.getController().getDrools().isBrained()); assertSame(controllerSupport.getController(), PolicyControllerConstants.getFactory().get("lifecycle")); - } - @Test - public void testUndeployDeploy() { + ToscaPolicy policy = getPolicyFromFile(EXAMPLE_NATIVE_DROOLS_POLICY_JSON, EXAMPLE_NATIVE_DROOLS_POLICY_NAME); + ControllerPolicy controllerPolicy = fsm.getDomainMaker().convertTo(policy, ControllerPolicy.class); + PolicyTypeNativeDroolsController controller = + new PolicyTypeNativeDroolsController(fsm, policy.getTypeIdentifier()); assertTrue(controller.undeploy(policy)); assertThatIllegalArgumentException().isThrownBy( () -> PolicyControllerConstants.getFactory().get(controllerPolicy.getName())); - assertFalse(controller.deploy(policy)); - Properties noopTopicProperties = new Properties(); noopTopicProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SOURCE_TOPICS, "DCAE_TOPIC"); noopTopicProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, "APPC-CL"); TopicEndpointManager.getManager().addTopics(noopTopicProperties); assertTrue(controller.deploy(policy)); + /* this should be ok too */ + assertTrue(controller.deploy(policy)); + } + + @Test + public void testControllerProperties() throws CoderException { + Properties noopTopicProperties = new Properties(); + noopTopicProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SOURCE_TOPICS, + "DCAE_TOPIC,APPC-CL,APPC-LCM-WRITE,SDNR-CL-RSP"); + noopTopicProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, + "APPC-CL,APPC-LCM-READ,POLICY-CL-MGT,DCAE_CL_RSP"); + TopicEndpointManager.getManager().addTopics(noopTopicProperties); + + ToscaPolicy nativeControllerPolicy = + getExamplesPolicy("policies/usecases.native.controller.policy.input.tosca.json", "usecases"); + PolicyTypeNativeDroolsController controller = + new PolicyTypeNativeDroolsController(fsm, nativeControllerPolicy.getTypeIdentifier()); + assertTrue(controller.deploy(nativeControllerPolicy)); + Properties properties = PolicyControllerConstants.getFactory().get("usecases").getProperties(); + + assertEquals("usecases", properties.getProperty("controller.name")); + + assertNull(properties.getProperty("rules.groupId")); + assertNull(properties.getProperty("rules.artifactId")); + assertNull(properties.getProperty("rules.version")); + + assertEquals("DCAE_TOPIC,APPC-CL,APPC-LCM-WRITE,SDNR-CL-RSP", + properties.getProperty("noop.source.topics")); + assertEquals("APPC-CL,APPC-LCM-READ,POLICY-CL-MGT,DCAE_CL_RSP", + properties.getProperty("noop.sink.topics")); + + assertEquals("org.onap.policy.controlloop.CanonicalOnset,org.onap.policy.controlloop.CanonicalAbated", + properties.getProperty("noop.source.topics.DCAE_TOPIC.events")); + assertEquals("[?($.closedLoopEventStatus == 'ONSET')]", + properties + .getProperty("noop.source.topics.DCAE_TOPIC.events.org.onap.policy.controlloop.CanonicalOnset.filter")); + assertEquals("[?($.closedLoopEventStatus == 'ABATED')]", + properties + .getProperty("noop.source.topics.DCAE_TOPIC.events." + + "org.onap.policy.controlloop.CanonicalAbated.filter")); + assertEquals("org.onap.policy.controlloop.util.Serialization,gson", + properties.getProperty("noop.source.topics.DCAE_TOPIC.events.custom.gson")); + + assertEquals("org.onap.policy.appc.Response", properties.getProperty("noop.source.topics.APPC-CL.events")); + assertEquals("[?($.CommonHeader && $.Status)]", + properties + .getProperty("noop.source.topics.APPC-CL.events.org.onap.policy.appc.Response.filter")); + assertEquals("org.onap.policy.appc.util.Serialization,gsonPretty", + properties.getProperty("noop.source.topics.APPC-CL.events.custom.gson")); + + assertEquals("org.onap.policy.appclcm.AppcLcmDmaapWrapper", + properties.getProperty("noop.source.topics.APPC-LCM-WRITE.events")); + assertEquals("[?($.type == 'response')]", + properties + .getProperty("noop.source.topics.APPC-LCM-WRITE.events." + + "org.onap.policy.appclcm.AppcLcmDmaapWrapper.filter")); + assertEquals("org.onap.policy.appclcm.util.Serialization,gson", + properties.getProperty("noop.source.topics.APPC-LCM-WRITE.events.custom.gson")); + + assertEquals("org.onap.policy.sdnr.PciResponseWrapper", + properties.getProperty("noop.source.topics.SDNR-CL-RSP.events")); + assertEquals("[?($.type == 'response')]", + properties + .getProperty("noop.source.topics.SDNR-CL-RSP.events." + + "org.onap.policy.sdnr.PciResponseWrapper.filter")); + assertEquals("org.onap.policy.sdnr.util.Serialization,gson", + properties.getProperty("noop.source.topics.SDNR-CL-RSP.events.custom.gson")); + + assertEquals("org.onap.policy.appc.Request", properties.getProperty("noop.sink.topics.APPC-CL.events")); + assertEquals("org.onap.policy.appc.util.Serialization,gsonPretty", + properties.getProperty("noop.sink.topics.APPC-CL.events.custom.gson")); + + assertEquals("org.onap.policy.appclcm.AppcLcmDmaapWrapper", + properties.getProperty("noop.sink.topics.APPC-LCM-READ.events")); + assertEquals("org.onap.policy.appclcm.util.Serialization,gson", + properties.getProperty("noop.sink.topics.APPC-LCM-READ.events.custom.gson")); + + assertEquals("org.onap.policy.controlloop.VirtualControlLoopNotification", + properties.getProperty("noop.sink.topics.POLICY-CL-MGT.events")); + assertEquals("org.onap.policy.controlloop.util.Serialization,gsonPretty", + properties.getProperty("noop.sink.topics.POLICY-CL-MGT.events.custom.gson")); + + assertEquals("org.onap.policy.controlloop.ControlLoopResponse", + properties.getProperty("noop.sink.topics.DCAE_CL_RSP.events")); + assertEquals("org.onap.policy.controlloop.util.Serialization,gsonPretty", + properties.getProperty("noop.sink.topics.DCAE_CL_RSP.events.custom.gson")); + + assertEquals("test", properties.getProperty("notes")); + assertEquals("auto", properties.getProperty("persistence.type")); + + assertTrue(controller.undeploy(nativeControllerPolicy)); + } + + private ToscaPolicy getExamplesPolicy(String resourcePath, String policyName) throws CoderException { + String policyJson = ResourceUtils.getResourceAsString(resourcePath); + ToscaServiceTemplate serviceTemplate = new StandardCoder().decode(policyJson, ToscaServiceTemplate.class); + return serviceTemplate.getToscaTopologyTemplate().getPolicies().get(0).get(policyName); } } \ No newline at end of file diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java index 2222399b..d9e21b83 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java @@ -119,8 +119,10 @@ public class RestLifecycleManagerTest { controllerSupport.installArtifact(); Properties noopTopicProperties = new Properties(); - noopTopicProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SOURCE_TOPICS, "DCAE_TOPIC"); - noopTopicProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, "APPC-CL"); + noopTopicProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SOURCE_TOPICS, + "DCAE_TOPIC,APPC-CL,APPC-LCM-WRITE,SDNR-CL-RSP"); + noopTopicProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, + "APPC-CL,APPC-LCM-READ,POLICY-CL-MGT,SDNR-CL,DCAE_CL_RSP"); TopicEndpointManager.getManager().addTopics(noopTopicProperties); client = HttpClientFactoryInstance.getClientFactory().get("lifecycle"); @@ -227,6 +229,8 @@ public class RestLifecycleManagerTest { if (StringUtils.isBlank(opPolicy.getName())) { opPolicy.setName(opPolicy.getMetadata().get("policy-id")); } + assertTrue( + listPost("policies/operations/validation", toString(opPolicy), Status.OK.getStatusCode()).isEmpty()); booleanPost("policies", toString(opPolicy), Status.OK.getStatusCode(), Boolean.TRUE); assertTrue(PolicyControllerConstants.getFactory().get("lifecycle").isAlive()); @@ -253,7 +257,7 @@ public class RestLifecycleManagerTest { /* individual deploy/undeploy operations */ - resourceLists("policies/operations", 2); + resourceLists("policies/operations", 3); booleanPost("policies/operations/deployment", toString(opPolicy), Status.OK.getStatusCode(), Boolean.TRUE); assertEquals(1, @@ -311,6 +315,10 @@ public class RestLifecycleManagerTest { get("policies/example.controller/1.0.0", Status.NOT_FOUND.getStatusCode()); assertThatIllegalArgumentException().isThrownBy(() -> PolicyControllerConstants.getFactory().get("lifecycle")); + opPolicy.getMetadata().remove("policy-id"); + assertFalse( + listPost("policies/operations/validation", toString(opPolicy), + Status.NOT_ACCEPTABLE.getStatusCode()).isEmpty()); } private Response get(String contextPath, int statusCode) { @@ -329,6 +337,12 @@ public class RestLifecycleManagerTest { booleanResponse(response, statusCode, bool); } + private List listPost(String contextPath, String body, int statusCode) { + Response response = client.post(contextPath, Entity.json(body), Collections.emptyMap()); + assertEquals(statusCode, response.getStatus()); + return HttpClient.getBody(response, List.class); + } + private void booleanPost(String contextPath, String body, int statusCode, Boolean bool) { Response response = client.post(contextPath, Entity.json(body), Collections.emptyMap()); booleanResponse(response, statusCode, bool); diff --git a/feature-lifecycle/src/test/resources/tosca-policy-native-controller-example.json b/feature-lifecycle/src/test/resources/tosca-policy-native-controller-example.json index 2b98a242..642ecc0e 100644 --- a/feature-lifecycle/src/test/resources/tosca-policy-native-controller-example.json +++ b/feature-lifecycle/src/test/resources/tosca-policy-native-controller-example.json @@ -18,15 +18,11 @@ "topicName": "DCAE_TOPIC", "events": [ { - "eventClass": "org.onap.policy.controlloop.CanonicalOnset", - "eventFilter": "[?($.closedLoopEventStatus == 'ONSET')]", - "customSerialization": { - "customSerializerClass": "org.onap.policy.controlloop.util.Serialization", - "jsonParser": "gson" - } + "eventClass": "java.util.HashMap", + "eventFilter": "[?($.closedLoopEventStatus == 'ONSET')]" }, { - "eventClass": "org.onap.policy.controlloop.CanonicalAbated", + "eventClass": "java.util.HashMap", "eventFilter": "[?($.closedLoopEventStatus == 'ABATED')]" } ] @@ -37,12 +33,8 @@ "topicName": "APPC-CL", "events": [ { - "eventClass": "org.onap.policy.appc.Response", - "eventFilter": "[?($.CommonHeader && $.Status)]", - "customSerialization": { - "customSerializerClass": "org.onap.policy.appc.util.Serialization", - "jsonParser": "gsonPretty" - } + "eventClass": "java.util.HashMap", + "eventFilter": "[?($.CommonHeader && $.Status)]" } ] } -- cgit 1.2.3-korg