deploy and undeploy as audits. 39/84739/2
authorjhh <jorge.hernandez-herrero@att.com>
Tue, 9 Apr 2019 19:24:34 +0000 (14:24 -0500)
committerjhh <jorge.hernandez-herrero@att.com>
Tue, 9 Apr 2019 19:30:01 +0000 (14:30 -0500)
Change-Id: Iea1766d5d8075394e1dccc109f4477bd2c270c36
Issue-ID: POLICY-1624
Signed-off-by: jhh <jorge.hernandez-herrero@att.com>
14 files changed:
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java
feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java
feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java
feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java
feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateRunningTest.java
feature-lifecycle/src/test/resources/tosca-policy-operational-firewall.json [new file with mode: 0644]
feature-lifecycle/src/test/resources/tosca-policy-operational-restart.json [moved from feature-lifecycle/src/test/resources/tosca-policy.json with 100% similarity]
feature-lifecycle/src/test/resources/tosca-policy-operational-restart.v2.json [new file with mode: 0644]
policy-management/lombok.config [new file with mode: 0644]
policy-management/src/main/java/org/onap/policy/drools/controller/DroolsController.java
policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java
policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java

index b99953e..97f3574 100644 (file)
@@ -283,6 +283,10 @@ public class LifecycleFsm implements Startable {
         policiesMap.put(policy.getIdentifier(), policy);
     }
 
+    protected void undeployedPolicyAction(@NonNull ToscaPolicy policy) {
+        policiesMap.remove(policy.getIdentifier());
+    }
+
     /* ** Action Helpers ** */
 
     private boolean startIo() {
index d481b8b..38ea091 100644 (file)
@@ -61,8 +61,6 @@ public class LifecycleStateActive extends LifecycleStateRunning {
     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 @@ public class LifecycleStateActive extends LifecycleStateRunning {
     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;
     }
 }
index 405dbeb..ed200ea 100644 (file)
@@ -134,8 +134,15 @@ public abstract class LifecycleStateRunning extends LifecycleStateDefault {
             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) {
index 1beee55..d5ac423 100644 (file)
@@ -24,7 +24,6 @@ import java.io.IOException;
 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 class ControllerSupport {
     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);
     }
 }
index 3200642..b8afd20 100644 (file)
@@ -33,6 +33,7 @@ import java.nio.file.Paths;
 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 @@ public class LifecycleStateActiveTest extends LifecycleStateRunningTest {
         change.setName(fsm.getName());
 
         fsm.source.offer(new StandardCoder().encode(change));
+        controllerSupport.getController().start();
     }
 
     @Test
@@ -197,7 +199,6 @@ public class LifecycleStateActiveTest extends LifecycleStateRunningTest {
         long interval = 2 * originalInterval;
         update.setPdpHeartbeatIntervalMs(interval * 1000L);
 
-        controllerSupport.getController().start();
         fsm.start(controllerSupport.getController());
 
         assertTrue(fsm.update(update));
@@ -207,20 +208,83 @@ public class LifecycleStateActiveTest extends LifecycleStateRunningTest {
         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());
+
+        // 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());
 
-        controllerSupport.getController().stop();
+        // 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();
     }
 }
index 100bcef..775dc8b 100644 (file)
@@ -187,7 +187,7 @@ public class LifecycleStatePassiveTest extends LifecycleStateRunningTest {
         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));
 
index d7bb6d7..6da9dc1 100644 (file)
@@ -41,7 +41,7 @@ public abstract class LifecycleStateRunningTest {
     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 (file)
index 0000000..7bfb16b
--- /dev/null
@@ -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-operational-restart.v2.json b/feature-lifecycle/src/test/resources/tosca-policy-operational-restart.v2.json
new file mode 100644 (file)
index 0000000..39d1618
--- /dev/null
@@ -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 (file)
index 0000000..2384843
--- /dev/null
@@ -0,0 +1,3 @@
+config.stopBubbling = true
+lombok.addLombokGeneratedAnnotation = true
+lombok.nonNull.exceptionType = IllegalArgumentException
index 344725f..78a2f4e 100644 (file)
@@ -22,7 +22,7 @@ package org.onap.policy.drools.controller;
 
 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;
@@ -214,6 +214,11 @@ public interface DroolsController extends Startable, Lockable {
      */
     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.
      * 
@@ -227,6 +232,16 @@ public interface DroolsController extends Startable, Lockable {
     List<Object> factQuery(String sessionName, String queryName, String queriedEntity, boolean delete,
         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.
      * 
index 95b053f..a9ab212 100644 (file)
@@ -27,7 +27,10 @@ import java.util.Collection;
 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;
@@ -832,6 +835,15 @@ public class MavenDroolsController implements DroolsController {
         return factObjects;
     }
 
+    @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) {
@@ -880,6 +892,33 @@ public class MavenDroolsController implements DroolsController {
         return factObjects;
     }
 
+    @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);
index 815aaab..5bf51ef 100644 (file)
@@ -25,6 +25,7 @@ import java.util.Collections;
 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;
@@ -180,6 +181,11 @@ public class NullDroolsController implements DroolsController {
         return new ArrayList<>();
     }
 
+    @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, 
@@ -187,6 +193,16 @@ public class NullDroolsController implements DroolsController {
         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";
     }