deploy and undeploy as audits.
Change-Id: Iea1766d5d8075394e1dccc109f4477bd2c270c36
Issue-ID: POLICY-1624
Signed-off-by: jhh <jorge.hernandez-herrero@att.com>
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 b99953e..97f3574 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
@@ -283,6 +283,10 @@
policiesMap.put(policy.getIdentifier(), policy);
}
+ protected void undeployedPolicyAction(@NonNull ToscaPolicy policy) {
+ policiesMap.remove(policy.getIdentifier());
+ }
+
/* ** Action Helpers ** */
private boolean startIo() {
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java
index d481b8b..38ea091 100644
--- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java
@@ -61,8 +61,6 @@
protected boolean deployPolicy(@NonNull PolicyController controller, @NonNull ToscaPolicy policy) {
logger.info("{}: deploy {} into {}", this, policy.getIdentifier(), controller.getName());
- // TODO: This is the latest version - retract policy with same id but different version
-
if (!controller.offer(policy)) {
return false;
}
@@ -75,8 +73,12 @@
protected boolean undeployPolicy(@NonNull PolicyController controller, @NonNull ToscaPolicy policy) {
logger.info("{}: undeploy {} from {}", this, policy.getIdentifier(), controller.getName());
- // TODO: retract policy.
+ if (!controller.getDrools().delete(policy)) {
+ logger.warn("Policy {}:{}:{}:{} was not deployed.",
+ policy.getType(), policy.getTypeVersion(), policy.getName(), policy.getVersion());
+ }
+ fsm.undeployedPolicyAction(policy);
return true;
}
}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java
index 405dbeb..ed200ea 100644
--- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java
@@ -134,8 +134,15 @@
return true;
}
- boolean success = deployPolicies(policies);
- return undeployPolicies(policies) && success;
+ // Note that PAP sends the list of all ACTIVE policies with every
+ // UPDATE message. First, we will undeploy all policies that are
+ // running but are not present in this list. This will include
+ // policies that are overridden by a different version. Second,
+ // we will deploy those policies that are not installed but
+ // resent in this list.
+
+ boolean success = undeployPolicies(policies);
+ return deployPolicies(policies) && success;
}
protected boolean deployPolicies(List<ToscaPolicy> policies) {
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 1beee55..d5ac423 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
@@ -24,7 +24,6 @@
import java.nio.file.Paths;
import java.util.List;
import java.util.Properties;
-import java.util.stream.Collectors;
import lombok.Getter;
import lombok.NonNull;
import org.kie.api.builder.ReleaseId;
@@ -103,10 +102,6 @@
public <T> List<T> getFacts(Class<T> clazz) {
return PolicyController.factory.get(name)
.getDrools()
- .facts(SESSION_NAME, clazz.getCanonicalName(), false)
- .stream()
- .filter(clazz::isInstance)
- .map(clazz::cast)
- .collect(Collectors.toList());
+ .facts(SESSION_NAME, clazz);
}
}
diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java
index 3200642..b8afd20 100644
--- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java
+++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java
@@ -33,6 +33,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
@@ -73,6 +74,7 @@
change.setName(fsm.getName());
fsm.source.offer(new StandardCoder().encode(change));
+ controllerSupport.getController().start();
}
@Test
@@ -197,7 +199,6 @@
long interval = 2 * originalInterval;
update.setPdpHeartbeatIntervalMs(interval * 1000L);
- controllerSupport.getController().start();
fsm.start(controllerSupport.getController());
assertTrue(fsm.update(update));
@@ -207,20 +208,83 @@
assertEquals("Z", fsm.getGroup());
assertEquals("z", fsm.getSubgroup());
- String rawPolicy =
- new String(Files.readAllBytes(Paths.get("src/test/resources/tosca-policy.json")));
- ToscaPolicy toscaPolicy = new StandardCoder().decode(rawPolicy, ToscaPolicy.class);
- update.setPolicies(Arrays.asList(toscaPolicy));
+ String restartV1 =
+ new String(Files.readAllBytes(Paths.get("src/test/resources/tosca-policy-operational-restart.json")));
+ ToscaPolicy toscaPolicyRestartV1 = new StandardCoder().decode(restartV1, ToscaPolicy.class);
+ update.setPolicies(Arrays.asList(toscaPolicyRestartV1));
+
+ // update with an operational.restart policy
assertTrue(fsm.update(update));
assertEquals(1, fsm.policyTypesMap.size());
List<ToscaPolicy> factPolicies = controllerSupport.getFacts(ToscaPolicy.class);
assertEquals(1, factPolicies.size());
- assertEquals(toscaPolicy, factPolicies.get(0));
+ assertEquals(toscaPolicyRestartV1, factPolicies.get(0));
assertEquals(1, fsm.policiesMap.size());
- controllerSupport.getController().stop();
+ // dup update with the same operational.restart policy - nothing changes
+
+ assertTrue(fsm.update(update));
+ assertEquals(1, fsm.policyTypesMap.size());
+
+ factPolicies = controllerSupport.getFacts(ToscaPolicy.class);
+ assertEquals(1, factPolicies.size());
+ assertEquals(toscaPolicyRestartV1, factPolicies.get(0));
+ assertEquals(1, fsm.policiesMap.size());
+
+ // undeploy operational.restart policy
+
+ update.setPolicies(Collections.emptyList());
+ assertTrue(fsm.update(update));
+ assertEquals(1, fsm.policyTypesMap.size());
+
+ factPolicies = controllerSupport.getFacts(ToscaPolicy.class);
+ assertEquals(0, factPolicies.size());
+ assertEquals(0, fsm.policiesMap.size());
+
+ // redeploy operational.restart policy
+
+ update.setPolicies(Arrays.asList(toscaPolicyRestartV1));
+ assertTrue(fsm.update(update));
+ assertEquals(1, fsm.policyTypesMap.size());
+
+ factPolicies = controllerSupport.getFacts(ToscaPolicy.class);
+ assertEquals(1, factPolicies.size());
+ assertEquals(toscaPolicyRestartV1, factPolicies.get(0));
+ assertEquals(1, fsm.policiesMap.size());
+
+ // deploy a new version of the operational.restart policy
+
+ String restartV2 =
+ new String(Files.readAllBytes(Paths.get("src/test/resources/tosca-policy-operational-restart.v2.json")));
+ ToscaPolicy toscaPolicyRestartV2 = new StandardCoder().decode(restartV2, ToscaPolicy.class);
+ update.setPolicies(Arrays.asList(toscaPolicyRestartV2));
+ assertTrue(fsm.update(update));
+ assertEquals(1, fsm.policyTypesMap.size());
+
+ factPolicies = controllerSupport.getFacts(ToscaPolicy.class);
+ assertEquals(1, factPolicies.size());
+ assertNotEquals(toscaPolicyRestartV1, factPolicies.get(0));
+ assertEquals(toscaPolicyRestartV2, factPolicies.get(0));
+ assertEquals(1, fsm.policiesMap.size());
+
+ // deploy another policy : firewall
+
+ String firewall =
+ new String(Files.readAllBytes(Paths.get("src/test/resources/tosca-policy-operational-firewall.json")));
+ ToscaPolicy toscaPolicyFirewall = new StandardCoder().decode(firewall, ToscaPolicy.class);
+ update.setPolicies(Arrays.asList(toscaPolicyRestartV2, toscaPolicyFirewall));
+ assertTrue(fsm.update(update));
+ assertEquals(1, fsm.policyTypesMap.size());
+
+ factPolicies = controllerSupport.getFacts(ToscaPolicy.class);
+ assertEquals(2, factPolicies.size());
+ assertTrue(factPolicies.stream().noneMatch((ff) -> Objects.equals(toscaPolicyRestartV1, ff)));
+ assertTrue(factPolicies.stream().anyMatch((ff) -> Objects.equals(toscaPolicyRestartV2, ff)));
+ assertTrue(factPolicies.stream().anyMatch((ff) -> Objects.equals(toscaPolicyFirewall, ff)));
+ assertEquals(2, fsm.policiesMap.size());
+
fsm.shutdown();
}
}
diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java
index 100bcef..775dc8b 100644
--- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java
+++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java
@@ -187,7 +187,7 @@
assertBasicPassive();
String rawPolicy =
- new String(Files.readAllBytes(Paths.get("src/test/resources/tosca-policy.json")));
+ new String(Files.readAllBytes(Paths.get("src/test/resources/tosca-policy-operational-restart.json")));
ToscaPolicy toscaPolicy = new StandardCoder().decode(rawPolicy, ToscaPolicy.class);
update.setPolicies(Arrays.asList(toscaPolicy));
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 d7bb6d7..6da9dc1 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
@@ -41,7 +41,7 @@
public static void setUp() throws IOException {
LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "INFO");
LoggerUtil.setLevel("org.onap.policy.common.endpoints", "WARN");
- LoggerUtil.setLevel("org.onap.policy.drools", "WARN");
+ LoggerUtil.setLevel("org.onap.policy.drools", "INFO");
SystemPersistence.manager.setConfigurationDir("src/test/resources");
controllerSupport.createController();
}
diff --git a/feature-lifecycle/src/test/resources/tosca-policy-operational-firewall.json b/feature-lifecycle/src/test/resources/tosca-policy-operational-firewall.json
new file mode 100644
index 0000000..7bfb16b
--- /dev/null
+++ b/feature-lifecycle/src/test/resources/tosca-policy-operational-firewall.json
@@ -0,0 +1,9 @@
+{
+ "type": "onap.policies.controlloop.Operational",
+ "typeVersion": "1.0.0",
+ "properties": {
+ "content": "controlLoop%3A%0D%0A++version%3A+2.0.0%0D%0A++controlLoopName%3A+ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a%0D%0A++trigger_policy%3A+unique-policy-id-1-modifyConfig%0D%0A++timeout%3A+1200%0D%0A++abatement%3A+false%0D%0A+%0D%0Apolicies%3A%0D%0A++-+id%3A+unique-policy-id-1-modifyConfig%0D%0A++++name%3A+modify+packet+gen+config%0D%0A++++description%3A%0D%0A++++actor%3A+APPC%0D%0A++++recipe%3A+ModifyConfig%0D%0A++++target%3A%0D%0A++++++%23+TBD+-+Cannot+be+known+until+instantiation+is+done%0D%0A++++++resourceID%3A+Eace933104d443b496b8.nodes.heat.vpg%0D%0A++++++type%3A+VNF%0D%0A++++retry%3A+0%0D%0A++++timeout%3A+300%0D%0A++++success%3A+final_success%0D%0A++++failure%3A+final_failure%0D%0A++++failure_timeout%3A+final_failure_timeout%0D%0A++++failure_retries%3A+final_failure_retries%0D%0A++++failure_exception%3A+final_failure_exception%0D%0A++++failure_guard%3A+final_failure_guard"
+ },
+ "name": "operational.firewall",
+ "version": "1.0.0"
+}
diff --git a/feature-lifecycle/src/test/resources/tosca-policy.json b/feature-lifecycle/src/test/resources/tosca-policy-operational-restart.json
similarity index 100%
rename from feature-lifecycle/src/test/resources/tosca-policy.json
rename to feature-lifecycle/src/test/resources/tosca-policy-operational-restart.json
diff --git a/feature-lifecycle/src/test/resources/tosca-policy-operational-restart.v2.json b/feature-lifecycle/src/test/resources/tosca-policy-operational-restart.v2.json
new file mode 100644
index 0000000..39d1618
--- /dev/null
+++ b/feature-lifecycle/src/test/resources/tosca-policy-operational-restart.v2.json
@@ -0,0 +1,9 @@
+{
+ "type": "onap.policies.controlloop.Operational",
+ "typeVersion": "1.0.0",
+ "properties": {
+ "content": "controlLoop%3A%0A%20%20version%3A%202.0.0%0A%20%20controlLoopName%3A%20ControlLoop-vCPEv2-48f0c2c3-a172-4192-9ae3-052274181b6e%0A%20%20trigger_policy%3A%20unique-policy-id-1-restart%0A%20%20timeout%3A%203600%0A%20%20abatement%3A%20true%0A%20%0Apolicies%3A%0A%20%20-%20id%3A%20unique-policy-id-1-restart%0A%20%20%20%20name%3A%20Restart%20the%20VM%0A%20%20%20%20description%3A%0A%20%20%20%20actor%3A%20APPC%0A%20%20%20%20recipe%3A%20Restart%0A%20%20%20%20target%3A%0A%20%20%20%20%20%20type%3A%20VM%0A%20%20%20%20retry%3A%203%0A%20%20%20%20timeout%3A%201200%0A%20%20%20%20success%3A%20final_success%0A%20%20%20%20failure%3A%20final_failure%0A%20%20%20%20failure_timeout%3A%20final_failure_timeout%0A%20%20%20%20failure_retries%3A%20final_failure_retries%0A%20%20%20%20failure_exception%3A%20final_failure_exception%0A%20%20%20%20failure_guard%3A%20final_failure_guard"
+ },
+ "name": "operational.restart",
+ "version": "2.0.0"
+}
diff --git a/policy-management/lombok.config b/policy-management/lombok.config
new file mode 100644
index 0000000..2384843
--- /dev/null
+++ b/policy-management/lombok.config
@@ -0,0 +1,3 @@
+config.stopBubbling = true
+lombok.addLombokGeneratedAnnotation = true
+lombok.nonNull.exceptionType = IllegalArgumentException
diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsController.java b/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsController.java
index 344725f..78a2f4e 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsController.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsController.java
@@ -22,7 +22,7 @@
import java.util.List;
import java.util.Map;
-
+import org.checkerframework.checker.nullness.qual.NonNull;
import org.onap.policy.common.capabilities.Lockable;
import org.onap.policy.common.capabilities.Startable;
import org.onap.policy.common.endpoints.event.comm.TopicSink;
@@ -215,6 +215,11 @@
List<Object> facts(String sessionName, String className, boolean delete);
/**
+ * Gets facts.
+ */
+ <T> List<T> facts(@NonNull String sessionName, @NonNull Class<T> clazz);
+
+ /**
* gets the facts associated with a query for a give session for a given queried entity.
*
* @param sessionName the session
@@ -228,6 +233,16 @@
Object... queryParams);
/**
+ * Deletes a fact from a session.
+ */
+ <T> boolean delete(@NonNull String sessionName, @NonNull T fact);
+
+ /**
+ * Delete a fact object of type T.
+ */
+ <T> boolean delete(@NonNull T fact);
+
+ /**
* halts and permanently releases all resources.
*
*/
diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java
index 95b053f..a9ab212 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java
@@ -27,7 +27,10 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
import org.apache.commons.collections4.queue.CircularFifoQueue;
+import org.checkerframework.checker.nullness.qual.NonNull;
import org.drools.core.ClassObjectFilter;
import org.kie.api.definition.KiePackage;
import org.kie.api.definition.rule.Query;
@@ -833,6 +836,15 @@
}
@Override
+ public <T> List<T> facts(@NonNull String sessionName, @NonNull Class<T> clazz) {
+ return facts(sessionName, clazz.getCanonicalName(), false)
+ .stream()
+ .filter(clazz::isInstance)
+ .map(clazz::cast)
+ .collect(Collectors.toList());
+ }
+
+ @Override
public List<Object> factQuery(String sessionName, String queryName, String queriedEntity,
boolean delete, Object... queryParams) {
if (sessionName == null || sessionName.isEmpty()) {
@@ -881,6 +893,33 @@
}
@Override
+ public <T> boolean delete(@NonNull String sessionName, @NonNull T fact) {
+ String factClassName = fact.getClass().getName();
+
+ PolicySession session = getSession(sessionName);
+ KieSession kieSession = session.getKieSession();
+
+ Collection<FactHandle> factHandles = kieSession.getFactHandles(new ClassObjectFilter(fact.getClass()));
+ for (FactHandle factHandle : factHandles) {
+ try {
+ if (Objects.equals(fact, kieSession.getObject(factHandle))) {
+ logger.info("Deleting {} from {}", factClassName, sessionName);
+ kieSession.delete(factHandle);
+ return true;
+ }
+ } catch (Exception e) {
+ logger.warn("Object cannot be retrieved from fact {}", factHandle, e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public <T> boolean delete(@NonNull T fact) {
+ return this.getSessionNames().stream().map((ss) -> delete(ss, fact)).reduce(false, Boolean::logicalOr);
+ }
+
+ @Override
public Class<?> fetchModelClass(String className) {
return ReflectionUtil.fetchClass(this.policyContainer.getClassLoader(), className);
}
diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java
index 815aaab..5bf51ef 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java
@@ -25,6 +25,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.checkerframework.checker.nullness.qual.NonNull;
import org.onap.policy.common.endpoints.event.comm.TopicSink;
import org.onap.policy.drools.controller.DroolsController;
import org.onap.policy.drools.core.PolicyContainer;
@@ -181,12 +182,27 @@
}
@Override
+ public <T> List<T> facts(@NonNull String sessionName, @NonNull Class<T> clazz) {
+ return new ArrayList<>();
+ }
+
+ @Override
public List<Object> factQuery(String sessionName, String queryName,
String queriedEntity,
boolean delete, Object... queryParams) {
return new ArrayList<>();
}
+ @Override
+ public <T> boolean delete(@NonNull String sessionName, @NonNull T fact) {
+ return false;
+ }
+
+ @Override
+ public <T> boolean delete(@NonNull T fact) {
+ return false;
+ }
+
private String makeInvokeMsg() {
return this.getClass().getCanonicalName() + " invoked";
}