diff options
Diffstat (limited to 'controlloop/templates/template.demo.clc/src/test')
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 |