aboutsummaryrefslogtreecommitdiffstats
path: root/controlloop/templates/template.demo/src
diff options
context:
space:
mode:
Diffstat (limited to 'controlloop/templates/template.demo/src')
-rw-r--r--controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_xacml_guard.drl123
-rw-r--r--controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/AaiSimulatorTest.java1
-rw-r--r--controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopXacmlGuardTest.java53
-rw-r--r--controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/Util.java4
-rw-r--r--controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VCPEControlLoopTest.java441
-rw-r--r--controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VFWControlLoopTest.java435
-rw-r--r--controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vCPE.yaml23
-rw-r--r--controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vFW.yaml28
-rw-r--r--controlloop/templates/template.demo/src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml26
9 files changed, 1116 insertions, 18 deletions
diff --git a/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_xacml_guard.drl b/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_xacml_guard.drl
index 276e64b7d..aa1f1e977 100644
--- a/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_xacml_guard.drl
+++ b/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_xacml_guard.drl
@@ -32,6 +32,11 @@ import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager;
import org.onap.policy.appc.Request;
import org.onap.policy.appc.Response;
import org.onap.policy.appc.CommonHeader;
+import org.onap.policy.appclcm.LCMRequestWrapper;
+import org.onap.policy.appclcm.LCMResponseWrapper;
+import org.onap.policy.appclcm.LCMRequest;
+import org.onap.policy.appclcm.LCMResponse;
+import org.onap.policy.appclcm.LCMCommonHeader;
import org.onap.policy.vfc.VFCRequest;
import org.onap.policy.vfc.VFCManager;
import org.onap.policy.guard.PolicyGuard;
@@ -490,7 +495,7 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
case "APPC":
- if (request instanceof Request) {
+ if (request instanceof Request || request instanceof LCMRequestWrapper) {
Engine.deliver("UEB", "APPC-CL", request);
}
break;
@@ -771,6 +776,122 @@ rule "${policyName}.APPC.RESPONSE.CLEANUP"
//
retract($response);
end
+
+/*
+*
+* This rule responds to APPC Response Events using the new LCM interface provided by appc
+*
+*/
+rule "${policyName}.APPC.LCM.RESPONSE"
+ when
+ $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
+ $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), closedLoopEventStatus == ControlLoopEventStatus.ONSET )
+ $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID )
+ $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID )
+ $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() )
+ $lock : TargetLock (requestID == $event.requestID)
+ $response : LCMResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.requestID )
+ then
+ //
+ // Logging
+ //
+ Logger.info("------------------------------------------------------------------------------------------------");
+ Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage());
+ Logger.metrics($params);
+ Logger.metrics($event);
+ Logger.metrics($manager);
+ Logger.metrics($operation);
+ Logger.metrics($opTimer);
+ Logger.metrics($lock);
+ Logger.metrics($response);
+ //
+ // Get the result of the operation
+ //
+ PolicyResult policyResult = $operation.onResponse($response);
+ if (policyResult != null) {
+ Logger.info("operation finished with result: " + policyResult);
+ //
+ // This Operation has completed, construct a notification showing our results. (DB write - end operation)
+ //
+ VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
+ notification.from = "policy";
+ notification.policyName = drools.getRule().getName();
+ notification.policyScope = "${policyScope}";
+ notification.policyVersion = "${policyVersion}";
+ notification.message = $operation.getOperationHistory();
+ notification.history = $operation.getHistory();
+ if (policyResult.equals(PolicyResult.SUCCESS)) {
+ notification.notification = ControlLoopNotificationType.OPERATION_SUCCESS;
+ //
+ // Let interested parties know
+ //
+ Engine.deliver("UEB", "POLICY-CL-MGT", notification);
+ } else {
+ notification.notification = ControlLoopNotificationType.OPERATION_FAILURE;
+ //
+ // Let interested parties know
+ //
+ Engine.deliver("UEB", "POLICY-CL-MGT", notification);
+ }
+ //
+ // Ensure the operation is complete
+ //
+ if ($operation.isOperationComplete() == true) {
+ //
+ // It is complete, remove it from memory
+ //
+ retract($operation);
+ //
+ // We must also retract the timer object
+ // NOTE: We could write a Rule to do this
+ //
+ retract($opTimer);
+ //
+ // Complete the operation
+ //
+ modify($manager) {finishOperation($operation)};
+ } else {
+ //
+ // Just doing this will kick off the LOCKED rule again
+ //
+ modify($operation) {};
+ }
+ } else {
+ //
+ // Its not finished yet (i.e. expecting more Response objects)
+ //
+ // Or possibly it is a leftover response that we timed the request out previously
+ //
+ }
+ //
+ // We are going to retract these objects from memory
+ //
+ retract($response);
+end
+
+/*
+*
+* Clean Up any lingering LCM reponses
+*
+*/
+rule "${policyName}.APPC.LCM.RESPONSE.CLEANUP"
+ when
+ $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
+ $response : LCMResponseWrapper($id : getBody().getCommonHeader().getRequestId )
+ not ( VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), requestID == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
+ then
+ //
+ // Logging
+ //
+ Logger.info("------------------------------------------------------------------------------------------------");
+ Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage());
+ Logger.metrics($params);
+ //
+ // Retract it
+ //
+ retract($response);
+end
+
/*
*
* This is the timer that manages the timeout for an individual operation.
diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/AaiSimulatorTest.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/AaiSimulatorTest.java
index 3bdeca1fc..71c6e3a29 100644
--- a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/AaiSimulatorTest.java
+++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/AaiSimulatorTest.java
@@ -27,7 +27,6 @@ import java.util.UUID;
import org.junit.AfterClass;
import org.junit.BeforeClass;
-import org.junit.Ignore;
import org.junit.Test;
import org.onap.policy.aai.AAIGETResponse;
import org.onap.policy.aai.AAINQF199.AAINQF199Manager;
diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopXacmlGuardTest.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopXacmlGuardTest.java
index 23f03f7e8..8c0b99462 100644
--- a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopXacmlGuardTest.java
+++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopXacmlGuardTest.java
@@ -32,14 +32,16 @@ import java.time.Instant;
import java.util.HashMap;
import java.util.UUID;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
-import org.onap.policy.appc.Request;
-import org.onap.policy.appc.Response;
-import org.onap.policy.appc.ResponseCode;
-import org.onap.policy.appc.ResponseValue;
+import org.onap.policy.appclcm.LCMRequest;
+import org.onap.policy.appclcm.LCMRequestWrapper;
+import org.onap.policy.appclcm.LCMResponse;
+import org.onap.policy.appclcm.LCMResponseWrapper;
import org.onap.policy.controlloop.ControlLoopEventStatus;
import org.onap.policy.controlloop.ControlLoopNotificationType;
@@ -47,6 +49,7 @@ import org.onap.policy.controlloop.VirtualControlLoopEvent;
import org.onap.policy.controlloop.VirtualControlLoopNotification;
import org.onap.policy.controlloop.policy.ControlLoopPolicy;
import org.onap.policy.controlloop.policy.TargetType;
+import org.onap.policy.drools.http.server.HttpServletServer;
import org.onap.policy.drools.impl.PolicyEngineJUnitImpl;
import org.onap.policy.guard.PolicyGuard;
import org.slf4j.Logger;
@@ -55,8 +58,22 @@ import org.slf4j.LoggerFactory;
public class ControlLoopXacmlGuardTest {
+ @BeforeClass
+ public static void setUpSimulator() {
+ try {
+ Util.buildAaiSim();
+ } catch (InterruptedException e) {
+ fail(e.getMessage());
+ }
+ }
+
+ @AfterClass
+ public static void tearDownSimulator() {
+ HttpServletServer.factory.destroy();
+ }
+
private static final Logger logger = LoggerFactory.getLogger(ControlLoopXacmlGuardTest.class);
-
+
@Test
public void test() {
try {
@@ -216,8 +233,10 @@ public class ControlLoopXacmlGuardTest {
obj = engine.subscribe("UEB", "APPC-CL");
assertNotNull(obj);
- assertTrue(obj instanceof Request);
- assertTrue(((Request)obj).CommonHeader.SubRequestID.equals("1"));
+ assertTrue(obj instanceof LCMRequestWrapper);
+ LCMRequestWrapper dmaapRequest = (LCMRequestWrapper) obj;
+ LCMRequest appcRequest = dmaapRequest.getBody();
+ assertTrue(appcRequest.getCommonHeader().getSubRequestId().equals("1"));
logger.debug("\n============ APP-C Got request!!! ===========\n");
//
@@ -232,11 +251,12 @@ public class ControlLoopXacmlGuardTest {
//
// Now we are going to success it
//
- Response response = new Response((Request) obj);
- response.Status.Code = ResponseCode.SUCCESS.getValue();
- response.Status.Value = ResponseValue.SUCCESS.toString();
- response.Status.Description = "AppC success";
- kieSession.insert(response);
+ LCMResponseWrapper dmaapResponse = new LCMResponseWrapper();
+ LCMResponse appcResponse = new LCMResponse(appcRequest);
+ appcResponse.getStatus().setCode(400);
+ appcResponse.getStatus().setMessage("AppC success");
+ dmaapResponse.setBody(appcResponse);
+ kieSession.insert(dmaapResponse);
//
// Give it some time to process
//
@@ -248,7 +268,7 @@ public class ControlLoopXacmlGuardTest {
//
// now wait for it to finish
//
- Thread.sleep(5000);
+ Thread.sleep(15000);
//
// Ensure they released the lock
//
@@ -288,6 +308,7 @@ public class ControlLoopXacmlGuardTest {
Object fact = kieSession.getObject(handle);
assertEquals("", "org.onap.policy.controlloop.Params", fact.getClass().getName());
}
+ kieSession.dispose();
}
@@ -307,7 +328,7 @@ public class ControlLoopXacmlGuardTest {
event.target = "vserver.vserver-name";
event.closedLoopAlarmStart = Instant.now().minusSeconds(5);
event.closedLoopAlarmEnd = Instant.now();
- event.AAI = new HashMap<String, String>();
+ event.AAI = new HashMap<>();
event.AAI.put("cloud-region.identity-url", "foo");
event.AAI.put("vserver.selflink", "bar");
event.AAI.put("vserver.is-closed-loop-disabled", "false");
@@ -322,7 +343,7 @@ public class ControlLoopXacmlGuardTest {
event.requestID = requestID;
event.target = "vserver.vserver-name";
event.closedLoopAlarmStart = Instant.now();
- event.AAI = new HashMap<String, String>();
+ event.AAI = new HashMap<>();
event.AAI.put("cloud-region.identity-url", "foo");
event.AAI.put("vserver.selflink", "bar");
event.AAI.put("vserver.is-closed-loop-disabled", "false");
@@ -350,7 +371,7 @@ public class ControlLoopXacmlGuardTest {
//
// add some aai
//
- event.AAI = new HashMap<String, String>();
+ event.AAI = new HashMap<>();
event.AAI.put("cloud-region.identity-url", "foo");
event.AAI.put("vserver.selflink", "bar");
event.AAI.put("vserver.vserver-name", "vmfoo");
diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/Util.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/Util.java
index 61be1535e..502ef7c1d 100644
--- a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/Util.java
+++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/Util.java
@@ -239,6 +239,10 @@ public final class Util {
"src/main/resources/frequency_limiter_template.xml",
"src/test/resources/xacml/autogenerated_frequency_limiter_migrate.xml");
+ PolicyGuardYamlToXacml.fromYamlToXacml("src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml",
+ "src/main/resources/frequency_limiter_template.xml",
+ "src/test/resources/xacml/autogenerated_frequency_limiter_modifyconfig.xml");
+
PolicyGuardYamlToXacml.fromYamlToXacmlBlacklist("src/test/resources/yaml/policy_guard_appc_restart_blacklist.yaml",
"src/main/resources/blacklist_template.xml",
"src/test/resources/xacml/autogenerated_blacklist.xml");
diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VCPEControlLoopTest.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VCPEControlLoopTest.java
new file mode 100644
index 000000000..a34ee6cd1
--- /dev/null
+++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VCPEControlLoopTest.java
@@ -0,0 +1,441 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * demo
+ * ================================================================================
+ * 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.template.demo;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.UUID;
+
+import org.junit.Test;
+import org.kie.api.runtime.KieSession;
+import org.kie.api.runtime.rule.FactHandle;
+import org.onap.policy.appclcm.LCMRequest;
+import org.onap.policy.appclcm.LCMRequestWrapper;
+import org.onap.policy.appclcm.LCMResponse;
+import org.onap.policy.appclcm.LCMResponseWrapper;
+import org.onap.policy.controlloop.ControlLoopEventStatus;
+import org.onap.policy.controlloop.ControlLoopNotificationType;
+import org.onap.policy.controlloop.VirtualControlLoopEvent;
+import org.onap.policy.controlloop.VirtualControlLoopNotification;
+import org.onap.policy.controlloop.policy.ControlLoopPolicy;
+import org.onap.policy.controlloop.policy.TargetType;
+import org.onap.policy.drools.impl.PolicyEngineJUnitImpl;
+import org.onap.policy.guard.PolicyGuard;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VCPEControlLoopTest {
+
+ private static final Logger logger = LoggerFactory.getLogger(VCPEControlLoopTest.class);
+
+ private KieSession kieSession;
+ private Util.Pair<ControlLoopPolicy, String> pair;
+ private PolicyEngineJUnitImpl engine;
+
+ @Test
+ public void successTest() {
+
+ /*
+ * Start the kie session
+ */
+ try {
+ kieSession = startSession("src/main/resources/ControlLoop_Template_xacml_guard.drl",
+ "src/test/resources/yaml/policy_ControlLoop_vCPE.yaml",
+ "service=ServiceTest;resource=ResourceTest;type=operational",
+ "CL_vCPE",
+ "org.onap.closed_loop.ServiceTest:VNFS:1.0.0");
+ } catch (IOException e) {
+ e.printStackTrace();
+ logger.debug("Could not create kieSession");
+ fail("Could not create kieSession");
+ }
+
+ /*
+ * Create a thread to continuously fire rules
+ * until main thread calls halt
+ */
+ new Thread( new Runnable() {
+ @Override
+ public void run() {
+ kieSession.fireUntilHalt();
+ }
+ } ).start();
+
+ /*
+ * Create a unique requestId and a unique trigger source
+ */
+ UUID requestID = UUID.randomUUID();
+ String triggerSourceName = "foobartriggersource36";
+
+ /*
+ * This will be the object returned from the PolicyEngine
+ */
+ Object obj = null;
+
+ /*
+ * Simulate an onset event the policy engine will
+ * receive from DCAE to kick off processing through
+ * the rules.
+ */
+ try {
+ sendOnset(pair.a, requestID, triggerSourceName);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ logger.debug("Unable to send onset event");
+ fail("Unable to send onset event");
+ }
+
+ /*
+ * Pull the object that was sent out to DMAAP and make
+ * sure it is a ControlLoopNoticiation of type active
+ */
+ obj = engine.subscribe("UEB", "POLICY-CL-MGT");
+ assertNotNull(obj);
+ assertTrue(obj instanceof VirtualControlLoopNotification);
+ assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.ACTIVE));
+
+ /*
+ * Give the control loop time to acquire a lock
+ */
+ try {
+ Thread.sleep(4000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ logger.debug("An interrupt Exception was thrown");
+ fail("An interrupt Exception was thrown");
+ }
+
+ /*
+ * The fact should be ready to query guard now to see
+ * if a ModifyConfig recipe is allowed
+ */
+ obj = engine.subscribe("UEB", "POLICY-CL-MGT");
+ assertNotNull(obj);
+ logger.debug("\n\n####################### GOING TO QUERY GUARD about Restart!!!!!!");
+ logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
+
+ /*
+ * Make sure the object is an instance of a ControlLoopNotification
+ * and is of type operation
+ */
+ assertTrue(obj instanceof VirtualControlLoopNotification);
+ assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
+
+ try {
+ Thread.sleep(4000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ logger.debug("An interrupt Exception was thrown");
+ fail("An interrupt Exception was thrown");
+ }
+
+ /*
+ * The guard response should be received at this point
+ */
+ obj = engine.subscribe("UEB", "POLICY-CL-MGT");
+ assertNotNull(obj);
+ logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
+
+ /*
+ * The object should be a ControlLoopNotification with type operation
+ */
+ assertTrue(obj instanceof VirtualControlLoopNotification);
+ assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
+
+ /*
+ * See if Guard permits this action, if it does
+ * not then the test should fail
+ */
+ if (((VirtualControlLoopNotification)obj).message.contains("Guard result: Permit")) {
+
+ /*
+ * A notification should be sent out of the Policy
+ * Engine at this point, it will be of type operation
+ */
+ obj = engine.subscribe("UEB", "POLICY-CL-MGT");
+ assertNotNull(obj);
+ logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
+
+ /* A notification should be sent out of the Policy
+ * Engine at this point, it will be of type operation
+ */
+ assertTrue(obj instanceof VirtualControlLoopNotification);
+ assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
+
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ logger.debug("An interrupt Exception was thrown");
+ fail("An interrupt Exception was thrown");
+ }
+
+ /*
+ * Obtain the request sent from the Policy Engine
+ */
+ obj = engine.subscribe("UEB", "APPC-CL");
+ assertNotNull(obj);
+
+ /*
+ * The request should be of type LCMRequestWrapper
+ * and the subrequestid should be 1
+ */
+ assertTrue(obj instanceof LCMRequestWrapper);
+ LCMRequestWrapper dmaapRequest = (LCMRequestWrapper) obj;
+ LCMRequest appcRequest = dmaapRequest.getBody();
+ assertTrue(appcRequest.getCommonHeader().getSubRequestId().equals("1"));
+
+ logger.debug("\n============ APPC received the request!!! ===========\n");
+
+ /*
+ * Give some time for processing
+ */
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ logger.debug("An interrupt Exception was thrown");
+ fail("An interrupt Exception was thrown");
+ }
+
+ /*
+ * Simulate a success response from APPC and insert
+ * the response into the working memory
+ */
+ LCMResponseWrapper dmaapResponse = new LCMResponseWrapper();
+ LCMResponse appcResponse = new LCMResponse(appcRequest);
+ appcResponse.getStatus().setCode(400);
+ appcResponse.getStatus().setMessage("AppC success");
+ dmaapResponse.setBody(appcResponse);
+ kieSession.insert(dmaapResponse);
+
+ /*
+ * Give time for processing
+ */
+ try {
+ Thread.sleep(4000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ logger.debug("An interrupt Exception was thrown");
+ fail("An interrupt Exception was thrown");
+ }
+
+ /*
+ * Make sure the next notification is delivered
+ */
+ obj = engine.subscribe("UEB", "POLICY-CL-MGT");
+ assertNotNull(obj);
+ logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
+
+ /*
+ * The ControlLoopNotification should be
+ * an OPERATION_SUCCESS
+ */
+ assertTrue(obj instanceof VirtualControlLoopNotification);
+ assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION_SUCCESS));
+
+ /*
+ * Now simulate the abatement sent from DCAE
+ */
+ try {
+ sendAbatement(pair.a, requestID, triggerSourceName);
+ } catch (InterruptedException e1) {
+ e1.printStackTrace();
+ logger.debug("Abatement could not be sent");
+ fail("Abatement could not be sent");
+ }
+
+ /*
+ * Give time to finish processing
+ */
+ try {
+ Thread.sleep(20000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ logger.debug("An interrupt Exception was thrown");
+ fail("An interrupt Exception was thrown");
+ }
+
+ /*
+ * This should be the final notification from the Policy Engine
+ */
+ obj = engine.subscribe("UEB", "POLICY-CL-MGT");
+ assertNotNull(obj);
+ logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
+
+ /*
+ * The ControlLoopNotification should be of type FINAL_SUCCESS
+ */
+ assertTrue(obj instanceof VirtualControlLoopNotification);
+ assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.FINAL_SUCCESS));
+
+ /*
+ * One final check to make sure the lock is released
+ */
+ assertFalse(PolicyGuard.isLocked(TargetType.VM, triggerSourceName, requestID));
+ }
+ else {
+ fail("Operation Denied by Guard");
+ }
+
+ /*
+ * This will stop the thread that is firing the rules
+ */
+ kieSession.halt();
+
+ /*
+ * The only fact in memory should be Params
+ */
+ assertEquals(1, kieSession.getFactCount());
+
+ /*
+ * Print what's left in memory
+ */
+ dumpFacts(kieSession);
+
+ /*
+ * Gracefully shut down the kie session
+ */
+ kieSession.dispose();
+ }
+
+ /**
+ * This method will start a kie session and instantiate
+ * the Policy Engine.
+ *
+ * @param droolsTemplate
+ * the DRL rules file
+ * @param yamlFile
+ * the yaml file containing the policies
+ * @param policyScope
+ * scope for policy
+ * @param policyName
+ * name of the policy
+ * @param policyVersion
+ * version of the policy
+ * @return the kieSession to be used to insert facts
+ * @throws IOException
+ */
+ private KieSession startSession(String droolsTemplate,
+ String yamlFile,
+ String policyScope,
+ String policyName,
+ String policyVersion) throws IOException {
+
+ /*
+ * Load policies from yaml
+ */
+ pair = Util.loadYaml(yamlFile);
+ assertNotNull(pair);
+ assertNotNull(pair.a);
+ assertNotNull(pair.a.getControlLoop());
+ assertNotNull(pair.a.getControlLoop().getControlLoopName());
+ assertTrue(pair.a.getControlLoop().getControlLoopName().length() > 0);
+
+ /*
+ * Construct a kie session
+ */
+ final KieSession kieSession = Util.buildContainer(droolsTemplate,
+ pair.a.getControlLoop().getControlLoopName(),
+ policyScope,
+ policyName,
+ policyVersion,
+ URLEncoder.encode(pair.b, "UTF-8"));
+
+ /*
+ * Retrieve the Policy Engine
+ */
+ engine = (PolicyEngineJUnitImpl) kieSession.getGlobal("Engine");
+
+ logger.debug("============");
+ logger.debug(URLEncoder.encode(pair.b, "UTF-8"));
+ logger.debug("============");
+
+ return kieSession;
+ }
+
+ /**
+ * This method is used to simulate event messages from DCAE
+ * that start the control loop (onset message).
+ *
+ * @param policy the controlLoopName comes from the policy
+ * @param requestID the requestId for this event
+ * @param triggerSourceName
+ * @throws InterruptedException
+ */
+ protected void sendOnset(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException {
+ VirtualControlLoopEvent event = new VirtualControlLoopEvent();
+ event.closedLoopControlName = policy.getControlLoop().getControlLoopName();
+ event.requestID = requestID;
+ event.target = "vserver.vserver-name";
+ event.closedLoopAlarmStart = Instant.now();
+ event.AAI = new HashMap<>();
+ event.AAI.put("cloud-region.identity-url", "foo");
+ event.AAI.put("vserver.selflink", "bar");
+ event.AAI.put("vserver.is-closed-loop-disabled", "false");
+ event.AAI.put("vserver.vserver-name", "testGenericVnfName");
+ event.AAI.put("generic-vnf.vnf-id", "testGenericVnfId");
+ event.closedLoopEventStatus = ControlLoopEventStatus.ONSET;
+ kieSession.insert(event);
+ Thread.sleep(1000);
+ }
+
+ /**
+ * This method is used to simulate event messages from DCAE
+ * that end the control loop (abatement message).
+ *
+ * @param policy the controlLoopName comes from the policy
+ * @param requestID the requestId for this event
+ * @param triggerSourceName
+ * @throws InterruptedException
+ */
+ protected void sendAbatement(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException {
+ VirtualControlLoopEvent event = new VirtualControlLoopEvent();
+ event.closedLoopControlName = policy.getControlLoop().getControlLoopName();
+ event.requestID = requestID;
+ event.target = "vserver.vserver-name";
+ event.closedLoopAlarmStart = Instant.now().minusSeconds(5);
+ event.closedLoopAlarmEnd = Instant.now();
+ event.AAI = new HashMap<>();
+ event.AAI.put("cloud-region.identity-url", "foo");
+ event.AAI.put("vserver.selflink", "bar");
+ event.AAI.put("vserver.is-closed-loop-disabled", "false");
+ event.AAI.put("generic-vnf.vnf-name", "testGenericVnfName");
+ event.closedLoopEventStatus = ControlLoopEventStatus.ABATED;
+ kieSession.insert(event);
+ }
+
+ /**
+ * This method will dump all the facts in the working memory.
+ *
+ * @param kieSession the session containing the facts
+ */
+ public void dumpFacts(KieSession kieSession) {
+ logger.debug("Fact Count: {}", kieSession.getFactCount());
+ for (FactHandle handle : kieSession.getFactHandles()) {
+ logger.debug("FACT: {}", handle);
+ }
+ }
+}
diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VFWControlLoopTest.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VFWControlLoopTest.java
new file mode 100644
index 000000000..25920e8b5
--- /dev/null
+++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VFWControlLoopTest.java
@@ -0,0 +1,435 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * demo
+ * ================================================================================
+ * 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.template.demo;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.UUID;
+
+import org.junit.Test;
+import org.kie.api.runtime.KieSession;
+import org.kie.api.runtime.rule.FactHandle;
+import org.onap.policy.appc.Request;
+import org.onap.policy.appc.Response;
+import org.onap.policy.appc.ResponseCode;
+import org.onap.policy.controlloop.ControlLoopEventStatus;
+import org.onap.policy.controlloop.ControlLoopNotificationType;
+import org.onap.policy.controlloop.VirtualControlLoopEvent;
+import org.onap.policy.controlloop.VirtualControlLoopNotification;
+import org.onap.policy.controlloop.policy.ControlLoopPolicy;
+import org.onap.policy.controlloop.policy.TargetType;
+import org.onap.policy.drools.impl.PolicyEngineJUnitImpl;
+import org.onap.policy.guard.PolicyGuard;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VFWControlLoopTest {
+
+ private static final Logger logger = LoggerFactory.getLogger(VFWControlLoopTest.class);
+
+ private KieSession kieSession;
+ private Util.Pair<ControlLoopPolicy, String> pair;
+ private PolicyEngineJUnitImpl engine;
+
+ @Test
+ public void successTest() {
+
+ /*
+ * Start the kie session
+ */
+ try {
+ kieSession = startSession("src/main/resources/ControlLoop_Template_xacml_guard.drl",
+ "src/test/resources/yaml/policy_ControlLoop_vFW.yaml",
+ "service=ServiceDemo;resource=Res1Demo;type=operational",
+ "CL_vFW",
+ "org.onap.closed_loop.ServiceDemo:VNFS:1.0.0");
+ } catch (IOException e) {
+ e.printStackTrace();
+ logger.debug("Could not create kieSession");
+ fail("Could not create kieSession");
+ }
+
+ /*
+ * Create a thread to continuously fire rules
+ * until main thread calls halt
+ */
+ new Thread( new Runnable() {
+ @Override
+ public void run() {
+ kieSession.fireUntilHalt();
+ }
+ } ).start();
+
+ /*
+ * Create a unique requestId and a unique trigger source
+ */
+ UUID requestID = UUID.randomUUID();
+ String triggerSourceName = "foobartriggersource36";
+
+ /*
+ * This will be the object returned from the PolicyEngine
+ */
+ Object obj = null;
+
+ /*
+ * Simulate an onset event the policy engine will
+ * receive from DCAE to kick off processing through
+ * the rules
+ */
+ try {
+ sendOnset(pair.a, requestID, triggerSourceName);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ logger.debug("Unable to send onset event");
+ fail("Unable to send onset event");
+ }
+
+ /*
+ * Pull the object that was sent out to DMAAP and make
+ * sure it is a ControlLoopNoticiation of type active
+ */
+ obj = engine.subscribe("UEB", "POLICY-CL-MGT");
+ assertNotNull(obj);
+ assertTrue(obj instanceof VirtualControlLoopNotification);
+ assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.ACTIVE));
+
+ /*
+ * Give the control loop time to acquire a lock
+ */
+ try {
+ Thread.sleep(4000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ logger.debug("An interrupt Exception was thrown");
+ fail("An interrupt Exception was thrown");
+ }
+
+ /*
+ * The fact should be ready to query guard now to see
+ * if a ModifyConfig recipe is allowed
+ */
+ obj = engine.subscribe("UEB", "POLICY-CL-MGT");
+ assertNotNull(obj);
+ logger.debug("\n\n####################### GOING TO QUERY GUARD about ModifyConfig!!!!!!");
+ logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
+
+ /*
+ * Make sure the object is an instance of a ControlLoopNotification
+ * and is of type operation
+ */
+ assertTrue(obj instanceof VirtualControlLoopNotification);
+ assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
+
+ try {
+ Thread.sleep(4000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ logger.debug("An interrupt Exception was thrown");
+ fail("An interrupt Exception was thrown");
+ }
+
+ /*
+ * The guard response should be received at this point
+ */
+ obj = engine.subscribe("UEB", "POLICY-CL-MGT");
+ assertNotNull(obj);
+ logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
+
+ /*
+ * The object should be a ControlLoopNotification with type operation
+ */
+ assertTrue(obj instanceof VirtualControlLoopNotification);
+ assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
+
+ /*
+ * See if Guard permits this action, if it does
+ * not then the test should fail
+ */
+ if (((VirtualControlLoopNotification)obj).message.contains("Guard result: Permit")) {
+
+ /*
+ * Obtain the ControlLoopNoticiation, it should be of type operation
+ */
+ obj = engine.subscribe("UEB", "POLICY-CL-MGT");
+ assertNotNull(obj);
+ logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
+
+ /*
+ * A notification should be sent out of the Policy
+ * Engine at this point, it will be of type operation
+ */
+ assertTrue(obj instanceof VirtualControlLoopNotification);
+ assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
+
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ logger.debug("An interrupt Exception was thrown");
+ fail("An interrupt Exception was thrown");
+ }
+
+ /*
+ * Obtain the request sent from the Policy Engine
+ */
+ obj = engine.subscribe("UEB", "APPC-CL");
+ assertNotNull(obj);
+
+ /*
+ * The request should be of type Request
+ * and the subrequestid should be 1
+ */
+ assertTrue(obj instanceof Request);
+ assertTrue(((Request)obj).getCommonHeader().SubRequestID.equals("1"));
+
+ logger.debug("\n============ APPC received the request!!! ===========\n");
+
+ /*
+ * Give some time for processing
+ */
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ logger.debug("An interrupt Exception was thrown");
+ fail("An interrupt Exception was thrown");
+ }
+
+ /*
+ * Simulate a success response from APPC and insert
+ * the response into the working memory
+ */
+ Response appcResponse = new Response((Request)obj);
+ appcResponse.getStatus().Code = ResponseCode.SUCCESS.getValue();
+ appcResponse.getStatus().Description = "AppC success";
+ kieSession.insert(appcResponse);
+
+ /*
+ * Give time for processing
+ */
+ try {
+ Thread.sleep(4000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ logger.debug("An interrupt Exception was thrown");
+ fail("An interrupt Exception was thrown");
+ }
+
+ /*
+ * Make sure the next notification is delivered
+ */
+ obj = engine.subscribe("UEB", "POLICY-CL-MGT");
+ assertNotNull(obj);
+ logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
+
+ /*
+ * The ControlLoopNotification should be
+ * an OPERATION_SUCCESS
+ */
+ assertTrue(obj instanceof VirtualControlLoopNotification);
+ assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION_SUCCESS));
+
+ /*
+ * Now simulate the abatement sent from DCAE
+ */
+ try {
+ sendAbatement(pair.a, requestID, triggerSourceName);
+ } catch (InterruptedException e1) {
+ e1.printStackTrace();
+ logger.debug("Abatement could not be sent");
+ fail("Abatement could not be sent");
+ }
+
+ /*
+ * Give time to finish processing
+ */
+ try {
+ Thread.sleep(20000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ logger.debug("An interrupt Exception was thrown");
+ fail("An interrupt Exception was thrown");
+ }
+
+ /*
+ * This should be the final notification from the Policy Engine
+ */
+ obj = engine.subscribe("UEB", "POLICY-CL-MGT");
+ assertNotNull(obj);
+ logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
+
+ /*
+ * The ControlLoopNotification should be of type FINAL_SUCCESS
+ */
+ assertTrue(obj instanceof VirtualControlLoopNotification);
+ assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.FINAL_SUCCESS));
+
+ /*
+ * One final check to make sure the lock is released
+ */
+ assertFalse(PolicyGuard.isLocked(TargetType.VM, triggerSourceName, requestID));
+ }
+ else {
+ fail("Operation Denied by Guard");
+ }
+
+ /*
+ * This will stop the thread that is firing the rules
+ */
+ kieSession.halt();
+
+ /*
+ * The only fact in memory should be Params
+ */
+ assertEquals(1, kieSession.getFactCount());
+
+ /*
+ * Print what's left in memory
+ */
+ dumpFacts(kieSession);
+
+ /*
+ * Gracefully shut down the kie session
+ */
+ kieSession.dispose();
+ }
+
+ /**
+ * This method will start a kie session and instantiate
+ * the Policy Engine.
+ *
+ * @param droolsTemplate
+ * the DRL rules file
+ * @param yamlFile
+ * the yaml file containing the policies
+ * @param policyScope
+ * scope for policy
+ * @param policyName
+ * name of the policy
+ * @param policyVersion
+ * version of the policy
+ * @return the kieSession to be used to insert facts
+ * @throws IOException
+ */
+ private KieSession startSession(String droolsTemplate,
+ String yamlFile,
+ String policyScope,
+ String policyName,
+ String policyVersion) throws IOException {
+
+ /*
+ * Load policies from yaml
+ */
+ pair = Util.loadYaml(yamlFile);
+ assertNotNull(pair);
+ assertNotNull(pair.a);
+ assertNotNull(pair.a.getControlLoop());
+ assertNotNull(pair.a.getControlLoop().getControlLoopName());
+ assertTrue(pair.a.getControlLoop().getControlLoopName().length() > 0);
+
+ /*
+ * Construct a kie session
+ */
+ final KieSession kieSession = Util.buildContainer(droolsTemplate,
+ pair.a.getControlLoop().getControlLoopName(),
+ policyScope,
+ policyName,
+ policyVersion,
+ URLEncoder.encode(pair.b, "UTF-8"));
+
+ /*
+ * Retrieve the Policy Engine
+ */
+ engine = (PolicyEngineJUnitImpl) kieSession.getGlobal("Engine");
+
+ logger.debug("============");
+ logger.debug(URLEncoder.encode(pair.b, "UTF-8"));
+ logger.debug("============");
+
+ return kieSession;
+ }
+
+ /**
+ * This method is used to simulate event messages from DCAE
+ * that start the control loop (onset message).
+ *
+ * @param policy the controlLoopName comes from the policy
+ * @param requestID the requestId for this event
+ * @param triggerSourceName
+ * @throws InterruptedException
+ */
+ protected void sendOnset(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException {
+ VirtualControlLoopEvent event = new VirtualControlLoopEvent();
+ event.closedLoopControlName = policy.getControlLoop().getControlLoopName();
+ event.requestID = requestID;
+ event.target = "vserver.vserver-name";
+ event.closedLoopAlarmStart = Instant.now();
+ event.AAI = new HashMap<>();
+ event.AAI.put("cloud-region.identity-url", "foo");
+ event.AAI.put("vserver.selflink", "bar");
+ event.AAI.put("vserver.is-closed-loop-disabled", "false");
+ event.AAI.put("vserver.vserver-name", "testGenericVnfName");
+ event.closedLoopEventStatus = ControlLoopEventStatus.ONSET;
+ kieSession.insert(event);
+ Thread.sleep(2000);
+ }
+
+ /**
+ * This method is used to simulate event messages from DCAE
+ * that end the control loop (abatement message).
+ *
+ * @param policy the controlLoopName comes from the policy
+ * @param requestID the requestId for this event
+ * @param triggerSourceName
+ * @throws InterruptedException
+ */
+ protected void sendAbatement(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException {
+ VirtualControlLoopEvent event = new VirtualControlLoopEvent();
+ event.closedLoopControlName = policy.getControlLoop().getControlLoopName();
+ event.requestID = requestID;
+ event.target = "vserver.vserver-name";
+ event.closedLoopAlarmStart = Instant.now().minusSeconds(5);
+ event.closedLoopAlarmEnd = Instant.now();
+ event.AAI = new HashMap<>();
+ event.AAI.put("cloud-region.identity-url", "foo");
+ event.AAI.put("vserver.selflink", "bar");
+ event.AAI.put("vserver.is-closed-loop-disabled", "false");
+ event.AAI.put("generic-vnf.vnf-name", "testGenericVnfName");
+ event.closedLoopEventStatus = ControlLoopEventStatus.ABATED;
+ kieSession.insert(event);
+ }
+
+ /**
+ * This method will dump all the facts in the working memory.
+ *
+ * @param kieSession the session containing the facts
+ */
+ public void dumpFacts(KieSession kieSession) {
+ logger.debug("Fact Count: {}", kieSession.getFactCount());
+ for (FactHandle handle : kieSession.getFactHandles()) {
+ logger.debug("FACT: {}", handle);
+ }
+ }
+}
diff --git a/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vCPE.yaml b/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vCPE.yaml
new file mode 100644
index 000000000..de2ece4ed
--- /dev/null
+++ b/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vCPE.yaml
@@ -0,0 +1,23 @@
+controlLoop:
+ version: 2.0.0
+ controlLoopName: ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e
+ trigger_policy: unique-policy-id-1-restart
+ timeout: 3600
+ abatement: true
+
+policies:
+ - id: unique-policy-id-1-restart
+ name: Restart the VM
+ description:
+ actor: APPC
+ recipe: Restart
+ target:
+ type: VM
+ retry: 3
+ timeout: 1200
+ success: final_success
+ failure: final_failure
+ failure_timeout: final_failure_timeout
+ failure_retries: final_failure_retries
+ failure_exception: final_failure_exception
+ failure_guard: final_failure_guard
diff --git a/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vFW.yaml b/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vFW.yaml
new file mode 100644
index 000000000..e78b1ca33
--- /dev/null
+++ b/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vFW.yaml
@@ -0,0 +1,28 @@
+controlLoop:
+ version: 2.0.0
+ controlLoopName: ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a
+ services:
+ - serviceInvariantUUID: 5cfe6f4a-41bc-4247-8674-ebd4b98e35cc
+ serviceUUID: 0f40bba5-986e-4b3c-803f-ddd1b7b25f24
+ serviceName: 57e66ea7-0ed6-45c7-970f
+ trigger_policy: unique-policy-id-1-modifyConfig
+ timeout: 1200
+ abatement: true
+
+policies:
+ - id: unique-policy-id-1-modifyConfig
+ name: modify packet gen config
+ description:
+ actor: APPC
+ recipe: ModifyConfig
+ target:
+ resourceID: Eace933104d443b496b8.nodes.heat.vpg
+ type: VM
+ retry: 0
+ timeout: 300
+ success: final_success
+ failure: final_failure
+ failure_timeout: final_failure_timeout
+ failure_retries: final_failure_retries
+ failure_exception: final_failure_exception
+ failure_guard: final_failure_guard
diff --git a/controlloop/templates/template.demo/src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml b/controlloop/templates/template.demo/src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml
new file mode 100644
index 000000000..a94d4f231
--- /dev/null
+++ b/controlloop/templates/template.demo/src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml
@@ -0,0 +1,26 @@
+guard:
+ version: 2.0.0
+
+guards:
+ - id: unique_guard_6
+ name: APPC 6 ModifyConfig
+ description: |
+ We only allow 2 ModifyConfig over 10 minute window during the day time hours (avoid midnight to 5am)
+ match_parameters:
+ controlLoopName: ControlLoop-Service123-cbed919f-2212-4ef7-8051-fe6308da1bda
+ actor: APPC
+ recipe: ModifyConfig
+ targets:
+ - s1
+ - s2
+ - foobartriggersource36
+ - s3
+ - testGenericVnfName
+ limit_constraints:
+ - freq_limit_per_target: 1
+ time_window:
+ value: 10
+ units: minute
+ active_time_range:
+ start: 00:00:00-05:00
+ end: 23:59:59-05:00 \ No newline at end of file