Added new test transaction feature 99/8799/7
authorMagnusen, Drew (dm741q) <dm741q@att.com>
Fri, 25 Aug 2017 15:20:46 +0000 (10:20 -0500)
committerMagnusen, Drew (dm741q) <dm741q@att.com>
Wed, 30 Aug 2017 17:44:47 +0000 (12:44 -0500)
Added test transaction feature which is used to test the health
of policy controllers.

Issue-ID: POLICY-177
Change-Id: I9a966be73f040c01e208bffd1dd67e8d858c1d37
Signed-off-by: Magnusen, Drew (dm741q) <dm741q@att.com>
feature-test-transaction/pom.xml [new file with mode: 0644]
feature-test-transaction/src/assembly/assemble_zip.xml [new file with mode: 0644]
feature-test-transaction/src/main/java/org/onap/policy/drools/testtransaction/TestTransaction.java [new file with mode: 0644]
feature-test-transaction/src/main/java/org/onap/policy/drools/testtransaction/TestTransactionFeature.java [new file with mode: 0644]
feature-test-transaction/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureAPI [new file with mode: 0644]
feature-test-transaction/src/main/resources/TestTransactionTemplate.drl [new file with mode: 0644]
pom.xml

diff --git a/feature-test-transaction/pom.xml b/feature-test-transaction/pom.xml
new file mode 100644 (file)
index 0000000..693c3dc
--- /dev/null
@@ -0,0 +1,97 @@
+<!--
+  ============LICENSE_START=======================================================
+  feature-test-transaction
+  ================================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  ================================================================================
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+  
+       http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END=========================================================
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.onap.policy.drools-pdp</groupId>
+    <artifactId>drools-pdp</artifactId>
+    <version>1.1.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>feature-test-transaction</artifactId>
+    
+    <name>feature-test-transaction</name>
+    <description>Separately loadable module which sends test transaction through system</description>
+
+  <properties>
+          <maven.compiler.source>1.8</maven.compiler.source>
+          <maven.compiler.target>1.8</maven.compiler.target>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.6</version>
+        <executions>
+          <execution>
+            <id>zipfile</id>
+            <goals>
+              <goal>single</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <attach>true</attach>
+              <finalName>${project.artifactId}-${project.version}</finalName>
+              <descriptors>
+                <descriptor>src/assembly/assemble_zip.xml</descriptor>
+              </descriptors>
+              <appendAssemblyId>false</appendAssemblyId>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <version>2.8</version>
+        <executions>
+          <execution>
+            <id>copy-dependencies</id>
+            <goals>
+              <goal>copy-dependencies</goal>
+            </goals>
+            <phase>prepare-package</phase>
+            <configuration>
+              <transitive>false</transitive>
+              <outputDirectory>${project.build.directory}/assembly/lib</outputDirectory>
+              <overWriteReleases>false</overWriteReleases>
+              <overWriteSnapshots>true</overWriteSnapshots>
+              <overWriteIfNewer>true</overWriteIfNewer>
+              <useRepositoryLayout>false</useRepositoryLayout>
+              <addParentPoms>false</addParentPoms>
+              <copyPom>false</copyPom>
+                         <includeScope>runtime</includeScope>
+                         <excludeTransitive>true</excludeTransitive>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.onap.policy.drools-pdp</groupId>
+      <artifactId>policy-management</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file
diff --git a/feature-test-transaction/src/assembly/assemble_zip.xml b/feature-test-transaction/src/assembly/assemble_zip.xml
new file mode 100644 (file)
index 0000000..03c0bb5
--- /dev/null
@@ -0,0 +1,78 @@
+<!--
+  ============LICENSE_START=======================================================
+  feature-test-transaction
+  ================================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  ================================================================================
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+  
+       http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END=========================================================
+  -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+     xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+     xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+     <id>feature-test-transaction</id>
+     <formats>
+          <format>zip</format>
+     </formats>
+
+     <!-- we want "system" and related files right at the root level as this 
+          file is suppose to be unzip on top of a karaf distro. -->
+     <includeBaseDirectory>false</includeBaseDirectory>
+
+     <fileSets>
+          <fileSet>
+               <directory>target</directory>
+               <outputDirectory>lib/feature</outputDirectory>
+               <includes>
+                    <include>feature-test-transaction-${project.version}.jar</include>
+               </includes>
+          </fileSet>
+               <fileSet>
+                       <directory>target/assembly/lib</directory>
+                       <outputDirectory>lib/dependencies</outputDirectory>
+                       <includes>
+                               <include>*.jar</include>
+                       </includes>
+               </fileSet>
+               <fileSet>
+                       <directory>src/main/feature/config</directory>
+                       <outputDirectory>config</outputDirectory>
+                       <fileMode>0644</fileMode>
+                       <excludes/>
+               </fileSet>
+               <fileSet>
+                       <directory>src/main/feature/bin</directory>
+                       <outputDirectory>bin</outputDirectory>
+                       <fileMode>0744</fileMode>
+                       <excludes/>
+               </fileSet>
+               <fileSet>
+                       <directory>src/main/feature/db</directory>
+                       <outputDirectory>db</outputDirectory>
+                       <fileMode>0744</fileMode>
+                       <excludes/>
+               </fileSet>
+               <fileSet>
+                       <directory>src/main/feature/install</directory>
+                       <outputDirectory>install</outputDirectory>
+                       <fileMode>0744</fileMode>
+                       <excludes/>
+               </fileSet>
+
+     </fileSets>
+
+</assembly>
diff --git a/feature-test-transaction/src/main/java/org/onap/policy/drools/testtransaction/TestTransaction.java b/feature-test-transaction/src/main/java/org/onap/policy/drools/testtransaction/TestTransaction.java
new file mode 100644 (file)
index 0000000..b167898
--- /dev/null
@@ -0,0 +1,227 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * feature-test-transaction
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.policy.drools.testtransaction;
+
+import java.util.EventObject;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+
+import org.onap.policy.drools.controller.DroolsController;
+import org.onap.policy.drools.controller.internal.MavenDroolsController;
+import org.onap.policy.drools.system.PolicyController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+/**
+ * TestTransaction interface 
+ *
+ */
+public interface TestTransaction {
+
+       public static final String TT_FPC = "TT.FPC";
+       public static final String TT_COUNTER = "$ttc";
+       public static final String TT_UUID = "43868e59-d1f3-43c2-bd6f-86f89a61eea5";
+       public static long DEFAULT_TT_TASK_SLEEP = 20000;
+       
+       public static final TestTransaction manager = new TTImpl();
+
+       public void register(PolicyController controller);
+       public void unregister(PolicyController controller);
+}
+
+/**
+ * Implementation of TestTransaction interface.
+ * Controls the registering/unregistering of 
+ * PolicyController objects and the management
+ * of their related TTControllerTask threads. 
+ */
+class TTImpl implements TestTransaction {
+       
+       final protected Map<String, TTControllerTask> controllers = new HashMap<>();
+
+       @Override
+       public synchronized void register(PolicyController controller) {
+               if (controllers.containsValue(controller)) {
+                       TTControllerTask controllerTask = controllers.get(controller.getName());
+                       if (controllerTask.isAlive())
+                               return;
+                       
+                       // continue : unregister, register operation
+               }
+               
+               TTControllerTask controllerTask = new TTControllerTask(controller);
+               controllers.put(controller.getName(), controllerTask);
+       }
+
+       @Override
+       public synchronized void unregister(PolicyController controller) {
+               if (!controllers.containsValue(controller))
+                       return;
+               
+               TTControllerTask controllerTask = controllers.get(controller.getName());
+               controllerTask.stop();
+               
+               controllers.remove(controller.getName());
+       }
+}
+
+/**
+ * TTControllerTask implements the Runnabale interface
+ * Carries out the injection of an event into a drools 
+ * session and subsequent query of a counter to ensure
+ * that forward progress is occuring. 
+ * 
+ */
+class TTControllerTask implements Runnable {
+    // get an instance of logger 
+       private static final Logger logger = LoggerFactory.getLogger(TTControllerTask.class); 
+   
+       protected final PolicyController controller;
+
+       protected volatile boolean alive = true;
+       protected final Thread thread = new Thread(this);
+
+       public TTControllerTask(PolicyController controller) {
+               this.controller = controller;
+               thread.setName("tt-controller-task-" + controller.getName());
+               thread.start();
+       }
+       
+       public PolicyController getController() {
+               return controller;
+       }
+
+       public synchronized boolean isAlive() {
+               return alive;
+       }
+
+       public synchronized void stop() {
+               this.alive = false;
+               thread.interrupt();
+               try {
+                       thread.join(1000);
+               } catch (InterruptedException e) {
+                       logger.error("TestTransaction thread threw", e);
+                       thread.interrupt();
+               }
+       }       
+       
+       public Thread getThread() {
+               return thread;
+       }
+
+       @Override
+       public void run() {
+               try {   
+                       List<String> sessions = 
+                                       controller.getDrools().getSessionNames();
+                       
+                       if (!(controller.getDrools().isBrained())) {
+                               alive = false;
+                               logger.error(this + ": unknown drools controller");
+                               return;
+                       }
+                       
+                       DroolsController drools = controller.getDrools();
+                       
+                       HashMap<String,Long> fpcs = new HashMap<>();
+                       for (String session: sessions) {
+                               fpcs.put(session, -1L);
+                       }
+                       
+                       while (controller.isAlive() && 
+                                  !controller.isLocked() &&
+                                  drools.isBrained() &&
+                                  alive) {
+                               
+                               for (String session : sessions) {
+                                       List<Object> facts = controller.getDrools().factQuery(session,
+                                                       TestTransaction.TT_FPC,
+                                                       TestTransaction.TT_COUNTER,
+                                                       false);
+                                       if (facts == null || facts.size() != 1) {
+                                               /* 
+                                                * unexpected something wrong here, can't expect to recover 
+                                                * note this exception is caught right below at the exit of run()
+                                                */
+                                               logger.error("Controller: {}, with rules artifact: (group) {}, (artifact) {}, (version) {} - FPC query failed after EventObject insertion! ",
+                                                                               controller.getName(),
+                                                                               controller.getDrools().getGroupId(),
+                                                                               controller.getDrools().getArtifactId(), 
+                                                                               controller.getDrools().getVersion());
+                                               break;
+                                       }
+                                       logger.debug("Facts: {}", facts);
+                                       
+                                       long fpc = (Long) facts.get(0);
+                                       if (fpc != fpcs.get(session))
+                                               logger.info("Controller: {} , session {}  - Forward progress successful: {} -> {}",
+                                                                               controller.getName(),
+                                                                               session,
+                                                                               fpcs.get(session), 
+                                                                               fpc);
+                                       else 
+                                               logger.error("Controller: {}, session {} - Forward progress failure: {}",
+                                                               controller.getName(),
+                                                               session,
+                                                               fpc);
+                                       
+                                       fpcs.put(session, fpc);                                                                 
+                                       drools.getContainer().insert(session, new EventObject(TestTransaction.TT_UUID));
+                               }
+                               
+                               if (!alive)
+                                       return;
+                               
+                               if (!Thread.currentThread().isInterrupted())
+                                       Thread.sleep(TestTransaction.DEFAULT_TT_TASK_SLEEP);
+                       }
+               } catch (InterruptedException e) {
+                       logger.info("{}: stopping ...", this, e);
+               } 
+               catch (IllegalArgumentException e) {
+                       logger.error("{}: controller {} has not been enabled for testing: ", this, controller.getName(), e.getMessage());
+               } catch (Exception e) {
+                       logger.error("Controller: {} is not testable - TestTransaction caught exception: {} ",
+                                       controller.getName(),
+                                       e.getMessage());
+                       logger.error("TestTransaction thread threw", e);
+               } finally {
+                       logger.info("Exiting: {}", this);
+                       alive = false;
+               }
+       }
+
+       @Override
+       public String toString() {
+               StringBuilder builder = new StringBuilder();
+               builder.append("TTControllerTask [controller=");
+               builder.append(controller);
+               builder.append(", alive=");
+               builder.append(alive);
+               builder.append(", thread=");
+               builder.append(thread.getName());
+               builder.append("]");
+               return builder.toString();
+       }
+       
+}
diff --git a/feature-test-transaction/src/main/java/org/onap/policy/drools/testtransaction/TestTransactionFeature.java b/feature-test-transaction/src/main/java/org/onap/policy/drools/testtransaction/TestTransactionFeature.java
new file mode 100644 (file)
index 0000000..72c5496
--- /dev/null
@@ -0,0 +1,83 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * feature-test-transaction
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.drools.testtransaction;
+
+import org.onap.policy.drools.features.PolicyControllerFeatureAPI;
+import org.onap.policy.drools.system.PolicyController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+/**
+ * TestTransactionFeature implements the PolicyControllerFeatureAPI.
+ * TestTransactionFeature is the interface to the TestTransaction feature logic.
+ * 
+ */
+public class TestTransactionFeature implements PolicyControllerFeatureAPI {
+
+    // get an instance of logger 
+       private static final Logger logger = LoggerFactory.getLogger(TestTransactionFeature.class); 
+
+    @Override
+    public boolean afterStart(PolicyController controller){
+        
+        logger.info("TEST_TRANSACTION FEATURE LOADED");
+        
+        if (controller.isAlive() &&
+            !controller.isLocked() && 
+            controller.getDrools().isBrained())
+               TestTransaction.manager.register(controller);
+        
+        return false;
+    }
+    
+    @Override
+    public boolean afterLock(PolicyController controller) {
+        logger.info("CONTROLLER " + controller.getName() + " LOCKED");
+        
+        TestTransaction.manager.unregister(controller);
+        return false;
+    }
+    
+    @Override
+    public boolean afterUnlock(PolicyController controller) {
+        logger.info("CONTROLLER " + controller.getName() + " UNLOCKED");
+        
+        if (controller.isAlive() &&
+               !controller.isLocked() && 
+            controller.getDrools().isBrained())
+               TestTransaction.manager.register(controller);
+        
+        return false;
+    }
+
+    @Override
+    public boolean beforeStop(PolicyController controller) {
+        logger.info("CONTROLLER " + controller.getName() + " ABOUT TO STOP");
+        
+        TestTransaction.manager.unregister(controller);
+        
+        return false;
+    }
+
+    @Override
+    public int getSequenceNumber() {
+        return 1000;
+    }
+}
diff --git a/feature-test-transaction/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureAPI b/feature-test-transaction/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureAPI
new file mode 100644 (file)
index 0000000..6b60237
--- /dev/null
@@ -0,0 +1 @@
+org.onap.policy.drools.testtransaction.TestTransactionFeature
diff --git a/feature-test-transaction/src/main/resources/TestTransactionTemplate.drl b/feature-test-transaction/src/main/resources/TestTransactionTemplate.drl
new file mode 100644 (file)
index 0000000..381f089
--- /dev/null
@@ -0,0 +1,47 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * feature-test-transaction
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.policy.drools.rules;
+
+import java.util.EventObject;
+
+declare ForwardProgress
+       counter : Long
+end
+
+rule "TT.SETUP"
+when
+then
+       ForwardProgress fp = new ForwardProgress();
+       fp.setCounter(0L);
+       insert(fp);
+end
+
+rule "TT"
+when 
+       $fp : ForwardProgress()
+       $tt : EventObject(source == "43868e59-d1f3-43c2-bd6f-86f89a61eea5")
+then
+       $fp.setCounter($fp.getCounter() + 1);
+       retract($tt);
+end
+
+query "TT.FPC"
+       ForwardProgress(counter >= 0, $ttc : counter)
+end
diff --git a/pom.xml b/pom.xml
index e5fc5c9..f3f1460 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -70,6 +70,7 @@
                <module>feature-healthcheck</module>
                <module>feature-eelf</module>
                <module>feature-session-persistence</module>
+               <module>feature-test-transaction</module>
                <module>packages</module>
        </modules>