aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhh <jorge.hernandez-herrero@att.com>2020-03-31 21:05:14 -0500
committerjhh <jorge.hernandez-herrero@att.com>2020-04-01 10:59:29 -0500
commitece155048af47ea83ff898c999aa5137dc99a988 (patch)
tree25af254f7cbbb42a99b9b98d5e6767c65aef563d
parent565b43c67c8964fe9e046435307e479921881566 (diff)
Sync controller capabilities as controllers bounce
As native policies introduce temporality in policy types supported as they are removed and added, the associated policy types that can be honored at a a given time, may need to adjust. A significan portion of this review is dedicated to multi-policy junits and telemetry instrumentation. Issue-ID: POLICY-2459 Signed-off-by: jhh <jorge.hernandez-herrero@att.com> Change-Id: I62bbc03411446849eaa55c9b1524220dc13c2cb0 Signed-off-by: jhh <jorge.hernandez-herrero@att.com>
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java5
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java23
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsController.java1
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsController.java17
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/server/restful/RestLifecycleManager.java194
-rw-r--r--feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java18
-rw-r--r--feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java359
-rw-r--r--feature-lifecycle/src/test/resources/lifecycle.kmodule5
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java7
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java4
10 files changed, 534 insertions, 99 deletions
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java
index d9205977..12828e02 100644
--- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java
@@ -23,6 +23,7 @@ package org.onap.policy.drools.lifecycle;
import org.onap.policy.drools.features.DroolsControllerFeatureApi;
import org.onap.policy.drools.features.PolicyControllerFeatureApi;
import org.onap.policy.drools.features.PolicyEngineFeatureApi;
+import org.onap.policy.drools.protocol.configuration.DroolsConfiguration;
import org.onap.policy.drools.system.PolicyController;
import org.onap.policy.drools.system.PolicyEngine;
@@ -52,7 +53,9 @@ public class LifecycleFeature
}
@Override
- public boolean afterPatch(PolicyController controller, boolean success) {
+ public boolean afterPatch(
+ PolicyController controller, DroolsConfiguration oldConfiguration,
+ DroolsConfiguration newConfiguration, boolean success) {
return fsmPatch(controller);
}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java
index 3ecb4b3a..ac76883f 100644
--- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java
@@ -31,6 +31,7 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
@@ -189,6 +190,7 @@ public class LifecycleFsm implements Startable {
PolicyTypeDroolsController ptDroolsController = (PolicyTypeDroolsController) policyTypesMap.get(id);
if (ptDroolsController == null) {
policyTypesMap.put(id, new PolicyTypeDroolsController(this, id, controller));
+ logger.info("policy-type {} added", id);
} else {
ptDroolsController.add(controller);
}
@@ -219,14 +221,19 @@ public class LifecycleFsm implements Startable {
*/
public synchronized void stop(@NonNull PolicyController controller) {
logger.info("lifecycle event: stop controller: {}", controller.getName());
- for (ToscaPolicyTypeIdentifier id : controller.getPolicyTypes()) {
- if (!policyTypesMap.containsKey(id)) {
- continue;
- }
- PolicyTypeDroolsController ptDroolsController = (PolicyTypeDroolsController) policyTypesMap.get(id);
- ptDroolsController.remove(controller);
- if (ptDroolsController.controllers().isEmpty()) {
- policyTypesMap.remove(id);
+
+ List<PolicyTypeDroolsController> opControllers =
+ policyTypesMap.values().stream()
+ .filter(typeController -> typeController instanceof PolicyTypeDroolsController)
+ .map(typeController -> (PolicyTypeDroolsController) typeController)
+ .filter(opController -> opController.getControllers().containsKey(controller.getName()))
+ .collect(Collectors.toList());
+
+ for (PolicyTypeDroolsController opController : opControllers) {
+ opController.remove(controller);
+ if (opController.controllers().isEmpty()) {
+ policyTypesMap.remove(opController.getPolicyType());
+ logger.info("policy-type {} removed", opController.getPolicyType());
}
}
}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsController.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsController.java
index 2772d854..8dfbf2f3 100644
--- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsController.java
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsController.java
@@ -52,6 +52,7 @@ public class PolicyTypeDroolsController implements PolicyTypeController {
private static final Logger logger = LoggerFactory.getLogger(PolicyTypeController.class);
+ @Getter
protected final Map<String, PolicyController> controllers = new ConcurrentHashMap<>();
@Getter
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 8255c027..e74b2895 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
@@ -84,14 +84,23 @@ public class PolicyTypeNativeDroolsController implements PolicyTypeController {
PolicyController controller;
try {
- controller = PolicyEngineConstants.getManager()
- .createPolicyController(controllerConfig.getControllerName(), controllerProps);
+ controller =
+ PolicyEngineConstants.getManager()
+ .createPolicyController(controllerConfig.getControllerName(), controllerProps);
} catch (RuntimeException e) {
- logger.warn("failed deploy (cannot create controller) for policy: {}", policy);
+ logger.warn("failed deploy (cannot create controller) for policy: {}", policy, e);
return false;
}
- return controller != null;
+ try {
+ controller.start();
+ } catch (RuntimeException e) {
+ logger.warn("failed deploy (cannot start ontroller) for policy: {}", policy, e);
+ PolicyEngineConstants.getManager().removePolicyController(controller);
+ return false;
+ }
+
+ return true;
}
@Override
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 3e55a10c..5c8f9dc2 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
@@ -21,9 +21,13 @@ package org.onap.policy.drools.server.restful;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
+import java.util.List;
import java.util.Properties;
+import java.util.stream.Collectors;
import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
+import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@@ -33,12 +37,18 @@ import javax.ws.rs.core.Response;
import org.onap.policy.common.endpoints.event.comm.TopicSink;
import org.onap.policy.common.endpoints.event.comm.TopicSource;
import org.onap.policy.common.endpoints.http.server.YamlMessageBodyHandler;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
import org.onap.policy.drools.lifecycle.LifecycleFeature;
import org.onap.policy.drools.lifecycle.PolicyTypeController;
import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
import org.onap.policy.models.pdp.enums.PdpState;
import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* REST Lifecycle Manager.
@@ -50,6 +60,10 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifi
@Api
public class RestLifecycleManager {
+ private static final Logger logger = LoggerFactory.getLogger(RestLifecycleManager.class);
+
+ private static final StandardCoder coder = new StandardCoder();
+
/**
* GET group.
*/
@@ -213,16 +227,23 @@ public class RestLifecycleManager {
*/
@GET
- @Path("policyTypes/{policyType}/{policyVersion}")
+ @Path("policyTypes/{policyType}/{policyTypeVersion}")
@ApiOperation(value = "Entities associated with a policy type",
notes = "Lifecycle policy Types", response = PolicyTypeController.class)
public Response policyType(
- @ApiParam(value = "Policy Type", required = true) @PathParam("policyType") String policyType,
- @ApiParam(value = "Policy Type Version", required = true) @PathParam("policyVersion") String policyVersion) {
+ @ApiParam(value = "Policy Type", required = true)
+ @PathParam("policyType") String policyType,
+ @ApiParam(value = "Policy Type Version", required = true)
+ @PathParam("policyTypeVersion") String policyTypeVersion) {
+ PolicyTypeController typeController =
+ LifecycleFeature.fsm.getPolicyTypesMap()
+ .get(new ToscaPolicyTypeIdentifier(policyType, policyTypeVersion));
+ if (typeController == null) {
+ return Response.status(Response.Status.NOT_FOUND).build();
+ }
+
return Response.status(Response.Status.OK)
- .entity(LifecycleFeature.fsm
- .getPolicyTypesMap()
- .get(new ToscaPolicyTypeIdentifier(policyType, policyVersion)))
+ .entity(typeController)
.build();
}
@@ -232,8 +253,7 @@ public class RestLifecycleManager {
@GET
@Path("policies")
- @ApiOperation(value = "List of tracked policies",
- notes = "Lifecycle Policies", responseContainer = "List")
+ @ApiOperation(value = "List of policies", responseContainer = "List")
public Response policies() {
return Response.status(Response.Status.OK)
.entity(LifecycleFeature.fsm.getPoliciesMap().keySet())
@@ -242,28 +262,160 @@ public class RestLifecycleManager {
}
/**
+ * POST a Policy.
+ */
+
+ @POST
+ @Path("policies")
+ @ApiOperation(value = "Deploy a policy", response = Boolean.class)
+ public Response deployTrackedPolicy(
+ @ApiParam(value = "Tosca Policy", required = true) String policy) {
+
+ ToscaPolicy toscaPolicy = getToscaPolicy(policy);
+ if (toscaPolicy == null) {
+ return Response.status(Response.Status.NOT_ACCEPTABLE).build();
+ }
+
+ PolicyTypeController typeController = getPolicyTypeController(toscaPolicy);
+ if (typeController == null) {
+ return Response.status(Response.Status.NOT_FOUND).build();
+ }
+
+ List<ToscaPolicy> policies =
+ LifecycleFeature.fsm.getPoliciesMap().values().stream().collect(Collectors.toList());
+ policies.add(toscaPolicy);
+ return Response.status(Response.Status.OK)
+ .entity(LifecycleFeature.fsm.update(getPolicyUpdate(policies)))
+ .build();
+ }
+
+ /**
* GET a policy.
*/
@GET
- @Path("policies/{policy}/{policyVersion}")
- @ApiOperation(value = "Lifecycle tracked policy",
- notes = "Lifecycle Tracked Policy", response = ToscaPolicy.class)
+ @Path("policies/{policyName}/{policyVersion}")
+ @ApiOperation(value = "Retrieves a policy", response = ToscaPolicy.class)
public Response policy(
+ @ApiParam(value = "Policy Name", required = true) @PathParam("policyName") String policyName,
+ @ApiParam(value = "Policy Version", required = true) @PathParam("policyVersion") String policyVersion) {
+
+ ToscaPolicy policy;
+ try {
+ policy =
+ LifecycleFeature.fsm.getPoliciesMap().get(new ToscaPolicyIdentifier(policyName, policyVersion));
+ } catch (RuntimeException r) {
+ logger.debug("policy {}:{} has not been found", policyName, policyVersion, r);
+ return Response.status(Response.Status.NOT_FOUND).build();
+ }
+
+ if (policy == null) {
+ return Response.status(Response.Status.NOT_FOUND).build();
+ }
+
+ return Response.status(Response.Status.OK).entity(policy).build();
+ }
+
+ /**
+ * DELETE a policy.
+ */
+
+ @DELETE
+ @Path("policies/{policyName}/{policyVersion}")
+ @ApiOperation(value = "Deletes a Lifecycle tracked policy", response = Boolean.class)
+ public Response undeployPolicy(
@ApiParam(value = "Policy", required = true) @PathParam("policyName") String policyName,
@ApiParam(value = "Policy Version", required = true) @PathParam("policyVersion") String policyVersion) {
- ToscaPolicy policy = LifecycleFeature.fsm
- .getPoliciesMap()
- .get(new ToscaPolicyTypeIdentifier(policyName, policyVersion));
- if (policy != null) {
- return
- Response.status(Response.Status.OK)
- .entity(LifecycleFeature.fsm.getPolicyTypesMap()
- .get(new ToscaPolicyTypeIdentifier(policyName, policyVersion)))
- .build();
+ ToscaPolicy policy;
+ try {
+ policy =
+ LifecycleFeature.fsm.getPoliciesMap().get(new ToscaPolicyIdentifier(policyName, policyVersion));
+ } catch (RuntimeException r) {
+ logger.debug("policy {}:{} has not been found", policyName, policyVersion, r);
+ return Response.status(Response.Status.NOT_FOUND).build();
+ }
+
+ if (policy == null) {
+ return Response.status(Response.Status.NOT_FOUND).build();
+ }
+
+ List<ToscaPolicy> policies =
+ LifecycleFeature.fsm.getPoliciesMap().values().stream().collect(Collectors.toList());
+ policies.removeIf(aPolicy -> policy.getIdentifier().equals(aPolicy.getIdentifier()));
+ return Response.status(Response.Status.OK)
+ .entity(LifecycleFeature.fsm.update(getPolicyUpdate(policies)))
+ .build();
+ }
+
+ /**
+ * List of policies individual Operations supported.
+ */
+
+ @GET
+ @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();
+ }
+
+ /**
+ * POST a deployment operation on a policy.
+ */
+
+ @POST
+ @Path("policies/operations/deployment")
+ @ApiOperation(value = "Deploys a policy", notes = "Deploys a policy", response = Boolean.class)
+ public Response deployOperation(@ApiParam(value = "Tosca Policy", required = true) String policy) {
+ return deployUndeployOperation(policy, true);
+ }
+
+ /**
+ * POST an undeployment operation on a policy.
+ */
+
+ @POST
+ @Path("policies/operations/undeployment")
+ @ApiOperation(value = "Undeploys a policy", response = Boolean.class)
+ public Response undeployOperation(@ApiParam(value = "Tosca Policy", required = true) String policy) {
+ return deployUndeployOperation(policy, false);
+ }
+
+ private Response deployUndeployOperation(String policy, boolean deploy) {
+ ToscaPolicy toscaPolicy = getToscaPolicy(policy);
+ if (toscaPolicy == null) {
+ return Response.status(Response.Status.NOT_ACCEPTABLE).build();
+ }
+
+ PolicyTypeController typeController = getPolicyTypeController(toscaPolicy);
+ if (typeController == null) {
+ return Response.status(Response.Status.NOT_FOUND).build();
+ }
+
+ return Response.status(Response.Status.OK)
+ .entity((deploy) ? typeController.deploy(toscaPolicy) : typeController.undeploy(toscaPolicy))
+ .build();
+ }
+
+ private ToscaPolicy getToscaPolicy(String policy) {
+ try {
+ return coder.decode(policy, ToscaPolicy.class);
+ } catch (CoderException | RuntimeException e) {
+ return null;
}
+ }
+
+ private PolicyTypeController getPolicyTypeController(ToscaPolicy policy) {
+ return LifecycleFeature.fsm.getPolicyTypesMap().get(policy.getTypeIdentifier());
+ }
- return Response.status(Response.Status.NOT_FOUND).build();
+ private PdpUpdate getPolicyUpdate(List<ToscaPolicy> policies) {
+ PdpUpdate update = new PdpUpdate();
+ update.setName(LifecycleFeature.fsm.getName());
+ update.setPdpGroup(LifecycleFeature.fsm.getGroup());
+ update.setPdpSubgroup(LifecycleFeature.fsm.getSubgroup());
+ update.setPolicies(policies);
+ return update;
}
+
}
diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java
index 9b673dd5..1e9f1c66 100644
--- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java
+++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java
@@ -69,12 +69,7 @@ public class ControllerSupport {
;
}
- ReleaseId coordinates =
- KieUtils.installArtifact(Paths.get(JUNIT_KMODULE_PATH).toFile(),
- Paths.get(JUNIT_KMODULE_POM_PATH).toFile(),
- JUNIT_KJAR_DRL_PATH,
- Paths.get(JUNIT_KMODULE_DRL_PATH).toFile());
-
+ ReleaseId coordinates = installArtifact();
Properties controllerProps = new Properties();
controllerProps.put(DroolsPropertyConstants.PROPERTY_CONTROLLER_NAME, name);
@@ -87,6 +82,17 @@ public class ControllerSupport {
}
/**
+ * install artifact.
+ */
+ public ReleaseId installArtifact() throws IOException {
+ return
+ KieUtils.installArtifact(Paths.get(JUNIT_KMODULE_PATH).toFile(),
+ Paths.get(JUNIT_KMODULE_POM_PATH).toFile(),
+ JUNIT_KJAR_DRL_PATH,
+ Paths.get(JUNIT_KMODULE_DRL_PATH).toFile());
+ }
+
+ /**
* Destroy the echo controller.
*/
public void destroyController() {
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 511fcc9b..2222399b 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
@@ -18,43 +18,87 @@
package org.onap.policy.drools.server.restful;
+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.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
+import org.apache.commons.lang3.StringUtils;
import org.junit.After;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
+import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicFactories;
import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams;
import org.onap.policy.common.endpoints.http.client.HttpClient;
import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
import org.onap.policy.common.endpoints.http.server.HttpServletServer;
import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance;
+import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
import org.onap.policy.common.utils.network.NetworkUtil;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.drools.lifecycle.ControllerSupport;
import org.onap.policy.drools.lifecycle.LifecycleFeature;
+import org.onap.policy.drools.lifecycle.LifecycleFsm;
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.enums.PdpState;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
/**
* REST Lifecycle Manager Test.
*/
public class RestLifecycleManagerTest {
+ // Native Drools Policy
+ private static final String EXAMPLE_NATIVE_CONTROLLER_POLICY_NAME = "example.controller";
+ private static final String EXAMPLE_NATIVE_CONTROLLER_POLICY_JSON =
+ "src/test/resources/tosca-policy-native-controller-example.json";
+
+ private static final String EXAMPLE_NATIVE_ARTIFACT_POLICY_NAME = "example.artifact";
+ private static final String EXAMPLE_NATIVE_ARTIFACT_POLICY_JSON =
+ "src/test/resources/tosca-policy-native-artifact-example.json";
+
+ private static final String OP_POLICY_NAME_VCPE = "operational.restart";
+ private static final String VCPE_OPERATIONAL_DROOLS_POLICY_JSON =
+ "policies/vCPE.policy.operational.input.tosca.json";
+
+ private static StandardCoder coder = new StandardCoder();
+ private static ControllerSupport controllerSupport = new ControllerSupport("lifecycle");
+
+ private LifecycleFsm fsm;
+ private HttpClient client;
+
/**
* Set up.
*/
@Before
public void setUp() throws Exception {
+ SystemPersistenceConstants.getManager().setConfigurationDir("target/test-classes");
+ fsm = newFsmInstance();
+
+ LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "INFO");
+ LoggerUtil.setLevel("org.onap.policy.common.endpoints", "WARN");
+ LoggerUtil.setLevel("org.onap.policy.drools", "INFO");
+
HttpServletServerFactoryInstance.getServerFactory().destroy();
HttpClientFactoryInstance.getClientFactory().destroy();
-
- SystemPersistenceConstants.getManager().setConfigurationDir("target/test-classes");
+ PolicyControllerConstants.getFactory().destroy();
HttpClientFactoryInstance.getClientFactory().build(
BusTopicParams.builder()
@@ -70,8 +114,16 @@ public class RestLifecycleManagerTest {
server.addServletClass("/*", RestLifecycleManager.class.getName());
server.waitedStart(5000L);
- Assert.assertTrue(NetworkUtil.isTcpPortOpen("localhost", 8765, 5, 10000L));
+ assertTrue(NetworkUtil.isTcpPortOpen("localhost", 8765, 5, 10000L));
+
+ controllerSupport.installArtifact();
+ 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);
+
+ client = HttpClientFactoryInstance.getClientFactory().get("lifecycle");
}
/**
@@ -79,88 +131,287 @@ public class RestLifecycleManagerTest {
*/
@After
public void tearDown() {
- HttpServletServerFactoryInstance.getServerFactory().destroy();
+ fsm.shutdown();
+
+ NoopTopicFactories.getSourceFactory().destroy();
+ NoopTopicFactories.getSinkFactory().destroy();
+
HttpClientFactoryInstance.getClientFactory().destroy();
+ HttpServletServerFactoryInstance.getServerFactory().destroy();
+
+ PolicyControllerConstants.getFactory().destroy();
+ SystemPersistenceConstants.getManager().setConfigurationDir(null);
}
@Test
- public void testFsm() {
+ public void testMultiPolicyFlow() throws IOException, CoderException {
+ /* group assignments */
- HttpClient client = HttpClientFactoryInstance.getClientFactory().get("lifecycle");
- Response response;
+ group();
+ subgroup();
- /* group */
+ /* other resources */
- response = client.put("group/GG", Entity.json(""), Collections.emptyMap());
- assertEquals(Status.OK.getStatusCode(), response.getStatus());
- assertEquals("GG", HttpClient.getBody(response, String.class));
+ properties();
+ topics();
- response = HttpClientFactoryInstance.getClientFactory().get("lifecycle").get("group");
- assertEquals(Status.OK.getStatusCode(), response.getStatus());
- assertEquals(LifecycleFeature.fsm.getGroup(), HttpClient.getBody(response, String.class));
+ /* status interval */
- /* subgroup */
+ status();
- response = client.put("subgroup/YY", Entity.json(""), Collections.emptyMap());
- assertEquals(Status.OK.getStatusCode(), response.getStatus());
- assertEquals("YY", HttpClient.getBody(response, String.class));
+ /* start up configuration */
- response = client.get("subgroup");
- assertEquals(Status.OK.getStatusCode(), response.getStatus());
- assertEquals(LifecycleFeature.fsm.getSubgroup(), HttpClient.getBody(response, String.class));
+ resourceLists("policyTypes", 2);
+ get("policyTypes/onap.policies.native.drools.Artifact/1.0.0", Status.OK.getStatusCode());
+ get("policyTypes/onap.policies.native.drools.Controller/1.0.0", Status.OK.getStatusCode());
+ get("policyTypes/onap.policies.controlloop.Operational/1.0.0", Status.NOT_FOUND.getStatusCode());
+ get("policyTypes/onap.policies.controlloop.operational.common.Drools/1.0.0", Status.NOT_FOUND.getStatusCode());
- /* properties */
+ resourceLists("policies", 0);
+ get("policies/example.controller/1.0.0", Status.NOT_FOUND.getStatusCode());
+ get("policies/example.artifact/1.0.0", Status.NOT_FOUND.getStatusCode());
- response = client.get("properties");
- assertEquals(Status.OK.getStatusCode(), response.getStatus());
- assertEquals(LifecycleFeature.fsm.getProperties(), HttpClient.getBody(response, Properties.class));
+ /* start lifecycle */
- /* state (disallowed state change as has not been started) */
+ assertTrue(fsm.start());
- response = client.put("state/PASSIVE", Entity.json(""), Collections.emptyMap());
- assertEquals(Status.OK.getStatusCode(), response.getStatus());
- assertEquals(Boolean.FALSE, HttpClient.getBody(response, Boolean.class));
+ booleanPut("state/ACTIVE", "", Status.OK.getStatusCode(), Boolean.TRUE);
+ assertEquals(PdpState.ACTIVE,
+ HttpClient.getBody(get("state", Status.OK.getStatusCode()), PdpState.class));
- response = client.get("state");
- assertEquals(Status.OK.getStatusCode(), response.getStatus());
- assertEquals(PdpState.TERMINATED, HttpClient.getBody(response, PdpState.class));
+ /* add native controller policy */
- /* topics */
+ ToscaPolicy nativeControllerPolicy =
+ getPolicyFromFile(EXAMPLE_NATIVE_CONTROLLER_POLICY_JSON, EXAMPLE_NATIVE_CONTROLLER_POLICY_NAME);
+ booleanPost("policies", toString(nativeControllerPolicy), Status.OK.getStatusCode(), Boolean.TRUE);
- assertEquals(Status.OK.getStatusCode(), client.get("topic/source").getStatus());
- assertEquals(Status.OK.getStatusCode(), client.get("topic/sink").getStatus());
+ assertTrue(PolicyControllerConstants.getFactory().get("lifecycle").isAlive());
+ assertFalse(PolicyControllerConstants.getFactory().get("lifecycle").getDrools().isBrained());
+ assertFalse(PolicyControllerConstants.getFactory().get("lifecycle").getDrools().isAlive());
- /* status interval */
+ get("policyTypes/onap.policies.controlloop.Operational/1.0.0", Status.NOT_FOUND.getStatusCode());
+ get("policyTypes/onap.policies.controlloop.operational.common.Drools/1.0.0", Status.NOT_FOUND.getStatusCode());
+
+ resourceLists("policies", 1);
+ get("policies/example.controller/1.0.0", Status.OK.getStatusCode());
+
+ /* add native artifact policy */
+
+ ToscaPolicy nativeArtifactPolicy =
+ getPolicyFromFile(EXAMPLE_NATIVE_ARTIFACT_POLICY_JSON, EXAMPLE_NATIVE_ARTIFACT_POLICY_NAME);
+ booleanPost("policies", toString(nativeArtifactPolicy), Status.OK.getStatusCode(), Boolean.TRUE);
+
+ assertTrue(PolicyControllerConstants.getFactory().get("lifecycle").isAlive());
+ assertTrue(PolicyControllerConstants.getFactory().get("lifecycle").getDrools().isBrained());
+ assertTrue(PolicyControllerConstants.getFactory().get("lifecycle").getDrools().isAlive());
+
+ /* verify new supported operational policy types */
+
+ resourceLists("policyTypes", 5);
+ get("policyTypes/onap.policies.native.drools.Artifact/1.0.0", Status.OK.getStatusCode());
+ get("policyTypes/onap.policies.native.drools.Controller/1.0.0", Status.OK.getStatusCode());
+ get("policyTypes/onap.policies.controlloop.Operational/1.0.0", Status.OK.getStatusCode());
+ get("policyTypes/onap.policies.controlloop.operational.common.Drools/1.0.0", Status.OK.getStatusCode());
+ get("policyTypes/onap.policies.type1.type2/1.0.0", Status.OK.getStatusCode());
+
+ /* verify controller and artifact policies */
+
+ resourceLists("policies", 2);
+ get("policies/example.controller/1.0.0", Status.OK.getStatusCode());
+ get("policies/example.artifact/1.0.0", Status.OK.getStatusCode());
+
+ /* add tosca compliant operational policy */
+
+ ToscaPolicy opPolicy = getExamplesPolicy(VCPE_OPERATIONAL_DROOLS_POLICY_JSON, OP_POLICY_NAME_VCPE);
+ opPolicy.getProperties().put("controllerName", "lifecycle");
+ if (StringUtils.isBlank(opPolicy.getName())) {
+ opPolicy.setName(opPolicy.getMetadata().get("policy-id"));
+ }
+
+ booleanPost("policies", toString(opPolicy), Status.OK.getStatusCode(), Boolean.TRUE);
+ assertTrue(PolicyControllerConstants.getFactory().get("lifecycle").isAlive());
+ assertTrue(PolicyControllerConstants.getFactory().get("lifecycle").getDrools().isBrained());
+ assertEquals(1,
+ PolicyControllerConstants
+ .getFactory().get("lifecycle").getDrools().facts("junits", ToscaPolicy.class) .size());
+
+ resourceLists("policies", 3);
+ get("policies/" + opPolicy.getName() + "/" + opPolicy.getVersion(), Status.OK.getStatusCode());
+ get("policies/example.controller/1.0.0", Status.OK.getStatusCode());
+ get("policies/example.artifact/1.0.0", Status.OK.getStatusCode());
+
+ booleanDelete("policies/" + opPolicy.getName() + "/" + opPolicy.getVersion(),
+ Status.OK.getStatusCode(), Boolean.TRUE);
+ assertEquals(0,
+ PolicyControllerConstants
+ .getFactory().get("lifecycle").getDrools().facts("junits", ToscaPolicy.class) .size());
- response = client.put("status/interval/1000", Entity.json(""), Collections.emptyMap());
+ resourceLists("policies", 2);
+ get("policies/" + opPolicy.getName() + "/" + opPolicy.getVersion(), Status.NOT_FOUND.getStatusCode());
+ get("policies/example.controller/1.0.0", Status.OK.getStatusCode());
+ get("policies/example.artifact/1.0.0", Status.OK.getStatusCode());
+
+ /* individual deploy/undeploy operations */
+
+ resourceLists("policies/operations", 2);
+
+ booleanPost("policies/operations/deployment", toString(opPolicy), Status.OK.getStatusCode(), Boolean.TRUE);
+ assertEquals(1,
+ PolicyControllerConstants
+ .getFactory().get("lifecycle").getDrools().facts("junits", ToscaPolicy.class) .size());
+
+ resourceLists("policies", 2);
+ get("policies/" + opPolicy.getName() + "/" + opPolicy.getVersion(), Status.NOT_FOUND.getStatusCode());
+ get("policies/example.controller/1.0.0", Status.OK.getStatusCode());
+ get("policies/example.artifact/1.0.0", Status.OK.getStatusCode());
+
+ booleanPost(
+ "policies/operations/undeployment", toString(opPolicy), Status.OK.getStatusCode(), Boolean.TRUE);
+ assertEquals(0,
+ PolicyControllerConstants
+ .getFactory().get("lifecycle").getDrools().facts("junits", ToscaPolicy.class) .size());
+
+ resourceLists("policies", 2);
+ get("policies/" + opPolicy.getName() + "/" + opPolicy.getVersion(), Status.NOT_FOUND.getStatusCode());
+ get("policies/example.controller/1.0.0", Status.OK.getStatusCode());
+ get("policies/example.artifact/1.0.0", Status.OK.getStatusCode());
+
+ /* delete native artifact policy */
+
+ booleanDelete("policies/example.artifact/1.0.0", Status.OK.getStatusCode(), Boolean.TRUE);
+ assertTrue(PolicyControllerConstants.getFactory().get("lifecycle").isAlive());
+ assertFalse(PolicyControllerConstants.getFactory().get("lifecycle").getDrools().isBrained());
+
+ resourceLists("policyTypes", 2);
+ get("policyTypes/onap.policies.native.drools.Artifact/1.0.0", Status.OK.getStatusCode());
+ get("policyTypes/onap.policies.native.drools.Controller/1.0.0", Status.OK.getStatusCode());
+ get("policyTypes/onap.policies.controlloop.Operational/1.0.0", Status.NOT_FOUND.getStatusCode());
+ get("policyTypes/onap.policies.controlloop.operational.common.Drools/1.0.0", Status.NOT_FOUND.getStatusCode());
+ get("policyTypes/onap.policies.type1.type2/1.0.0", Status.NOT_FOUND.getStatusCode());
+
+ resourceLists("policies", 1);
+ get("policies/" + opPolicy.getName() + "/" + opPolicy.getVersion(), Status.NOT_FOUND.getStatusCode());
+ get("policies/example.artifact/1.0.0", Status.NOT_FOUND.getStatusCode());
+ get("policies/example.controller/1.0.0", Status.OK.getStatusCode());
+
+ /* delete native controller policy */
+
+ booleanDelete("policies/example.controller/1.0.0", Status.OK.getStatusCode(), Boolean.TRUE);
+
+ resourceLists("policyTypes", 2);
+ get("policyTypes/onap.policies.native.drools.Artifact/1.0.0", Status.OK.getStatusCode());
+ get("policyTypes/onap.policies.native.drools.Controller/1.0.0", Status.OK.getStatusCode());
+ get("policyTypes/onap.policies.controlloop.Operational/1.0.0", Status.NOT_FOUND.getStatusCode());
+ get("policyTypes/onap.policies.controlloop.operational.common.Drools/1.0.0", Status.NOT_FOUND.getStatusCode());
+ get("policyTypes/onap.policies.type1.type2/1.0.0", Status.NOT_FOUND.getStatusCode());
+
+ resourceLists("policies", 0);
+ get("policies/" + opPolicy.getName() + "/" + opPolicy.getVersion(), Status.NOT_FOUND.getStatusCode());
+ get("policies/example.artifact/1.0.0", Status.NOT_FOUND.getStatusCode());
+ get("policies/example.controller/1.0.0", Status.NOT_FOUND.getStatusCode());
+
+ assertThatIllegalArgumentException().isThrownBy(() -> PolicyControllerConstants.getFactory().get("lifecycle"));
+ }
+
+ private Response get(String contextPath, int statusCode) {
+ Response response = client.get(contextPath);
+ assertEquals(statusCode, response.getStatus());
+ return response;
+ }
+
+ private void booleanResponse(Response response, int statusCode, Boolean bool) {
+ assertEquals(statusCode, response.getStatus());
+ assertEquals(bool, HttpClient.getBody(response, Boolean.class));
+ }
+
+ private void booleanPut(String contextPath, String body, int statusCode, Boolean bool) {
+ Response response = client.put(contextPath, Entity.json(body), Collections.emptyMap());
+ booleanResponse(response, statusCode, bool);
+ }
+
+ 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);
+ }
+
+ private void booleanDelete(String contextPath, int statusCode, Boolean bool) {
+ Response response = client.delete(contextPath, Collections.emptyMap());
+ booleanResponse(response, statusCode, bool);
+ }
+
+ private void resourceLists(String resource, int size) {
+ Response response = client.get(resource);
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+ assertEquals(size, HttpClient.getBody(response, List.class).size());
+ }
+
+ private void status() {
+ Response response = client.put("status/interval/240", Entity.json(""), Collections.emptyMap());
assertEquals(Status.OK.getStatusCode(), response.getStatus());
- assertEquals(Long.valueOf(1000L), HttpClient.getBody(response, Long.class));
+ assertEquals(Long.valueOf(240L), HttpClient.getBody(response, Long.class));
response = client.get("status/interval");
assertEquals(Status.OK.getStatusCode(), response.getStatus());
- assertEquals(Long.valueOf(1000L), HttpClient.getBody(response, Long.class));
+ assertEquals(Long.valueOf(240L), HttpClient.getBody(response, Long.class));
+ }
- /* policy types */
+ private void topics() {
+ assertEquals(Status.OK.getStatusCode(), client.get("topic/source").getStatus());
+ assertEquals(Status.OK.getStatusCode(), client.get("topic/sink").getStatus());
+ }
- response = client.get("policyTypes");
+ private void properties() {
+ Response response = client.get("properties");
assertEquals(Status.OK.getStatusCode(), response.getStatus());
- assertEquals(2, HttpClient.getBody(response, List.class).size());
+ assertEquals(fsm.getProperties(), HttpClient.getBody(response, Properties.class));
+ }
- response = client.get("policyTypes/onap.policies.native.drools.Artifact/1.0.0");
+ private void subgroup() {
+ Response response = client.put("subgroup/YY", Entity.json(""), Collections.emptyMap());
assertEquals(Status.OK.getStatusCode(), response.getStatus());
- assertNotNull(HttpClient.getBody(response, String.class));
+ assertEquals("YY", HttpClient.getBody(response, String.class));
- response = client.get("policyTypes/onap.policies.native.drools.Controller/1.0.0");
+ response = client.get("subgroup");
assertEquals(Status.OK.getStatusCode(), response.getStatus());
- assertNotNull(HttpClient.getBody(response, String.class));
+ assertEquals("YY", HttpClient.getBody(response, String.class));
+ }
- /* policies */
+ private void group() {
+ Response response = client.put("group/GG", Entity.json(""), Collections.emptyMap());
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+ assertEquals("GG", HttpClient.getBody(response, String.class));
- response = client.get("policies");
+ response = HttpClientFactoryInstance.getClientFactory().get("lifecycle").get("group");
assertEquals(Status.OK.getStatusCode(), response.getStatus());
- assertEquals(0, HttpClient.getBody(response, List.class).size());
+ assertEquals("GG", HttpClient.getBody(response, String.class));
+ }
+
+ private LifecycleFsm newFsmInstance() throws NoSuchFieldException, IllegalAccessException {
+ Field fsmField = LifecycleFeature.class.getDeclaredField("fsm");
+ fsmField.setAccessible(true);
+
+ Field modifiers = Field.class.getDeclaredField("modifiers");
+ modifiers.setAccessible(true);
+ modifiers.setInt(fsmField, fsmField.getModifiers() & ~Modifier.FINAL );
+
+ LifecycleFsm fsm = new LifecycleFsm();
+ fsmField.set(null, fsm);
+ return fsm;
+ }
+
+ protected ToscaPolicy getPolicyFromFile(String filePath, String policyName) throws CoderException, IOException {
+ String policyJson = Files.readString(Paths.get(filePath));
+ ToscaServiceTemplate serviceTemplate = coder.decode(policyJson, ToscaServiceTemplate.class);
+ return serviceTemplate.getToscaTopologyTemplate().getPolicies().get(0).get(policyName);
+ }
+
+ protected String toString(ToscaPolicy policy) throws CoderException {
+ return coder.encode(policy);
+ }
- response = client.get("policies/onap.policies.controlloop.Operational");
- assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus());
+ 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);
}
}
diff --git a/feature-lifecycle/src/test/resources/lifecycle.kmodule b/feature-lifecycle/src/test/resources/lifecycle.kmodule
index 8bf1ed5a..2e5235c7 100644
--- a/feature-lifecycle/src/test/resources/lifecycle.kmodule
+++ b/feature-lifecycle/src/test/resources/lifecycle.kmodule
@@ -20,7 +20,10 @@
-->
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
- <kbase name="onap.policies.type1.type2">
+ <kbase name="onap.policies.controlloop.Operational" default="false" equalsBehavior="equality"/>
+ <kbase name="onap.policies.controlloop.operational.common.Drools" default="false" equalsBehavior="equality"
+ includes="onap.policies.controlloop.Operational"/>
+ <kbase name="onap.policies.type1.type2" includes="onap.policies.controlloop.operational.common.Drools">
<ksession name="junits" />
</kbase>
</kmodule>
diff --git a/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java b/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java
index 49287786..d11863f0 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java
@@ -108,7 +108,8 @@ public interface PolicyControllerFeatureApi extends OrderedService {
* of the operation preventing the invocation of
* lower priority features. False, otherwise.
*/
- default boolean beforePatch(PolicyController controller, DroolsConfiguration configuration) {
+ default boolean beforePatch(
+ PolicyController controller, DroolsConfiguration oldConfiguration, DroolsConfiguration newConfiguration) {
return false;
}
@@ -119,7 +120,9 @@ public interface PolicyControllerFeatureApi extends OrderedService {
* of the operation preventing the invocation of
* lower priority features. False, otherwise.
*/
- default boolean afterPatch(PolicyController controller, boolean success) {
+ default boolean afterPatch(
+ PolicyController controller, DroolsConfiguration oldConfiguration,
+ DroolsConfiguration newConfiguration, boolean success) {
return false;
}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java b/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java
index b80f4c86..0c12dbcb 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java
@@ -227,7 +227,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
}
if (FeatureApiUtils.apply(getProviders(),
- feature -> feature.beforePatch(this, newDroolsConfiguration),
+ feature -> feature.beforePatch(this, oldDroolsConfiguration, newDroolsConfiguration),
(feature, ex) -> logger.error("{}: feature {} before-patch failure because of {}", this,
feature.getClass().getName(), ex.getMessage(), ex))) {
return true;
@@ -268,7 +268,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen
boolean finalSuccess = success;
FeatureApiUtils.apply(getProviders(),
- feature -> feature.afterPatch(this, finalSuccess),
+ feature -> feature.afterPatch(this, oldDroolsConfiguration, newDroolsConfiguration, finalSuccess),
(feature, ex) -> logger.error("{}: feature {} after-patch failure because of {}", this,
feature.getClass().getName(), ex.getMessage(), ex));