From fca3dd7b4bdc33b579750004c9d3bc163d20a2a7 Mon Sep 17 00:00:00 2001 From: Joshua Reich Date: Mon, 8 Apr 2019 09:41:36 -0700 Subject: Add Control Loop Coordination policy. Refactor code to support multiple pip engines. Add pip engine for outcome. Modify LegacyGuardTranslator to use coordination translator's convertPolicy function when processing coordination guard. This version of convertPolicy intentionally uses string replacement on template-like xacml coordination guard to enable future support for API-based creation of new coordination guard types. Bug fixes and code cleanup. * Unused imports, sonar problems. * Consolidation of getAttribute method * Only use TypedQuery for Pips Issue-ID: POLICY-1471 Change-Id: I4e9365b7f23bee96cf438dad44feda97c65f6ecc Signed-off-by: Joshua Reich Signed-off-by: Pamela Dragosh --- .../application/guard/CoordinationDirective.java | 43 +++ .../guard/CoordinationGuardTranslator.java | 166 ++++++++++++ .../pdp/application/guard/GuardPdpApplication.java | 25 +- .../guard/LegacyGuardPolicyRequest.java | 3 + .../application/guard/LegacyGuardTranslator.java | 6 +- ...olloop.guard.coordination.FirstBlocksSecond.xml | 63 +++++ .../pdp/application/guard/CoordinationTest.java | 298 +++++++++++++++++++++ .../application/guard/GuardPdpApplicationTest.java | 34 ++- .../src/test/resources/META-INF/persistence.xml | 8 +- .../requests/coordination.cl.1.node.1.json | 15 ++ .../requests/coordination.cl.1.node.2.json | 15 ++ .../requests/coordination.cl.2.node.1.json | 15 ++ .../requests/coordination.cl.2.node.2.json | 16 ++ .../test/resources/requests/guard.vfCount.1.json | 16 ++ .../test/resources/requests/guard.vfCount.3.json | 16 ++ .../test/resources/requests/guard.vfCount.6.json | 16 ++ ...guard.coordination.firstBlocksSecond.tosca.yaml | 14 + .../guard/src/test/resources/xacml.properties | 29 +- 18 files changed, 761 insertions(+), 37 deletions(-) create mode 100644 applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/CoordinationDirective.java create mode 100644 applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/CoordinationGuardTranslator.java create mode 100644 applications/guard/src/main/resources/coordination/function/onap.policies.controlloop.guard.coordination.FirstBlocksSecond.xml create mode 100644 applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/CoordinationTest.java create mode 100644 applications/guard/src/test/resources/requests/coordination.cl.1.node.1.json create mode 100644 applications/guard/src/test/resources/requests/coordination.cl.1.node.2.json create mode 100644 applications/guard/src/test/resources/requests/coordination.cl.2.node.1.json create mode 100644 applications/guard/src/test/resources/requests/coordination.cl.2.node.2.json create mode 100644 applications/guard/src/test/resources/requests/guard.vfCount.1.json create mode 100644 applications/guard/src/test/resources/requests/guard.vfCount.3.json create mode 100644 applications/guard/src/test/resources/requests/guard.vfCount.6.json create mode 100644 applications/guard/src/test/resources/test.policy.guard.coordination.firstBlocksSecond.tosca.yaml (limited to 'applications/guard/src') diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/CoordinationDirective.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/CoordinationDirective.java new file mode 100644 index 00000000..91f8ed2d --- /dev/null +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/CoordinationDirective.java @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2019 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.xacml.pdp.application.guard; + +import java.io.Serializable; +import java.util.List; + +import lombok.Data; + +@Data +public class CoordinationDirective implements Serializable { + private static final long serialVersionUID = 6897293694639777548L; + private List controlLoop; + private String coordinationFunction; + + /** + * gets the ith control loop. + * + * @param index the control loop's index + * @return the CoordinationDirective's string representation + */ + public String getControlLoop(int index) { + return controlLoop.get(index); + } +} diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/CoordinationGuardTranslator.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/CoordinationGuardTranslator.java new file mode 100644 index 00000000..c296526b --- /dev/null +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/CoordinationGuardTranslator.java @@ -0,0 +1,166 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2019 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.xacml.pdp.application.guard; + +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.util.XACMLPolicyScanner; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType; + +import org.apache.commons.io.IOUtils; +import org.onap.policy.models.decisions.concepts.DecisionRequest; +import org.onap.policy.models.decisions.concepts.DecisionResponse; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; + +public class CoordinationGuardTranslator implements ToscaPolicyTranslator { + + private static final Logger LOGGER = LoggerFactory.getLogger(CoordinationGuardTranslator.class); + + public CoordinationGuardTranslator() { + super(); + } + + @Override + public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException { + LOGGER.debug("Using CoordinationGuardTranslator.convertPolicy"); + // + // Policy name should be at the root + // + String policyName = toscaPolicy.getMetadata().get("policy-id"); + String type = toscaPolicy.getType(); + String coordinationFunctionPath = "src/main/resources/coordination/function"; + Map policyProps = toscaPolicy.getProperties(); + LOGGER.debug("path = {}", coordinationFunctionPath); + LOGGER.debug("props = {}", policyProps); + List controlLoop = (List) policyProps.get("controlLoop"); + CoordinationDirective cd = new CoordinationDirective(); + cd.setCoordinationFunction(type); + cd.setControlLoop(controlLoop); + LOGGER.debug("CoordinationDirective = {}", cd); + + String xacmlStr = generateXacmlFromCoordinationDirective(cd, coordinationFunctionPath); + + LOGGER.debug("xacmlStr\n{}", xacmlStr); + PolicyType scannedPolicy = null; + try (InputStream is = new ByteArrayInputStream(xacmlStr.getBytes(StandardCharsets.UTF_8))) { + scannedPolicy = (PolicyType) XACMLPolicyScanner.readPolicy(is); + } catch (IOException e) { + LOGGER.error("Failed to read policy", e); + } + return scannedPolicy; + } + + @Override + public Request convertRequest(DecisionRequest request) { + LOGGER.info("this convertRequest shouldn't be used"); + return null; + } + + @Override + public DecisionResponse convertResponse(Response xacmlResponse) { + LOGGER.info("this convertRequest shouldn't be used"); + return null; + } + + /** + * Load YAML coordination directive. + * + * @param directiveFilename yaml directive file to load + * @return the CoordinationDirective + */ + public static CoordinationDirective loadCoordinationDirectiveFromFile(String directiveFilename) { + try (InputStream is = new FileInputStream(new File(directiveFilename))) { + String contents = IOUtils.toString(is, StandardCharsets.UTF_8); + // + // Read the yaml into our Java Object + // + Yaml yaml = new Yaml(new Constructor(CoordinationDirective.class)); + Object obj = yaml.load(contents); + + LOGGER.debug(contents); + + return (CoordinationDirective) obj; + } catch (IOException e) { + LOGGER.error("Error while loading YAML coordination directive", e); + } + return null; + } + + /** + * Generate Xacml rule implementing specified CoordinationDirective. + * + * @param cd the CoordinationDirective + * @param protoDir the directory containing Xacml implementation prototypes + * @return the generated Xacml policy + */ + public static String generateXacmlFromCoordinationDirective(CoordinationDirective cd, + String protoDir) { + /* + * Determine file names + */ + String xacmlProtoFilename = protoDir + File.separator + cd.getCoordinationFunction() + ".xml"; + LOGGER.debug("xacmlProtoFilename={}", xacmlProtoFilename); + /* + * Values to be used for placeholders + */ + final String uniqueId = UUID.randomUUID().toString(); + final String cLOne = cd.getControlLoop(0); + final String cLTwo = cd.getControlLoop(1); + /* + * Replace prototype placeholders with appropriate values + */ + String xacmlPolicy = null; + try (Stream stream = Files.lines(Paths.get(xacmlProtoFilename))) { + xacmlPolicy = stream.map(s -> s.replaceAll("UNIQUE_ID", uniqueId)) + .map(s -> s.replaceAll("CONTROL_LOOP_ONE", cLOne)) + .map(s -> s.replaceAll("CONTROL_LOOP_TWO", cLTwo)) + .collect(Collectors.joining(System.lineSeparator())); + } catch (IOException e) { + LOGGER.error("Error while generating XACML policy for coordination directive", e); + } + return xacmlPolicy; + } + +} diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java index 0b3b1542..55568c36 100644 --- a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java @@ -43,15 +43,22 @@ public class GuardPdpApplication extends StdXacmlApplicationServiceProvider { private static final Logger LOGGER = LoggerFactory.getLogger(GuardPdpApplication.class); private static final String STRING_VERSION100 = "1.0.0"; private List supportedPolicyTypes = new ArrayList<>(); - private LegacyGuardTranslator translator = new LegacyGuardTranslator(); + private LegacyGuardTranslator legacyTranslator = new LegacyGuardTranslator(); + private CoordinationGuardTranslator coordinationTranslator = new CoordinationGuardTranslator(); + /** Constructor. * */ public GuardPdpApplication() { - this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier("onap.policies.controlloop.guard.FrequencyLimiter", + this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier( + "onap.policies.controlloop.guard.FrequencyLimiter", + STRING_VERSION100)); + this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier( + "onap.policies.controlloop.guard.MinMax", STRING_VERSION100)); - this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier("onap.policies.controlloop.guard.MinMax", + this.supportedPolicyTypes.add(new ToscaPolicyTypeIdentifier( + "onap.policies.controlloop.guard.coordination.FirstBlocksSecond", STRING_VERSION100)); } @@ -85,7 +92,15 @@ public class GuardPdpApplication extends StdXacmlApplicationServiceProvider { } @Override - protected ToscaPolicyTranslator getTranslator() { - return translator; + protected ToscaPolicyTranslator getTranslator(String type) { + LOGGER.debug("Policy type {}", type); + if ( type.contains("coordination") ) { + LOGGER.debug("returning coordinationTranslator"); + return coordinationTranslator; + } else { + LOGGER.debug("returning legacyTranslator"); + return legacyTranslator; + } } + } diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java index fa04e6bd..7b6c37a6 100644 --- a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java @@ -34,6 +34,7 @@ import lombok.Setter; import lombok.ToString; import org.onap.policy.models.decisions.concepts.DecisionRequest; +import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; @Getter @Setter @@ -42,6 +43,7 @@ import org.onap.policy.models.decisions.concepts.DecisionRequest; public class LegacyGuardPolicyRequest { private static final String STR_GUARD = "guard"; + private static final String URN_ONAP = ToscaDictionary.URN_ONAP; @XACMLSubject(includeInResults = true) private String onapName; @@ -79,6 +81,7 @@ public class LegacyGuardPolicyRequest { @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:max") private Integer max; + public LegacyGuardPolicyRequest() { super(); } diff --git a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java index 77dbb353..28e62b73 100644 --- a/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java +++ b/applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java @@ -57,6 +57,7 @@ import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator; import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils; +import org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -167,7 +168,6 @@ public class LegacyGuardTranslator implements ToscaPolicyTranslator { return decisionResponse; } - /** * From the TOSCA metadata section, pull in values that are needed into the XACML policy. * @@ -527,7 +527,9 @@ public class LegacyGuardTranslator implements ToscaPolicyTranslator { // // Right now I am faking the count value by re-using the request-id field // - String issuer = ToscaDictionary.GUARD_ISSUER + ":tw:" + timeWindow + ":" + timeUnits; + String issuer = ToscaDictionary.GUARD_ISSUER_PREFIX + + CountRecentOperationsPip.ISSUER_NAME + + ":tw:" + timeWindow + ":" + timeUnits; designator.setIssuer(issuer); AttributeValueType valueLimit = new AttributeValueType(); diff --git a/applications/guard/src/main/resources/coordination/function/onap.policies.controlloop.guard.coordination.FirstBlocksSecond.xml b/applications/guard/src/main/resources/coordination/function/onap.policies.controlloop.guard.coordination.FirstBlocksSecond.xml new file mode 100644 index 00000000..bea05f26 --- /dev/null +++ b/applications/guard/src/main/resources/coordination/function/onap.policies.controlloop.guard.coordination.FirstBlocksSecond.xml @@ -0,0 +1,63 @@ + + + + + Policy for first_blocks_second coordination (if first + running and second requests to run, deny second). + + + + + CONTROL_LOOP_TWO + + + + + + + + First Is Running + + + + + + Success + + + + diff --git a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/CoordinationTest.java b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/CoordinationTest.java new file mode 100644 index 00000000..e94ad712 --- /dev/null +++ b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/CoordinationTest.java @@ -0,0 +1,298 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2019 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.xacml.pdp.application.guard; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.IOException; +import java.sql.Date; +import java.time.Instant; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; +import java.util.ServiceLoader; +import java.util.UUID; + +import javax.persistence.EntityManager; +import javax.persistence.Persistence; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.runners.MethodSorters; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.common.utils.resources.TextFileUtils; +import org.onap.policy.models.decisions.concepts.DecisionRequest; +import org.onap.policy.models.decisions.concepts.DecisionResponse; +import org.onap.policy.pdp.xacml.application.common.TestUtils; +import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException; +import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider; +import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils; +import org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip; +import org.onap.policy.pdp.xacml.application.common.operationshistory.Dbao; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class CoordinationTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(CoordinationTest.class); + private static Properties properties = new Properties(); + private static File propertiesFile; + private static XacmlApplicationServiceProvider service; + private static DecisionRequest requestCl1Node1; + private static DecisionRequest requestCl1Node2; + private static DecisionRequest requestCl2Node1; + private static DecisionRequest requestCl2Node2; + private static StandardCoder gson = new StandardCoder(); + private static EntityManager em; + private static final String DENY = "Deny"; + private static final String PERMIT = "Permit"; + private static final String OPEN = "Success"; + private static final String CLOSE = "Closed"; + + + @ClassRule + public static final TemporaryFolder policyFolder = new TemporaryFolder(); + + /** + * Copies the xacml.properties and policies files into + * temporary folder and loads the service provider saving + * instance of provider off for other tests to use. + */ + @BeforeClass + public static void setup() throws Exception { + LOGGER.info("Setting up class"); + // + // Setup our temporary folder + // + XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename); + propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties", + properties, myCreator); + // + // Load service + // + ServiceLoader applicationLoader = + ServiceLoader.load(XacmlApplicationServiceProvider.class); + // + // Find the guard service application and save for use in all the tests + // + StringBuilder strDump = new StringBuilder("Loaded applications:" + System.lineSeparator()); + Iterator iterator = applicationLoader.iterator(); + while (iterator.hasNext()) { + XacmlApplicationServiceProvider application = iterator.next(); + // + // Is it our service? + // + if (application instanceof GuardPdpApplication) { + // + // Should be the first and only one + // + assertThat(service).isNull(); + service = application; + } + strDump.append(application.applicationName()); + strDump.append(" supports "); + strDump.append(application.supportedPolicyTypes()); + strDump.append(System.lineSeparator()); + } + LOGGER.info("{}", strDump); + // + // Tell it to initialize based on the properties file + // we just built for it. + // + service.initialize(propertiesFile.toPath().getParent()); + // + // Load Decision Requests + // + requestCl1Node1 = gson.decode( + TextFileUtils.getTextFileAsString( + "src/test/resources/requests/coordination.cl.1.node.1.json"), + DecisionRequest.class); + requestCl2Node1 = gson.decode( + TextFileUtils.getTextFileAsString( + "src/test/resources/requests/coordination.cl.2.node.1.json"), + DecisionRequest.class); + requestCl1Node2 = gson.decode( + TextFileUtils.getTextFileAsString( + "src/test/resources/requests/coordination.cl.1.node.2.json"), + DecisionRequest.class); + requestCl2Node2 = gson.decode( + TextFileUtils.getTextFileAsString( + "src/test/resources/requests/coordination.cl.2.node.2.json"), + DecisionRequest.class); + // + // Create EntityManager for manipulating DB + // + String persistenceUnit = CountRecentOperationsPip.ISSUER_NAME + ".persistenceunit"; + em = Persistence.createEntityManagerFactory( + CoordinationTest.properties.getProperty(persistenceUnit), properties) + .createEntityManager(); + } + + /** + * Clears the database before each test. + * + */ + @Before + public void startClean() throws Exception { + em.getTransaction().begin(); + em.createQuery("DELETE FROM Dbao").executeUpdate(); + em.getTransaction().commit(); + } + + /** + * Check that decision matches expectation. + * + * @param expected from the response + * @param response received + * + **/ + public void checkDecision(String expected, DecisionResponse response) throws CoderException { + LOGGER.info("Looking for {} Decision", expected); + assertThat(response).isNotNull(); + assertThat(response.getStatus()).isNotNull(); + assertThat(response.getStatus()).isEqualTo(expected); + // + // Dump it out as Json + // + LOGGER.info(gson.encode(response)); + } + + /** + * Request a decision and check that it matches expectation. + * + * @param request to send to Xacml PDP + * @param expected from the response + * + **/ + public void requestAndCheckDecision(DecisionRequest request, String expected) throws CoderException { + // + // Ask for a decision + // + DecisionResponse response = service.makeDecision(request); + // + // Check decision + // + checkDecision(expected, response); + } + + @Test + public void test1() throws CoderException, IOException, XacmlApplicationException { + LOGGER.info("**************** Running test1 ****************"); + // + // Now load the test coordination policy - make sure + // the pdp can support it and have it load + // into the PDP. + // + TestUtils.loadPolicies("src/test/resources/test.policy.guard.coordination.firstBlocksSecond.tosca.yaml", + service); + // + // cl1 doesn't have open action: cl2 should get permit + // + requestAndCheckDecision(requestCl2Node1, PERMIT); + // + // Open cl2 on node1 + // + insertOperationEvent(requestCl2Node1, OPEN); + // + // Under current coordination policy cl1 always can go + // + requestAndCheckDecision(requestCl1Node1, PERMIT); + // + // Open cl1 on node1 + // + insertOperationEvent(requestCl1Node1, OPEN); + // + // Close cl2 on node1 + // + insertOperationEvent(requestCl2Node1, CLOSE); + // + // Try cl2 again, cl1 has open action on node1: should get deny + // + requestAndCheckDecision(requestCl2Node1, DENY); + // + // Close cl1 on node1 + // + insertOperationEvent(requestCl1Node1, CLOSE); + // + // Under current coordination policy cl1 always can go + // + requestAndCheckDecision(requestCl1Node1, PERMIT); + // + // Open cl1 on node1 + // + insertOperationEvent(requestCl1Node1, OPEN); + // + // Try cl2 on node2, cl1 only open on node1: should get permit + // + requestAndCheckDecision(requestCl2Node2, PERMIT); + // + // Open cl2 on node2 + // + insertOperationEvent(requestCl2Node2, OPEN); + // + // Try cl2 on node1, cl1 open on node1: should get DENY + // + requestAndCheckDecision(requestCl2Node1, DENY); + } + + @SuppressWarnings("unchecked") + private void insertOperationEvent(DecisionRequest request, String outcome) { + // + // Get the properties + // + Map properties = (Map) request.getResource().get("guard"); + // + // Add an entry + // + Dbao newEntry = new Dbao(); + newEntry.setActor(properties.get("actor").toString()); + newEntry.setOperation(properties.get("recipe").toString()); + newEntry.setClosedLoopName(properties.get("clname").toString()); + newEntry.setOutcome(outcome); + newEntry.setStarttime(Date.from(Instant.now().minusMillis(20000))); + newEntry.setEndtime(Date.from(Instant.now())); + newEntry.setRequestId(UUID.randomUUID().toString()); + newEntry.setTarget(properties.get("target").toString()); + em.getTransaction().begin(); + em.persist(newEntry); + em.getTransaction().commit(); + } + + /** + * Close the entity manager. + */ + @AfterClass + public static void cleanup() throws Exception { + if (em != null) { + em.close(); + } + } +} diff --git a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java index 17917af0..c5cf0327 100644 --- a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java +++ b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java @@ -53,11 +53,12 @@ import org.onap.policy.common.utils.resources.TextFileUtils; import org.onap.policy.models.decisions.concepts.DecisionRequest; import org.onap.policy.models.decisions.concepts.DecisionResponse; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier; -import org.onap.policy.pdp.xacml.application.common.OnapOperationsHistoryDbao; import org.onap.policy.pdp.xacml.application.common.TestUtils; import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException; import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider; import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils; +import org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip; +import org.onap.policy.pdp.xacml.application.common.operationshistory.Dbao; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -85,7 +86,7 @@ public class GuardPdpApplicationTest { * instance of provider off for other tests to use. */ @BeforeClass - public static void setUp() throws Exception { + public static void setup() throws Exception { LOGGER.info("Setting up class"); // // Setup our temporary folder @@ -131,21 +132,22 @@ public class GuardPdpApplicationTest { // requestVfCount1 = gson.decode( TextFileUtils.getTextFileAsString( - "../../main/src/test/resources/decisions/decision.guard.vfCount.1.input.json"), + "src/test/resources/requests/guard.vfCount.1.json"), DecisionRequest.class); requestVfCount3 = gson.decode( TextFileUtils.getTextFileAsString( - "../../main/src/test/resources/decisions/decision.guard.vfCount.3.input.json"), + "src/test/resources/requests/guard.vfCount.3.json"), DecisionRequest.class); requestVfCount6 = gson.decode( TextFileUtils.getTextFileAsString( - "../../main/src/test/resources/decisions/decision.guard.vfCount.6.input.json"), + "src/test/resources/requests/guard.vfCount.6.json"), DecisionRequest.class); // // Create EntityManager for manipulating DB // + String persistenceUnit = CountRecentOperationsPip.ISSUER_NAME + ".persistenceunit"; em = Persistence.createEntityManagerFactory( - GuardPdpApplicationTest.properties.getProperty("historydb.persistenceunit"), properties) + GuardPdpApplicationTest.properties.getProperty(persistenceUnit), properties) .createEntityManager(); } @@ -156,7 +158,7 @@ public class GuardPdpApplicationTest { @Before public void startClean() throws Exception { em.getTransaction().begin(); - em.createQuery("DELETE FROM OnapOperationsHistoryDbao").executeUpdate(); + em.createQuery("DELETE FROM Dbao").executeUpdate(); em.getTransaction().commit(); } @@ -213,7 +215,7 @@ public class GuardPdpApplicationTest { // can support the correct policy types. // assertThat(service.supportedPolicyTypes()).isNotEmpty(); - assertThat(service.supportedPolicyTypes().size()).isEqualTo(2); + assertThat(service.supportedPolicyTypes().size()).isEqualTo(3); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( "onap.policies.controlloop.guard.FrequencyLimiter", "1.0.0"))).isTrue(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( @@ -222,6 +224,10 @@ public class GuardPdpApplicationTest { "onap.policies.controlloop.guard.MinMax", "1.0.0"))).isTrue(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( "onap.policies.controlloop.guard.MinMax", "1.0.1"))).isFalse(); + assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( + "onap.policies.controlloop.guard.coordination.FirstBlocksSecond", "1.0.0"))).isTrue(); + assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( + "onap.policies.controlloop.guard.coordination.FirstBlocksSecond", "1.0.1"))).isFalse(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier("onap.foo", "1.0.1"))).isFalse(); } @@ -357,10 +363,10 @@ public class GuardPdpApplicationTest { // // Add an entry // - OnapOperationsHistoryDbao newEntry = new OnapOperationsHistoryDbao(); + Dbao newEntry = new Dbao(); newEntry.setActor(properties.get("actor").toString()); newEntry.setOperation(properties.get("recipe").toString()); - newEntry.setClName(properties.get("clname").toString()); + newEntry.setClosedLoopName(properties.get("clname").toString()); newEntry.setOutcome("SUCCESS"); newEntry.setStarttime(Date.from(Instant.now().minusMillis(20000))); newEntry.setEndtime(Date.from(Instant.now())); @@ -372,8 +378,14 @@ public class GuardPdpApplicationTest { em.getTransaction().commit(); } + /** + * Close the entity manager. + */ @AfterClass public static void cleanup() throws Exception { - em.close(); + if (em != null) { + em.close(); + } } + } diff --git a/applications/guard/src/test/resources/META-INF/persistence.xml b/applications/guard/src/test/resources/META-INF/persistence.xml index de399c48..8d1e08ad 100644 --- a/applications/guard/src/test/resources/META-INF/persistence.xml +++ b/applications/guard/src/test/resources/META-INF/persistence.xml @@ -8,9 +8,9 @@ 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. @@ -23,10 +23,11 @@ org.eclipse.persistence.jpa.PersistenceProvider - org.onap.policy.pdp.xacml.application.common.OnapOperationsHistoryDbao + org.onap.policy.pdp.xacml.application.common.operationshistory.Dbao + @@ -38,4 +39,3 @@ - \ No newline at end of file diff --git a/applications/guard/src/test/resources/requests/coordination.cl.1.node.1.json b/applications/guard/src/test/resources/requests/coordination.cl.1.node.1.json new file mode 100644 index 00000000..dd461005 --- /dev/null +++ b/applications/guard/src/test/resources/requests/coordination.cl.1.node.1.json @@ -0,0 +1,15 @@ +{ + "ONAPName": "Policy", + "ONAPComponent": "drools-pdp", + "ONAPInstance": "usecase-template", + "requestId": "unique-request-id-47", + "action": "guard", + "resource": { + "guard": { + "actor": "SDNR", + "recipe": "Tilt", + "clname": "cl1", + "target": "node1" + } + } +} diff --git a/applications/guard/src/test/resources/requests/coordination.cl.1.node.2.json b/applications/guard/src/test/resources/requests/coordination.cl.1.node.2.json new file mode 100644 index 00000000..dbd3a53a --- /dev/null +++ b/applications/guard/src/test/resources/requests/coordination.cl.1.node.2.json @@ -0,0 +1,15 @@ +{ + "ONAPName": "Policy", + "ONAPComponent": "drools-pdp", + "ONAPInstance": "usecase-template", + "requestId": "unique-request-id-4712", + "action": "guard", + "resource": { + "guard": { + "actor": "SDNR", + "recipe": "Tilt", + "clname": "cl1", + "target": "node2" + } + } +} diff --git a/applications/guard/src/test/resources/requests/coordination.cl.2.node.1.json b/applications/guard/src/test/resources/requests/coordination.cl.2.node.1.json new file mode 100644 index 00000000..edccc45b --- /dev/null +++ b/applications/guard/src/test/resources/requests/coordination.cl.2.node.1.json @@ -0,0 +1,15 @@ +{ + "ONAPName": "Policy", + "ONAPComponent": "drools-pdp", + "ONAPInstance": "usecase-template", + "requestId": "unique-request-id-6877", + "action": "guard", + "resource": { + "guard": { + "actor": "SDNR", + "recipe": "Tilt", + "clname": "cl2", + "target": "node1" + } + } +} diff --git a/applications/guard/src/test/resources/requests/coordination.cl.2.node.2.json b/applications/guard/src/test/resources/requests/coordination.cl.2.node.2.json new file mode 100644 index 00000000..c1401f22 --- /dev/null +++ b/applications/guard/src/test/resources/requests/coordination.cl.2.node.2.json @@ -0,0 +1,16 @@ + +{ + "ONAPName": "Policy", + "ONAPComponent": "drools-pdp", + "ONAPInstance": "usecase-template", + "requestId": "unique-request-id-6837", + "action": "guard", + "resource": { + "guard": { + "actor": "SDNR", + "recipe": "Tilt", + "clname": "cl2", + "target": "node2" + } + } +} diff --git a/applications/guard/src/test/resources/requests/guard.vfCount.1.json b/applications/guard/src/test/resources/requests/guard.vfCount.1.json new file mode 100644 index 00000000..ef1b5f65 --- /dev/null +++ b/applications/guard/src/test/resources/requests/guard.vfCount.1.json @@ -0,0 +1,16 @@ +{ + "ONAPName": "Policy", + "ONAPComponent": "drools-pdp", + "ONAPInstance": "usecase-template", + "requestId": "unique-request-id-1", + "action": "guard", + "resource": { + "guard": { + "actor": "SO", + "recipe": "VF Module Create", + "clname": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3", + "target": "vLoadBalancer-00", + "vfCount": "1" + } + } +} diff --git a/applications/guard/src/test/resources/requests/guard.vfCount.3.json b/applications/guard/src/test/resources/requests/guard.vfCount.3.json new file mode 100644 index 00000000..9faa55d6 --- /dev/null +++ b/applications/guard/src/test/resources/requests/guard.vfCount.3.json @@ -0,0 +1,16 @@ +{ + "ONAPName": "Policy", + "ONAPComponent": "drools-pdp", + "ONAPInstance": "usecase-template", + "requestId": "unique-request-id-3", + "action": "guard", + "resource": { + "guard": { + "actor": "SO", + "recipe": "VF Module Create", + "clname": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3", + "target": "vLoadBalancer-00", + "vfCount": "3" + } + } +} diff --git a/applications/guard/src/test/resources/requests/guard.vfCount.6.json b/applications/guard/src/test/resources/requests/guard.vfCount.6.json new file mode 100644 index 00000000..e00d67ae --- /dev/null +++ b/applications/guard/src/test/resources/requests/guard.vfCount.6.json @@ -0,0 +1,16 @@ +{ + "ONAPName": "Policy", + "ONAPComponent": "drools-pdp", + "ONAPInstance": "usecase-template", + "requestId": "unique-request-id-2", + "action": "guard", + "resource": { + "guard": { + "actor": "SO", + "recipe": "VF Module Create", + "clname": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3", + "target": "vLoadBalancer-00", + "vfCount" : "6" + } + } +} diff --git a/applications/guard/src/test/resources/test.policy.guard.coordination.firstBlocksSecond.tosca.yaml b/applications/guard/src/test/resources/test.policy.guard.coordination.firstBlocksSecond.tosca.yaml new file mode 100644 index 00000000..649820b0 --- /dev/null +++ b/applications/guard/src/test/resources/test.policy.guard.coordination.firstBlocksSecond.tosca.yaml @@ -0,0 +1,14 @@ +tosca_definitions_version: tosca_simple_yaml_1_0_0 +topology_template: + policies: + - + guard.coordination.firstBlocksSecond.test: + type: onap.policies.controlloop.guard.coordination.FirstBlocksSecond + version: 1.0.0 + metadata: + policy-id : guard.coordination.firstBlocksSecond.test + policy-version: 1 + properties: + controlLoop: + - cl1 + - cl2 diff --git a/applications/guard/src/test/resources/xacml.properties b/applications/guard/src/test/resources/xacml.properties index 25dee375..534c538c 100644 --- a/applications/guard/src/test/resources/xacml.properties +++ b/applications/guard/src/test/resources/xacml.properties @@ -24,23 +24,22 @@ xacml.att.policyFinderFactory=org.onap.policy.pdp.xacml.application.common.OnapP # xacml.att.policyFinderFactory.combineRootPolicies=urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:deny-overrides -xacml.pip.engines=historydb - # -# PIP Engine Definition +# PIP Engine Definitions # -historydb.classname=org.onap.policy.pdp.xacml.application.common.OnapOperationsHistoryPipEngine -historydb.issuer=urn:org:onap:xacml:guard:historydb -historydb.name=operationHistoryDB -historydb.description=Returns operation counts based on time window +count-recent-operations.classname=org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip +count-recent-operations.issuer=urn:org:onap:xacml:guard:count-recent-operations +count-recent-operations.name=CountRecentOperations +count-recent-operations.description=Returns operation counts based on time window +count-recent-operations.persistenceunit=OperationsHistoryPUTest -# -# Database persistence for PIP -# -historydb.persistenceunit=OperationsHistoryPUTest +get-operation-outcome.classname=org.onap.policy.pdp.xacml.application.common.operationshistory.GetOperationOutcomePip +get-operation-outcome.issuer=urn:org:onap:xacml:guard:get-operation-outcome +get-operation-outcome.name=GetOperationOutcome +get-operation-outcome.description=Returns operation outcome +get-operation-outcome.persistenceunit=OperationsHistoryPUTest -# Policies to load # -#xacml.rootPolicies=guard -#guard.file=src/main/resources/RootGuardPolicy.xml - +# Make pips available to finder +# +xacml.pip.engines=count-recent-operations,get-operation-outcome \ No newline at end of file -- cgit 1.2.3-korg