aboutsummaryrefslogtreecommitdiffstats
path: root/controlloop/templates/template.demo.clc/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'controlloop/templates/template.demo.clc/src/test')
-rw-r--r--controlloop/templates/template.demo.clc/src/test/java/org/onap/policy/template/demo/clc/ControlLoopCoordinationTest.java497
-rw-r--r--controlloop/templates/template.demo.clc/src/test/java/org/onap/policy/template/demo/clc/Util.java297
-rw-r--r--controlloop/templates/template.demo.clc/src/test/resources/META-INF/persistence.xml48
-rw-r--r--controlloop/templates/template.demo.clc/src/test/resources/xacml/synthetic_control_loop_one_blocks_synthetic_control_loop_two.xml51
-rw-r--r--controlloop/templates/template.demo.clc/src/test/resources/xacml/xacml_guard_clc.properties65
-rw-r--r--controlloop/templates/template.demo.clc/src/test/resources/yaml/policy_ControlLoop_SyntheticOne.yaml43
-rw-r--r--controlloop/templates/template.demo.clc/src/test/resources/yaml/policy_ControlLoop_SyntheticTwo.yaml43
7 files changed, 1044 insertions, 0 deletions
diff --git a/controlloop/templates/template.demo.clc/src/test/java/org/onap/policy/template/demo/clc/ControlLoopCoordinationTest.java b/controlloop/templates/template.demo.clc/src/test/java/org/onap/policy/template/demo/clc/ControlLoopCoordinationTest.java
new file mode 100644
index 000000000..2d6279f32
--- /dev/null
+++ b/controlloop/templates/template.demo.clc/src/test/java/org/onap/policy/template/demo/clc/ControlLoopCoordinationTest.java
@@ -0,0 +1,497 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * demo
+ * ================================================================================
+ * Copyright (C) 2018 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.clc;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.att.research.xacml.util.XACMLProperties;
+
+import com.google.gson.Gson;
+
+import java.io.IOException;
+import java.lang.StringBuilder;
+import java.net.URLEncoder;
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Properties;
+import java.util.UUID;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+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.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
+import org.onap.policy.common.endpoints.event.comm.TopicListener;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
+import org.onap.policy.common.endpoints.http.server.HttpServletServer;
+import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
+import org.onap.policy.controlloop.ControlLoopEventStatus;
+import org.onap.policy.controlloop.ControlLoopNotificationType;
+import org.onap.policy.controlloop.ControlLoopTargetType;
+import org.onap.policy.controlloop.VirtualControlLoopEvent;
+import org.onap.policy.controlloop.VirtualControlLoopNotification;
+import org.onap.policy.controlloop.policy.ControlLoopPolicy;
+import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
+import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
+import org.onap.policy.drools.system.PolicyController;
+import org.onap.policy.drools.system.PolicyEngine;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ControlLoopCoordinationTest implements TopicListener {
+
+ private static final Logger logger = LoggerFactory.getLogger(ControlLoopCoordinationTest.class);
+
+ private static List<? extends TopicSink> noopTopics;
+
+ private static KieSession kieSession1;
+ private static KieSession kieSession2;
+ private static StringBuilder controlLoopOneName = new StringBuilder();
+ private static StringBuilder controlLoopTwoName = new StringBuilder();
+ private static String expectedDecision;
+
+ static {
+ /* Set environment properties */
+ Util.setAaiProps();
+ Util.setGuardPropsEmbedded();
+ Util.setPuProp();
+ }
+
+ /**
+ * Setup simulator.
+ */
+ @BeforeClass
+ public static void setUpSimulator() {
+ PolicyEngine.manager.configure(new Properties());
+ assertTrue(PolicyEngine.manager.start());
+ Properties noopSinkProperties = new Properties();
+ noopSinkProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, "APPC-LCM-READ,POLICY-CL-MGT");
+ noopSinkProperties.put("noop.sink.topics.APPC-LCM-READ.events", "org.onap.policy.appclcm.LcmRequestWrapper");
+ noopSinkProperties.put("noop.sink.topics.APPC-LCM-READ.events.custom.gson",
+ "org.onap.policy.appclcm.util.Serialization,gson");
+ noopSinkProperties.put("noop.sink.topics.POLICY-CL-MGT.events",
+ "org.onap.policy.controlloop.VirtualControlLoopNotification");
+ noopSinkProperties.put("noop.sink.topics.POLICY-CL-MGT.events.custom.gson",
+ "org.onap.policy.controlloop.util.Serialization,gsonPretty");
+ noopTopics = TopicEndpoint.manager.addTopicSinks(noopSinkProperties);
+
+ EventProtocolCoder.manager.addEncoder("junit.groupId", "junit.artifactId", "POLICY-CL-MGT",
+ "org.onap.policy.controlloop.VirtualControlLoopNotification", new JsonProtocolFilter(), null, null,
+ 1111);
+ EventProtocolCoder.manager.addEncoder("junit.groupId", "junit.artifactId", "APPC-LCM-READ",
+ "org.onap.policy.appclcm.LcmRequestWrapper", new JsonProtocolFilter(), null, null, 1111);
+ try {
+ Util.buildAaiSim();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ /*
+ * Start the kie sessions
+ */
+ try {
+ kieSession1 = startSession(
+ controlLoopOneName,
+ "src/main/resources/__closedLoopControlName__.drl",
+ "src/test/resources/yaml/policy_ControlLoop_SyntheticOne.yaml",
+ "service=ServiceDemo;resource=Res1Demo;type=operational",
+ "SyntheticControlLoopOnePolicy",
+ "org.onap.closed_loop.ServiceDemo:VNFS:1.0.0");
+ kieSession2 = startSession(
+ controlLoopTwoName,
+ "src/main/resources/__closedLoopControlName__.drl",
+ "src/test/resources/yaml/policy_ControlLoop_SyntheticTwo.yaml",
+ "service=ServiceDemo;resource=Res1Demo;type=operational",
+ "SyntheticControlLoopTwoPolicy",
+ "org.onap.closed_loop.ServiceDemo:VNFS:1.0.0");
+ } catch (IOException e) {
+ logger.debug("Could not create kieSession, exception {}", e.getMessage());
+ fail("Could not create kieSession");
+ }
+ }
+
+ /**
+ * Tear down simulator.
+ */
+ @AfterClass
+ public static void tearDownSimulator() {
+ /*
+ * Gracefully shut down the kie session
+ */
+ kieSession1.dispose();
+ kieSession2.dispose();
+
+ PolicyEngine.manager.stop();
+ HttpServletServer.factory.destroy();
+ PolicyController.factory.shutdown();
+ TopicEndpoint.manager.shutdown();
+ }
+
+ /**
+ * Set expected decision.
+ *
+ * @param ed the expected decision ("PERMIT" or "DENY")
+ */
+ public void expectedDecisionIs(String ed) {
+ expectedDecision = ed;
+ logger.info("Expected decision is {}", ed);
+ }
+
+ /**
+ * This method is used to simulate event messages from DCAE
+ * that start the control loop (onset message) or end the
+ * control loop (abatement message).
+ *
+ * @param controlLoopName the control loop name
+ * @param requestID the requestId for this event
+ * @param status could be onset or abated
+ * @param target the target name
+ * @param kieSession the kieSession to which this event is being sent
+ */
+ protected void sendEvent(String controlLoopName,
+ UUID requestId,
+ ControlLoopEventStatus status,
+ String target,
+ KieSession kieSession) {
+ logger.debug("sendEvent controlLoopName={}", controlLoopName);
+ VirtualControlLoopEvent event = new VirtualControlLoopEvent();
+ event.setClosedLoopControlName(controlLoopName);
+ event.setRequestId(requestId);
+ event.setTarget("generic-vnf.vnf-name");
+ event.setTargetType(ControlLoopTargetType.VNF);
+ event.setClosedLoopAlarmStart(Instant.now());
+ event.setAai(new HashMap<>());
+ event.getAai().put("generic-vnf.vnf-name", target);
+ event.setClosedLoopEventStatus(status);
+
+ Gson gson = new Gson();
+ String json = gson.toJson(event);
+ logger.debug("sendEvent {}", json);
+
+ kieSession.insert(event);
+ }
+
+
+ /**
+ * Simulate an event by inserting into kieSession and firing rules as needed.
+ *
+ * @param cles the ControlLoopEventStatus
+ * @param rid the request ID
+ * @param controlLoopName the control loop name
+ * @param kieSession the kieSession to which this event is being sent
+ * @param expectedDecision the expected decision
+ */
+ protected void simulateEvent(ControlLoopEventStatus cles,
+ UUID rid,
+ String controlLoopName,
+ String target,
+ KieSession kieSession,
+ String expectedDecision) {
+ int waitMillis = 5000;
+ //
+ // if onset, set expected decision
+ //
+ if (cles == ControlLoopEventStatus.ONSET) {
+ expectedDecisionIs(expectedDecision);
+ }
+ //
+ // simulate sending event
+ //
+ sendEvent(controlLoopName, rid, cles, target, kieSession);
+ kieSession.fireUntilHalt();
+ //
+ // get dump of database entries and log
+ //
+ List entries = Util.dumpDb();
+ assertNotNull(entries);
+ logger.debug("dumpDB, {} entries", entries.size());
+ for (Object entry : entries) {
+ logger.debug("{}", entry);
+ }
+ //
+ // we are done
+ //
+ logger.info("simulateEvent: done");
+ }
+
+ /**
+ * Simulate an onset event.
+ *
+ * @param rid the request ID
+ * @param controlLoopName the control loop name
+ * @param kieSession the kieSession to which this event is being sent
+ * @param expectedDecision the expected decision
+ */
+ public void simulateOnset(UUID rid,
+ String controlLoopName,
+ String target,
+ KieSession kieSession,
+ String expectedDecision) {
+ simulateEvent(ControlLoopEventStatus.ONSET, rid, controlLoopName, target, kieSession, expectedDecision);
+ }
+
+ /**
+ * Simulate an abated event.
+ *
+ * @param rid the request ID
+ * @param controlLoopName the control loop name
+ * @param kieSession the kieSession to which this event is being sent
+ */
+ public void simulateAbatement(UUID rid,
+ String controlLoopName,
+ String target,
+ KieSession kieSession) {
+ simulateEvent(ControlLoopEventStatus.ABATED, rid, controlLoopName, target, kieSession, null);
+ }
+
+ /**
+ * 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 throws IO exception
+ */
+ private static KieSession startSession(StringBuilder controlLoopName,
+ String droolsTemplate,
+ String yamlFile,
+ String policyScope,
+ String policyName,
+ String policyVersion) throws IOException {
+
+ /*
+ * Load policies from yaml
+ */
+ Util.Pair<ControlLoopPolicy, String> pair = Util.loadYaml(yamlFile);
+ assertNotNull(pair);
+ assertNotNull(pair.first);
+ assertNotNull(pair.first.getControlLoop());
+ assertNotNull(pair.first.getControlLoop().getControlLoopName());
+ assertTrue(!pair.first.getControlLoop().getControlLoopName().isEmpty());
+
+ controlLoopName.append(pair.first.getControlLoop().getControlLoopName());
+ String yamlContents = pair.second;
+
+ /*
+ * Construct a kie session
+ */
+ final KieSession kieSession = Util.buildContainer(droolsTemplate,
+ controlLoopName.toString(),
+ policyScope,
+ policyName,
+ policyVersion,
+ URLEncoder.encode(yamlContents, "UTF-8"));
+
+ /*
+ * Retrieve the Policy Engine
+ */
+
+ logger.debug("============");
+ logger.debug(URLEncoder.encode(yamlContents, "UTF-8"));
+ logger.debug("============");
+
+ return kieSession;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.drools.PolicyEngineListener#newEventNotification(java.lang.String)
+ */
+ @Override
+ public void onTopicEvent(CommInfrastructure commType, String topic, String event) {
+ /*
+ * Pull the object that was sent out to DMAAP and make sure it is a ControlLoopNoticiation
+ * of type active
+ */
+ Object obj = null;
+ if ("POLICY-CL-MGT".equals(topic)) {
+ obj = org.onap.policy.controlloop.util.Serialization.gsonJunit.fromJson(event,
+ org.onap.policy.controlloop.VirtualControlLoopNotification.class);
+ } else if ("APPC-LCM-READ".equals(topic)) {
+ obj = org.onap.policy.appclcm.util.Serialization.gsonJunit.fromJson(event,
+ org.onap.policy.appclcm.LcmRequestWrapper.class);
+ }
+ assertNotNull(obj);
+ if (obj instanceof VirtualControlLoopNotification) {
+ VirtualControlLoopNotification notification = (VirtualControlLoopNotification) obj;
+ String policyName = notification.getPolicyName();
+ if (policyName.endsWith("EVENT")) {
+ logger.debug("Rule Fired: " + notification.getPolicyName());
+ assertTrue(ControlLoopNotificationType.ACTIVE.equals(notification.getNotification()));
+ } else if (policyName.endsWith("GUARD_NOT_YET_QUERIED")) {
+ logger.debug("Rule Fired: " + notification.getPolicyName());
+ assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification()));
+ assertNotNull(notification.getMessage());
+ assertTrue(notification.getMessage().startsWith("Sending guard query"));
+ } else if (policyName.endsWith("GUARD.RESPONSE")) {
+ logger.debug("Rule Fired: " + notification.getPolicyName());
+ assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification()));
+ assertNotNull(notification.getMessage());
+ // THESE ARE THE MOST CRITICAL ASSERTS
+ // TEST IF GUARD.RESPONSE IS CORRECT
+ logger.debug("Testing whether decision was {} as expected", expectedDecision);
+ assertTrue(notification.getMessage().toUpperCase().endsWith(expectedDecision));
+ } else if (policyName.endsWith("GUARD_PERMITTED")) {
+ logger.debug("Rule Fired: " + notification.getPolicyName());
+ assertEquals(ControlLoopNotificationType.OPERATION,notification.getNotification());
+ assertNotNull(notification.getMessage());
+ assertTrue(notification.getMessage().startsWith("actor=APPC"));
+ } else if (policyName.endsWith("OPERATION.TIMEOUT")) {
+ logger.debug("Rule Fired: " + notification.getPolicyName());
+ kieSession1.halt();
+ kieSession2.halt();
+ logger.debug("The operation timed out");
+ fail("Operation Timed Out");
+ } else if (policyName.endsWith("APPC.LCM.RESPONSE")) {
+ logger.debug("Rule Fired: " + notification.getPolicyName());
+ assertTrue(ControlLoopNotificationType.OPERATION_SUCCESS.equals(notification.getNotification()));
+ assertNotNull(notification.getMessage());
+ assertTrue(notification.getMessage().startsWith("actor=APPC"));
+ } else if (policyName.endsWith("EVENT.MANAGER")) {
+ logger.debug("Rule Fired: " + notification.getPolicyName());
+ if (notification.getMessage().endsWith("Closing the control loop.")
+ || notification.getMessage().equals("Waiting for abatement")) {
+ if (policyName.startsWith(controlLoopOneName.toString())) {
+ logger.debug("Halting kieSession1");
+ kieSession1.halt();
+ } else if (policyName.startsWith(controlLoopTwoName.toString())) {
+ logger.debug("Halting kieSession2");
+ kieSession2.halt();
+ } else {
+ fail("Unknown ControlLoop");
+ }
+ }
+ } else if (policyName.endsWith("EVENT.MANAGER.TIMEOUT")) {
+ logger.debug("Rule Fired: " + notification.getPolicyName());
+ kieSession1.halt();
+ kieSession2.halt();
+ logger.debug("The control loop timed out");
+ fail("Control Loop Timed Out");
+ }
+ } else if (obj instanceof LcmRequestWrapper) {
+ /*
+ * The request should be of type LCMRequestWrapper and the subrequestid should be 1
+ */
+ LcmRequestWrapper dmaapRequest = (LcmRequestWrapper) obj;
+ LcmRequest appcRequest = dmaapRequest.getBody();
+ assertEquals(appcRequest.getCommonHeader().getSubRequestId(),"1");
+
+ logger.debug("\n============ APPC received the request!!! ===========\n");
+
+ /*
+ * 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);
+ kieSession1.insert(dmaapResponse);
+ kieSession2.insert(dmaapResponse);
+ }
+ }
+
+ /**
+ * 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);
+ }
+ }
+
+ /**
+ * Test that SyntheticControlLoopOne blocks SyntheticControlLoopTwo
+ * is enforced correctly.
+ */
+ @Test
+ public void testSyntheticControlLoopOneBlocksSyntheticControlLoopTwo() throws InterruptedException {
+ logger.info("Beginning testSyntheticControlLoopOneBlocksSyntheticControlLoopTwo");
+ /*
+ * Allows the PolicyEngine to callback to this object to
+ * notify that there is an event ready to be pulled
+ * from the queue
+ */
+ for (TopicSink sink : noopTopics) {
+ assertTrue(sink.start());
+ sink.register(this);
+ }
+
+ /*
+ * Create unique requestIds
+ */
+ final UUID requestId1 = UUID.randomUUID();
+ final UUID requestId2 = UUID.randomUUID();
+ final UUID requestId3 = UUID.randomUUID();
+ final UUID requestId4 = UUID.randomUUID();
+ final UUID requestId5 = UUID.randomUUID();
+ final String cl1 = controlLoopOneName.toString();
+ final String cl2 = controlLoopTwoName.toString();
+ final String t1 = "TARGET_1";
+ final String t2 = "TARGET_2";
+
+ logger.info("@@@@@@@@@@ cl2 ONSET t1 (Success) @@@@@@@@@@");
+ simulateOnset(requestId1, cl2, t1, kieSession2,"PERMIT");
+ logger.info("@@@@@@@@@@ cl1 ONSET t1 @@@@@@@@@@");
+ simulateOnset(requestId2, cl1, t1, kieSession1,"PERMIT");
+ logger.info("@@@@@@@@@@ cl2 ABATED t1 @@@@@@@@@@");
+ simulateAbatement(requestId1, cl2, t1, kieSession2);
+ logger.info("@@@@@@@@@@ cl2 ONSET t1 (Fail) @@@@@@@@@@");
+ simulateOnset(requestId3, cl2, t1, kieSession2,"DENY");
+ logger.info("@@@@@@@@@@ cl2 ONSET t2 (Success) @@@@@@@@@@");
+ simulateOnset(requestId4, cl2, t2, kieSession2,"PERMIT");
+ logger.info("@@@@@@@@@@ cl2 ABATED t2 @@@@@@@@@@");
+ simulateAbatement(requestId4, cl2, t2, kieSession2);
+ logger.info("@@@@@@@@@@ cl1 ABATED t1 @@@@@@@@@@");
+ simulateAbatement(requestId2, cl1, t1, kieSession1);
+ logger.info("@@@@@@@@@@ cl2 ONSET t1 (Success) @@@@@@@@@@");
+ simulateOnset(requestId5, cl2, t1, kieSession2,"PERMIT");
+ logger.info("@@@@@@@@@@ cl2 ABATED t1 @@@@@@@@@@");
+ simulateAbatement(requestId5, cl2, t1, kieSession2);
+
+ /*
+ * Print what's left in memory
+ */
+ dumpFacts(kieSession1);
+ dumpFacts(kieSession2);
+ }
+}
+
diff --git a/controlloop/templates/template.demo.clc/src/test/java/org/onap/policy/template/demo/clc/Util.java b/controlloop/templates/template.demo.clc/src/test/java/org/onap/policy/template/demo/clc/Util.java
new file mode 100644
index 000000000..5b5aa2d9c
--- /dev/null
+++ b/controlloop/templates/template.demo.clc/src/test/java/org/onap/policy/template/demo/clc/Util.java
@@ -0,0 +1,297 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * demo
+ * ================================================================================
+ * Copyright (C) 2018 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.clc;
+
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.persistence.Query;
+
+import org.apache.commons.io.IOUtils;
+import org.kie.api.KieServices;
+import org.kie.api.builder.KieBuilder;
+import org.kie.api.builder.KieFileSystem;
+import org.kie.api.builder.Message;
+import org.kie.api.builder.ReleaseId;
+import org.kie.api.builder.Results;
+import org.kie.api.builder.model.KieModuleModel;
+import org.kie.api.runtime.KieContainer;
+import org.kie.api.runtime.KieSession;
+import org.onap.policy.common.endpoints.http.server.HttpServletServer;
+import org.onap.policy.controlloop.policy.ControlLoopPolicy;
+import org.onap.policy.controlloop.policy.guard.ControlLoopGuard;
+import org.onap.policy.drools.system.PolicyEngine;
+import org.onap.policy.guard.PolicyGuardYamlToXacml;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.Constructor;
+
+
+public final class Util {
+
+ private static final String OPSHISTPUPROP = "OperationsHistoryPU";
+ private static final Logger logger = LoggerFactory.getLogger(Util.class);
+
+ public static class Pair<A, B> {
+ public final A first;
+ public final B second;
+
+ public Pair(A first, B second) {
+ this.first = first;
+ this.second = second;
+ }
+ }
+
+ /**
+ * Load YAML.
+ *
+ * @param testFile test file to load
+ * @return the Pair of a policy and the yaml contents
+ */
+ public static Pair<ControlLoopPolicy, String> loadYaml(String testFile) {
+ try (InputStream is = new FileInputStream(new File(testFile))) {
+ String contents = IOUtils.toString(is, StandardCharsets.UTF_8);
+ //
+ // Read the yaml into our Java Object
+ //
+ Yaml yaml = new Yaml(new Constructor(ControlLoopPolicy.class));
+ Object obj = yaml.load(contents);
+
+ logger.debug(contents);
+
+ return new Pair<ControlLoopPolicy, String>((ControlLoopPolicy) obj, contents);
+ } catch (IOException e) {
+ fail(e.getLocalizedMessage());
+ }
+ return null;
+ }
+
+ /**
+ * Load the YAML guard policy.
+ *
+ * @param testFile the test file to load
+ * @return return the guard object
+ */
+ public static ControlLoopGuard loadYamlGuard(String testFile) {
+ try (InputStream is = new FileInputStream(new File(testFile))) {
+ String contents = IOUtils.toString(is, StandardCharsets.UTF_8);
+ //
+ // Read the yaml into our Java Object
+ //
+ Yaml yaml = new Yaml(new Constructor(ControlLoopGuard.class));
+ Object obj = yaml.load(contents);
+ return (ControlLoopGuard) obj;
+ } catch (IOException e) {
+ fail(e.getLocalizedMessage());
+ }
+ return null;
+ }
+
+ public static HttpServletServer buildAaiSim() throws InterruptedException, IOException {
+ return org.onap.policy.simulators.Util.buildAaiSim();
+ }
+
+ private static String generatePolicy(String ruleContents,
+ String closedLoopControlName,
+ String policyScope,
+ String policyName,
+ String policyVersion,
+ String controlLoopYaml) {
+
+ Pattern pattern = Pattern.compile("\\$\\{closedLoopControlName\\}");
+ Matcher matcher = pattern.matcher(ruleContents);
+ ruleContents = matcher.replaceAll(closedLoopControlName);
+
+ pattern = Pattern.compile("\\$\\{policyScope\\}");
+ matcher = pattern.matcher(ruleContents);
+ ruleContents = matcher.replaceAll(policyScope);
+
+ pattern = Pattern.compile("\\$\\{policyName\\}");
+ matcher = pattern.matcher(ruleContents);
+ ruleContents = matcher.replaceAll(policyName);
+
+ pattern = Pattern.compile("\\$\\{policyVersion\\}");
+ matcher = pattern.matcher(ruleContents);
+ ruleContents = matcher.replaceAll(policyVersion);
+
+ pattern = Pattern.compile("\\$\\{controlLoopYaml\\}");
+ matcher = pattern.matcher(ruleContents);
+ ruleContents = matcher.replaceAll(controlLoopYaml);
+
+ return ruleContents;
+ }
+
+ /**
+ * Build the container.
+ *
+ * @param droolsTemplate template
+ * @param closedLoopControlName control loop id
+ * @param policyScope policy scope
+ * @param policyName policy name
+ * @param policyVersion policy version
+ * @param yamlSpecification incoming yaml specification
+ * @return the Kie session
+ * @throws IOException if the container cannot be built
+ */
+ public static KieSession buildContainer(String droolsTemplate, String closedLoopControlName,
+ String policyScope, String policyName, String policyVersion,
+ String yamlSpecification) throws IOException {
+ //
+ // Get our Drools Kie factory
+ //
+ KieServices ks = KieServices.Factory.get();
+
+ KieModuleModel kieModule = ks.newKieModuleModel();
+
+ logger.debug("KMODULE:" + System.lineSeparator() + kieModule.toXML());
+
+ //
+ // Generate our drools rule from our template
+ //
+ KieFileSystem kfs = ks.newKieFileSystem();
+
+ kfs.writeKModuleXML(kieModule.toXML());
+ {
+ Path rule = Paths.get(droolsTemplate);
+ String ruleTemplate = new String(Files.readAllBytes(rule));
+ String drlContents = generatePolicy(ruleTemplate,
+ closedLoopControlName,
+ policyScope,
+ policyName,
+ policyVersion,
+ yamlSpecification);
+
+ kfs.write("src/main/resources/" + policyName + ".drl",
+ ks.getResources().newByteArrayResource(drlContents.getBytes()));
+ }
+ //
+ // Compile the rule
+ //
+ KieBuilder builder = ks.newKieBuilder(kfs).buildAll();
+ Results results = builder.getResults();
+ if (results.hasMessages(Message.Level.ERROR)) {
+ for (Message msg : results.getMessages()) {
+ logger.error(msg.toString());
+ }
+ throw new RuntimeException("Drools Rule has Errors");
+ }
+ for (Message msg : results.getMessages()) {
+ logger.debug(msg.toString());
+ }
+ //
+ // Create our kie Session and container
+ //
+ ReleaseId releaseId = ks.getRepository().getDefaultReleaseId();
+ logger.debug(releaseId.toString());
+ KieContainer keyContainer = ks.newKieContainer(releaseId);
+
+ return keyContainer.newKieSession();
+ }
+
+ /**
+ * Set the A&AI properties.
+ */
+ public static void setAaiProps() {
+ PolicyEngine.manager.setEnvironmentProperty("aai.url", "http://localhost:6666");
+ PolicyEngine.manager.setEnvironmentProperty("aai.username", "AAI");
+ PolicyEngine.manager.setEnvironmentProperty("aai.password", "AAI");
+ }
+
+ /**
+ * Set the Guard properties to use embedded XACML PDPEngine.
+ */
+ public static void setGuardPropsEmbedded() {
+ /*
+ * Guard PDP-x connection Properties. No URL specified -> use embedded PDPEngine.
+ */
+ PolicyEngine.manager.setEnvironmentProperty("prop.guard.propfile",
+ "src/test/resources/xacml/xacml_guard_clc.properties");
+ PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_USER, "python");
+ PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_PASS, "test");
+ PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_CLIENT_USER, "python");
+ PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_CLIENT_PASS, "test");
+ PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_ENV, "TEST");
+ PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_DISABLED, "false");
+ }
+
+ /**
+ * Set the operation history properties.
+ */
+ public static void setPuProp() {
+ System.setProperty(OPSHISTPUPROP, "TestOperationsHistoryPU");
+ }
+
+ /**
+ * Dump the contents of the History database.
+ *
+ * @return a list of the database entries
+ */
+ public static List dumpDb() {
+ //
+ // Connect to in-mem db
+ //
+ EntityManagerFactory emf = Persistence.createEntityManagerFactory("TestOperationsHistoryPU");
+ EntityManager em = emf.createEntityManager();
+ //
+ // Create query
+ //
+ String sql = "select * from operationshistory10";
+ Query nq = em.createNativeQuery(sql);
+ List results = null;
+ //
+ // Execute query
+ //
+ try {
+ results = nq.getResultList();
+ } catch (Exception ex) {
+ logger.error("getStatusFromDB threw: ", ex);
+ //
+ // Clean up and return null
+ //
+ em.close();
+ emf.close();
+ return null;
+ }
+ //
+ // Clean up and return results
+ //
+ em.close();
+ emf.close();
+ return results;
+ }
+}
diff --git a/controlloop/templates/template.demo.clc/src/test/resources/META-INF/persistence.xml b/controlloop/templates/template.demo.clc/src/test/resources/META-INF/persistence.xml
new file mode 100644
index 000000000..808cef9b6
--- /dev/null
+++ b/controlloop/templates/template.demo.clc/src/test/resources/META-INF/persistence.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ drools-applications
+ ================================================================================
+ Copyright (C) 2018 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=========================================================
+ -->
+<persistence version="2.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/persistence"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
+
+ <!-- In-mem DB for junit -->
+ <persistence-unit name="TestOperationsHistoryPU"
+ transaction-type="RESOURCE_LOCAL">
+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+ <class>org.onap.policy.controlloop.eventmanager.OperationsHistoryDbEntry</class>
+ <properties>
+ <property name="eclipselink.ddl-generation"
+ value="create-tables" />
+ <property name="javax.persistence.jdbc.driver"
+ value="org.h2.Driver" />
+ <property name="javax.persistence.jdbc.url"
+ value="jdbc:h2:mem:test" />
+ <property name="javax.persistence.jdbc.user"
+ value="sa" />
+ <property name="javax.persistence.jdbc.password"
+ value="" />
+ <property name="eclipselink.logging.level"
+ value="CONFIG" />
+ </properties>
+ </persistence-unit>
+
+
+</persistence>
diff --git a/controlloop/templates/template.demo.clc/src/test/resources/xacml/synthetic_control_loop_one_blocks_synthetic_control_loop_two.xml b/controlloop/templates/template.demo.clc/src/test/resources/xacml/synthetic_control_loop_one_blocks_synthetic_control_loop_two.xml
new file mode 100644
index 000000000..f503a2b11
--- /dev/null
+++ b/controlloop/templates/template.demo.clc/src/test/resources/xacml/synthetic_control_loop_one_blocks_synthetic_control_loop_two.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ============LICENSE_START=======================================================
+ drools-applications
+ ================================================================================
+ Copyright (C) 2018 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=========================================================
+ -->
+<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" PolicyId="urn:com:att:xacml:policy:id:son:guard:5" Version="1" RuleCombiningAlgId="urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:permit-unless-deny">
+<Description>Policy for first_blocks_second coordination (if first running and second requests to run, deny second).</Description>
+<Target>
+ <AnyOf>
+ <AllOf>
+ <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match">
+ <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">SyntheticControlLoopTwo</AttributeValue>
+ <!-- value should be autofilled by yaml from a xacml template -->
+ <AttributeDesignator Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" AttributeId="urn:oasis:names:tc:xacml:1.0:clname:clname-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/>
+ </Match>
+ </AllOf>
+ </AnyOf>
+</Target>
+
+<Rule RuleId="urn:com:att:xacml:rule:id:1" Effect="Deny">
+ <Description>First Is Running</Description>
+ <Condition>
+ <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
+ <VariableReference VariableId="clc_status"/>
+ <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Success</AttributeValue>
+ </Apply>
+ </Condition>
+</Rule>
+
+<!-- 'action_one' should be autofilled by yaml from a xacml template -->
+<VariableDefinition VariableId="clc_status">
+ <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-one-and-only">
+ <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="com:att:research:xacml:test:sql:resource:operations:status" DataType="http://www.w3.org/2001/XMLSchema#string" Issuer="org:onap:policy:guard:getstatus:clname:SyntheticControlLoopOne" MustBePresent="false"/>
+ </Apply>
+</VariableDefinition>
+</Policy>
diff --git a/controlloop/templates/template.demo.clc/src/test/resources/xacml/xacml_guard_clc.properties b/controlloop/templates/template.demo.clc/src/test/resources/xacml/xacml_guard_clc.properties
new file mode 100644
index 000000000..5f5e0c8b2
--- /dev/null
+++ b/controlloop/templates/template.demo.clc/src/test/resources/xacml/xacml_guard_clc.properties
@@ -0,0 +1,65 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP
+# ================================================================================
+# Copyright (C) 2018 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=========================================================
+###
+#
+#
+# This files defines PIPs that will be used by XACML Guard Policies. One PIP per time window (5 min, 10min,...,1 month).
+#
+#
+#
+
+#
+# Default XACML Properties File
+# Standard API Factories
+#
+xacml.dataTypeFactory=com.att.research.xacml.std.StdDataTypeFactory
+xacml.pdpEngineFactory=com.att.research.xacmlatt.pdp.ATTPDPEngineFactory
+xacml.pepEngineFactory=com.att.research.xacml.std.pep.StdEngineFactory
+xacml.pipFinderFactory=com.att.research.xacml.std.pip.StdPIPFinderFactory
+xacml.traceEngineFactory=com.att.research.xacml.std.trace.LoggingTraceEngineFactory
+#
+# AT&T PDP Implementation Factories
+#
+xacml.att.evaluationContextFactory=com.att.research.xacmlatt.pdp.std.StdEvaluationContextFactory
+xacml.att.combiningAlgorithmFactory=com.att.research.xacmlatt.pdp.std.StdCombiningAlgorithmFactory
+xacml.att.functionDefinitionFactory=com.att.research.xacmlatt.pdp.std.StdFunctionDefinitionFactory
+xacml.att.policyFinderFactory=com.att.research.xacmlatt.pdp.std.StdPolicyFinderFactory
+
+
+#
+# NOTE: If you are testing against a RESTful PDP, then the PDP must be configured with the
+# policies and PIP configuration as defined below. Otherwise, this is the configuration that
+# the embedded PDP uses.
+#
+
+# In case we have multiple applicable Guard policies, we will deny if any of them denies.
+#xacml.att.policyFinderFactory.combineRootPolicies=urn:com:att:xacml:3.0:policy-combining-algorithm:combined-deny-overrides
+xacml.att.policyFinderFactory.combineRootPolicies=urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:permit-unless-deny
+
+
+# Policies to load
+#
+xacml.rootPolicies=p1
+p1.file=src/test/resources/xacml/synthetic_control_loop_one_blocks_synthetic_control_loop_two.xml
+
+# PIP Engine Definition
+#
+xacml.pip.engines=getstatus
+getstatus.classname=org.onap.policy.guard.PipEngineGetStatus
+getstatus.issuer=org:onap:policy:guard:getstatus
diff --git a/controlloop/templates/template.demo.clc/src/test/resources/yaml/policy_ControlLoop_SyntheticOne.yaml b/controlloop/templates/template.demo.clc/src/test/resources/yaml/policy_ControlLoop_SyntheticOne.yaml
new file mode 100644
index 000000000..2a74843a0
--- /dev/null
+++ b/controlloop/templates/template.demo.clc/src/test/resources/yaml/policy_ControlLoop_SyntheticOne.yaml
@@ -0,0 +1,43 @@
+# Copyright 2018 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.
+controlLoop:
+ version: 2.0.0
+ controlLoopName: SyntheticControlLoopOne
+ services:
+ - serviceName: ServiceSimple
+ resources:
+ - resourceName: res1
+ resourceType: VFC
+ - resourceName: res2
+ resourceType: VFC
+ trigger_policy: unique-policy-id-1
+ timeout: 2500
+ abatement: true
+
+policies:
+ - id: unique-policy-id-1
+ name: SyntheticControlLoopOnePolicy
+ description:
+ actor: APPC
+ recipe: action_one
+ target:
+ type: VNF
+ retry: 3
+ timeout: 200
+ success: final_success
+ failure: final_failure
+ failure_timeout: final_failure_timeout
+ failure_retries: final_failure_retries
+ failure_guard: final_failure_guard
+ failure_exception: final_failure_exception
diff --git a/controlloop/templates/template.demo.clc/src/test/resources/yaml/policy_ControlLoop_SyntheticTwo.yaml b/controlloop/templates/template.demo.clc/src/test/resources/yaml/policy_ControlLoop_SyntheticTwo.yaml
new file mode 100644
index 000000000..12e1bdf2b
--- /dev/null
+++ b/controlloop/templates/template.demo.clc/src/test/resources/yaml/policy_ControlLoop_SyntheticTwo.yaml
@@ -0,0 +1,43 @@
+# Copyright 2018 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.
+controlLoop:
+ version: 2.0.0
+ controlLoopName: SyntheticControlLoopTwo
+ services:
+ - serviceName: ServiceSimple
+ resources:
+ - resourceName: res1
+ resourceType: VFC
+ - resourceName: res2
+ resourceType: VFC
+ trigger_policy: unique-policy-id-1
+ timeout: 2500
+ abatement: true
+
+policies:
+ - id: unique-policy-id-1
+ name: SyntheticControlLoopTwoPolicy
+ description:
+ actor: APPC
+ recipe: action_two
+ target:
+ type: VNF
+ retry: 3
+ timeout: 200
+ success: final_success
+ failure: final_failure
+ failure_timeout: final_failure_timeout
+ failure_retries: final_failure_retries
+ failure_guard: final_failure_guard
+ failure_exception: final_failure_exception