diff options
Diffstat (limited to 'applications/guard/src/test')
14 files changed, 707 insertions, 280 deletions
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 index c75156df..b5585a7c 100644 --- 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 @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 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. @@ -30,6 +30,7 @@ import java.io.IOException; import java.sql.Date; import java.time.Instant; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Properties; import java.util.ServiceLoader; @@ -51,6 +52,8 @@ 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.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; 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; @@ -160,6 +163,16 @@ public class CoordinationTest { } /** + * Close the entity manager. + */ + @AfterClass + public static void cleanup() throws Exception { + if (em != null) { + em.close(); + } + } + + /** * Clears the database before each test. * */ @@ -170,52 +183,35 @@ public class CoordinationTest { 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 - // - Pair<DecisionResponse, Response> decision = service.makeDecision(request, null); - // - // Check decision - // - checkDecision(expected, decision.getKey()); + @Test + public void test0Basics() throws ToscaPolicyConversionException { + LOGGER.info("**************** Running test0Basics ****************"); + // + // Check the methods in coordination translator that don't get tested by + // the application. + // + CoordinationGuardTranslator translator = new CoordinationGuardTranslator(); + assertThat(translator.convertRequest(null)).isNull(); + assertThat(translator.convertResponse(null)).isNull(); + assertThat(CoordinationGuardTranslator.loadCoordinationDirectiveFromFile( + policyFolder.getRoot().getAbsolutePath() + "/nonexist.yaml")).isNull(); + CoordinationDirective directive = CoordinationGuardTranslator.loadCoordinationDirectiveFromFile( + "src/test/resources/test-directive.yaml"); + assertThat(directive).isNotNull(); } @Test - public void test1() throws CoderException, IOException, XacmlApplicationException { - LOGGER.info("**************** Running test1 ****************"); + public void test1Coordination() throws CoderException, IOException, XacmlApplicationException { + LOGGER.info("**************** Running test1Coordination ****************"); // // 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); + List<ToscaPolicy> loadedPolicies = TestUtils.loadPolicies( + "src/test/resources/test.policy.guard.coordination.firstBlocksSecond.tosca.yaml", service); + assertThat(loadedPolicies).isNotNull(); + assertThat(loadedPolicies.get(0).getName()).isEqualTo("guard.coordination.firstBlocksSecond.test"); // // cl1 doesn't have open action: cl2 should get permit // @@ -266,6 +262,42 @@ public class CoordinationTest { requestAndCheckDecision(requestCl2Node1, DENY); } + /** + * 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 + // + Pair<DecisionResponse, Response> decision = service.makeDecision(request, null); + // + // Check decision + // + checkDecision(expected, decision.getKey()); + } + @SuppressWarnings("unchecked") private void insertOperationEvent(DecisionRequest request, String outcome) { // @@ -288,14 +320,4 @@ public class CoordinationTest { 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 9c3ae5b2..c62575c0 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 @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 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. @@ -23,6 +23,7 @@ package org.onap.policy.xacml.pdp.application.guard; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import com.att.research.xacml.api.Response; import java.io.File; @@ -30,8 +31,8 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.sql.Date; import java.time.Instant; -import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Properties; import java.util.ServiceLoader; @@ -53,6 +54,7 @@ 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.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier; import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException; import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider; @@ -71,9 +73,7 @@ public class GuardPdpApplicationTest { private static File propertiesFile; private static RestServerParameters clientParams = new RestServerParameters(); private static XacmlApplicationServiceProvider service; - private static DecisionRequest requestVfCount1; - private static DecisionRequest requestVfCount3; - private static DecisionRequest requestVfCount6; + private static DecisionRequest requestVfCount; private static StandardCoder gson = new StandardCoder(); private static EntityManager em; private static final String DENY = "Deny"; @@ -132,17 +132,9 @@ public class GuardPdpApplicationTest { // // Load Decision Requests // - requestVfCount1 = gson.decode( + requestVfCount = gson.decode( TextFileUtils.getTextFileAsString( - "src/test/resources/requests/guard.vfCount.1.json"), - DecisionRequest.class); - requestVfCount3 = gson.decode( - TextFileUtils.getTextFileAsString( - "src/test/resources/requests/guard.vfCount.3.json"), - DecisionRequest.class); - requestVfCount6 = gson.decode( - TextFileUtils.getTextFileAsString( - "src/test/resources/requests/guard.vfCount.6.json"), + "src/test/resources/requests/guard.vfCount.json"), DecisionRequest.class); // // Create EntityManager for manipulating DB @@ -154,7 +146,17 @@ public class GuardPdpApplicationTest { } /** - * Clears the database before each test. + * Close the entity manager. + */ + @AfterClass + public static void cleanup() throws Exception { + if (em != null) { + em.close(); + } + } + + /** + * Clears the database before each test so there are no operations in it. * */ @Before @@ -202,7 +204,7 @@ public class GuardPdpApplicationTest { @Test public void test1Basics() throws CoderException, IOException { - LOGGER.info("**************** Running test1 ****************"); + LOGGER.info("**************** Running test1Basics ****************"); // // Make sure there's an application name // @@ -219,17 +221,17 @@ public class GuardPdpApplicationTest { assertThat(service.supportedPolicyTypes()).isNotEmpty(); assertThat(service.supportedPolicyTypes().size()).isEqualTo(4); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.FrequencyLimiter", "1.0.0"))).isTrue(); + "onap.policies.controlloop.guard.common.FrequencyLimiter", "1.0.0"))).isTrue(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.FrequencyLimiter", "1.0.1"))).isFalse(); + "onap.policies.controlloop.guard.common.FrequencyLimiter", "1.0.1"))).isFalse(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.MinMax", "1.0.0"))).isTrue(); + "onap.policies.controlloop.guard.common.MinMax", "1.0.0"))).isTrue(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.MinMax", "1.0.1"))).isFalse(); + "onap.policies.controlloop.guard.common.MinMax", "1.0.1"))).isFalse(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.Blacklist", "1.0.0"))).isTrue(); + "onap.policies.controlloop.guard.common.Blacklist", "1.0.0"))).isTrue(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( - "onap.policies.controlloop.guard.Blacklist", "1.0.1"))).isFalse(); + "onap.policies.controlloop.guard.common.Blacklist", "1.0.1"))).isFalse(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( "onap.policies.controlloop.guard.coordination.FirstBlocksSecond", "1.0.0"))).isTrue(); assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier( @@ -239,146 +241,106 @@ public class GuardPdpApplicationTest { @Test public void test2NoPolicies() throws CoderException { - LOGGER.info("**************** Running test2 ****************"); - requestAndCheckDecision(requestVfCount1,PERMIT); + LOGGER.info("**************** Running test2NoPolicies ****************"); + assertThatCode(() -> requestAndCheckDecision(requestVfCount, PERMIT)).doesNotThrowAnyException(); } @Test public void test3FrequencyLimiter() throws CoderException, FileNotFoundException, IOException, XacmlApplicationException { - LOGGER.info("**************** Running test3 ****************"); + LOGGER.info("**************** Running test3FrequencyLimiter ****************"); // // Now load the vDNS frequency limiter Policy - make sure // the pdp can support it and have it load // into the PDP. // - TestUtils.loadPolicies("src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml", service); + List<ToscaPolicy> loadedPolicies = TestUtils.loadPolicies( + "policies/vDNS.policy.guard.frequencylimiter.input.tosca.yaml", service); + assertThat(loadedPolicies).hasSize(1); + assertThat(loadedPolicies.get(0).getName()).isEqualTo("guard.frequency.scaleout"); // // Zero recent actions: should get permit // - requestAndCheckDecision(requestVfCount1,PERMIT); + requestAndCheckDecision(requestVfCount, PERMIT); // // Add entry into operations history DB // - insertOperationEvent(requestVfCount1); - // - // Only one recent actions: should get permit - // - requestAndCheckDecision(requestVfCount1,PERMIT); - // - // Add entry into operations history DB - // - insertOperationEvent(requestVfCount1); + insertOperationEvent(requestVfCount); // // Two recent actions, more than specified limit of 2: should get deny // - requestAndCheckDecision(requestVfCount1,DENY); + requestAndCheckDecision(requestVfCount, DENY); } + @SuppressWarnings("unchecked") @Test public void test4MinMax() throws CoderException, FileNotFoundException, IOException, XacmlApplicationException { - LOGGER.info("**************** Running test4 ****************"); + LOGGER.info("**************** Running test4MinMax ****************"); // // Now load the vDNS min max Policy - make sure // the pdp can support it and have it load // into the PDP. // - TestUtils.loadPolicies("src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml", service); + List<ToscaPolicy> loadedPolicies = TestUtils.loadPolicies( + "policies/vDNS.policy.guard.minmaxvnfs.input.tosca.yaml", service); + assertThat(loadedPolicies).hasSize(1); + assertThat(loadedPolicies.get(0).getName()).isEqualTo("guard.minmax.scaleout"); // - // vfcount=1 below min of 2: should get a Deny + // vfcount=0 below min of 1: should get a Permit // - requestAndCheckDecision(requestVfCount1, DENY); + requestAndCheckDecision(requestVfCount, PERMIT); // - // vfcount=3 between min of 2 and max of 5: should get a Permit + // vfcount=1 between min of 1 and max of 2: should get a Permit // - requestAndCheckDecision(requestVfCount3, PERMIT); + ((Map<String, Object>) requestVfCount.getResource().get("guard")).put("vfCount", 1); + requestAndCheckDecision(requestVfCount, PERMIT); // - // vfcount=6 above max of 5: should get a Deny + // vfcount=2 hits the max of 2: should get a Deny // - requestAndCheckDecision(requestVfCount6,DENY); + ((Map<String, Object>) requestVfCount.getResource().get("guard")).put("vfCount", 2); + requestAndCheckDecision(requestVfCount, DENY); // - // Add two entry into operations history DB + // vfcount=3 above max of 2: should get a Deny // - insertOperationEvent(requestVfCount1); - insertOperationEvent(requestVfCount1); + ((Map<String, Object>) requestVfCount.getResource().get("guard")).put("vfCount", 3); + requestAndCheckDecision(requestVfCount,DENY); // - // vfcount=3 between min of 2 and max of 5, but 2 recent actions is above frequency limit: should get a Deny + // Insert entry into operations history DB - to indicate a successful + // VF Module Create. // - requestAndCheckDecision(requestVfCount3, DENY); + insertOperationEvent(requestVfCount); // - // vfcount=6 above max of 5: should get a Deny + // vfcount=1 between min of 1 and max of 2; MinMax should succeed, + // BUT the frequency limiter should fail // - requestAndCheckDecision(requestVfCount6, DENY); - } - - @Test - public void test5MissingFields() throws FileNotFoundException, IOException, XacmlApplicationException, - CoderException { - LOGGER.info("**************** Running test5 ****************"); - // - // Most likely we would not get a policy with missing fields passed to - // us from the API. But in case that happens, or we decide that some fields - // will be optional due to re-working of how the XACML policies are built, - // let's add support in for that. - // - TestUtils.loadPolicies("src/test/resources/guard.policy-minmax-missing-fields1.yaml", service); - // - // We can create a DecisionRequest on the fly - no need - // to have it in the .json files - // - DecisionRequest request = new DecisionRequest(); - request.setOnapName("JUnit"); - request.setOnapComponent("test5MissingFields"); - request.setRequestId(UUID.randomUUID().toString()); - request.setAction("guard"); - Map<String, Object> guard = new HashMap<>(); - guard.put("actor", "FOO"); - guard.put("recipe", "bar"); - guard.put("vfCount", "4"); - Map<String, Object> resource = new HashMap<>(); - resource.put("guard", guard); - request.setResource(resource); - // - // Ask for a decision - should get permit - // - Pair<DecisionResponse, Response> decision = service.makeDecision(request, null); - LOGGER.info("Looking for Permit Decision {}", decision.getKey()); - assertThat(decision.getKey()).isNotNull(); - assertThat(decision.getKey().getStatus()).isNotNull(); - assertThat(decision.getKey().getStatus()).isEqualTo("Permit"); - // - // Try a deny - // - guard.put("vfCount", "10"); - resource.put("guard", guard); - request.setResource(resource); - decision = service.makeDecision(request, null); - LOGGER.info("Looking for Deny Decision {}", decision.getKey()); - assertThat(decision.getKey()).isNotNull(); - assertThat(decision.getKey().getStatus()).isNotNull(); - assertThat(decision.getKey().getStatus()).isEqualTo("Deny"); + ((Map<String, Object>) requestVfCount.getResource().get("guard")).put("vfCount", 1); + requestAndCheckDecision(requestVfCount, DENY); } @SuppressWarnings("unchecked") @Test - public void test6Blacklist() throws CoderException, XacmlApplicationException { - LOGGER.info("**************** Running test4 ****************"); + public void test5Blacklist() throws CoderException, XacmlApplicationException { + LOGGER.info("**************** Running test5Blacklist ****************"); // - // Setup requestVfCount1 to point to another target for this test + // Load the blacklist policy in with the others. // - ((Map<String, Object>)requestVfCount3.getResource().get("guard")).put("targets", "vLoadBalancer-01"); + List<ToscaPolicy> loadedPolicies = TestUtils.loadPolicies( + "policies/vDNS.policy.guard.blacklist.input.tosca.yaml", service); + assertThat(loadedPolicies).hasSize(1); + assertThat(loadedPolicies.get(0).getName()).isEqualTo("guard.blacklist.scaleout"); // - // vfcount=1 above min of 2: should get a permit + // vfcount=0 below min of 1: should get a Permit because target is NOT blacklisted // - requestAndCheckDecision(requestVfCount3, PERMIT); + requestAndCheckDecision(requestVfCount, PERMIT); // - // Now load the vDNS blacklist policy + // vfcount=1 between min of 1 and max of 2: change the // - TestUtils.loadPolicies("src/test/resources/vDNS.policy.guard.blacklist.output.tosca.yaml", service); + ((Map<String, Object>) requestVfCount.getResource().get("guard")) + .put("target", "the-vfmodule-where-root-is-true"); // - // vfcount=1 above min of 2: should get a permit + // vfcount=0 below min of 1: should get a Deny because target IS blacklisted // - requestAndCheckDecision(requestVfCount3, DENY); + requestAndCheckDecision(requestVfCount, DENY); } @SuppressWarnings("unchecked") @@ -406,14 +368,4 @@ public class GuardPdpApplicationTest { 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/GuardPolicyRequestTest.java b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequestTest.java new file mode 100644 index 00000000..b3ef3bdd --- /dev/null +++ b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPolicyRequestTest.java @@ -0,0 +1,87 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 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.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.onap.policy.models.decisions.concepts.DecisionRequest; + +public class GuardPolicyRequestTest { + + @Test + public void testAnomalies() { + DecisionRequest decisionRequest = new DecisionRequest(); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + Map<String, Object> resources = new HashMap<>(); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + resources.put("notguard", "foo"); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + resources.put("guard", null); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + Map<String, Object> guard = new HashMap<>(); + resources.put("guard", guard); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + guard.put("crap", "notused"); + resources.put("guard", guard); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + guard.put("actor", "notused"); + resources.put("guard", guard); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + guard.put("recipe", "notused"); + resources.put("guard", guard); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + guard.put("clname", "notused"); + resources.put("guard", guard); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + guard.put("target", "notused"); + resources.put("guard", guard); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + + guard.put("vfCount", 1); + resources.put("guard", guard); + decisionRequest.setResource(resources); + assertThat(GuardPolicyRequest.createInstance(decisionRequest)).isNotNull(); + } + +} diff --git a/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslatorTest.java b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslatorTest.java new file mode 100644 index 00000000..36b43aee --- /dev/null +++ b/applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardTranslatorTest.java @@ -0,0 +1,319 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 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 static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.StdMutableResponse; +import com.att.research.xacml.std.StdMutableResult; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.util.XACMLPolicyWriter; +import java.io.ByteArrayOutputStream; +import java.util.Map; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType; +import org.junit.Test; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.common.utils.coder.StandardYamlCoder; +import org.onap.policy.common.utils.resources.ResourceUtils; +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.ToscaPolicy; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; +import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate; +import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; +import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GuardTranslatorTest { + private static final Logger LOGGER = LoggerFactory.getLogger(GuardTranslatorTest.class); + private static final StandardYamlCoder yamlCoder = new StandardYamlCoder(); + private static StandardCoder gson = new StandardCoder(); + + private GuardTranslator translator = new GuardTranslator(); + + @Test + public void testRequest() throws Exception { + DecisionRequest decisionRequest = gson.decode( + TextFileUtils.getTextFileAsString( + "src/test/resources/requests/guard.vfCount.json"), + DecisionRequest.class); + Request xacmlRequest = translator.convertRequest(decisionRequest); + + assertThat(xacmlRequest).isNotNull(); + } + + @Test + public void testResponse() { + StdStatus status = new StdStatus(StdStatusCode.STATUS_CODE_OK); + StdMutableResult result = new StdMutableResult(Decision.PERMIT, status); + StdMutableResponse response = new StdMutableResponse(result); + + DecisionResponse decisionResponse = translator.convertResponse(response); + assertThat(decisionResponse).isNotNull(); + assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString()); + + result = new StdMutableResult(Decision.DENY, status); + response = new StdMutableResponse(result); + decisionResponse = translator.convertResponse(response); + assertThat(decisionResponse).isNotNull(); + assertThat(decisionResponse.getStatus()).isEqualTo(Decision.DENY.toString()); + + result = new StdMutableResult(Decision.INDETERMINATE, status); + response = new StdMutableResponse(result); + decisionResponse = translator.convertResponse(response); + assertThat(decisionResponse).isNotNull(); + assertThat(decisionResponse.getStatus()).isEqualTo(Decision.PERMIT.toString()); + } + + + @Test + public void testBadPolicies() throws Exception { + String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-bad-policies.yaml"); + // + // Serialize it into a class + // + ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class); + // + // Make sure all the fields are setup properly + // + JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate(); + jtst.fromAuthorative(serviceTemplate); + ToscaServiceTemplate completedJtst = jtst.toAuthorative(); + // + // Get the policies + // + for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) { + for (ToscaPolicy policy : policies.values()) { + if ("frequency-missing-properties".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Missing property limit"); + } else if ("frequency-timewindow".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("timeWindow is not an integer"); + } else if ("minmax-notarget".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Missing target field in minmax policy"); + } else if ("minmax-nominmax".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Missing min or max field in minmax policy"); + } else if ("blacklist-noblacklist".equals(policy.getName())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy) + ).withMessageContaining("Missing blacklist"); + } + } + } + } + + @Test + public void testPolicyConversion() throws Exception { + String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/test-policies.yaml"); + // + // Serialize it into a class + // + ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class); + // + // Make sure all the fields are setup properly + // + JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate(); + jtst.fromAuthorative(serviceTemplate); + ToscaServiceTemplate completedJtst = jtst.toAuthorative(); + // + // Get the policies + // + for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) { + for (ToscaPolicy policy : policies.values()) { + // + // Convert the policy + // + if ("onap.policies.controlloop.guard.common.Unknown".equals(policy.getType())) { + assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> + translator.convertPolicy(policy)); + continue; + } + PolicyType xacmlPolicy = translator.convertPolicy(policy); + assertThat(xacmlPolicy).isNotNull(); + // + // Let's dump it out + // + ByteArrayOutputStream os = new ByteArrayOutputStream(); + XACMLPolicyWriter.writePolicyFile(os, xacmlPolicy); + LOGGER.info(os.toString()); + // + // Validate the policy + // + assertThat(xacmlPolicy.getPolicyId()).isEqualTo(policy.getName()); + assertThat(xacmlPolicy.getVersion()).isEqualTo(policy.getVersion()); + assertThat(xacmlPolicy.getRuleCombiningAlgId()).isNotNull(); + validateCommon(policy, xacmlPolicy); + // + // Validate each policy type + // + if (GuardTranslator.POLICYTYPE_FREQUENCY.equals(policy.getType())) { + validateFrequency(policy, xacmlPolicy); + } else if (GuardTranslator.POLICYTYPE_MINMAX.equals(policy.getType())) { + validateMinMax(policy, xacmlPolicy); + } else if (GuardTranslator.POLICYTYPE_BLACKLIST.equals(policy.getType())) { + validateBlacklist(policy, xacmlPolicy); + } + } + } + } + + private void validateCommon(ToscaPolicy policy, PolicyType xacmlPolicy) { + boolean foundActor = false; + boolean foundOperation = false; + boolean foundTarget = false; + boolean foundControlLoop = false; + boolean foundTimeRange = false; + + assertThat(xacmlPolicy.getTarget()).isNotNull(); + assertThat(xacmlPolicy.getTarget().getAnyOf()).isNotEmpty(); + for (AnyOfType anyOf : xacmlPolicy.getTarget().getAnyOf()) { + assertThat(anyOf.getAllOf()).isNotEmpty(); + for (AllOfType allOf : anyOf.getAllOf()) { + assertThat(allOf.getMatch()).isNotEmpty(); + for (MatchType match : allOf.getMatch()) { + // + // These fields are required + // + if (ToscaDictionary.ID_RESOURCE_GUARD_ACTOR.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(match.getAttributeValue().getContent()).isNotNull(); + foundActor = true; + } else if (ToscaDictionary.ID_RESOURCE_GUARD_RECIPE.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(match.getAttributeValue().getContent()).isNotNull(); + foundOperation = true; + } else { + // + // These fields are optional + // + if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(policy.getProperties()).containsKey("target"); + foundTarget = true; + } + if (ToscaDictionary.ID_RESOURCE_GUARD_CLNAME.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_CONTROLLOOP); + foundControlLoop = true; + } + if (XACML3.ID_ENVIRONMENT_CURRENT_TIME.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TIMERANGE); + foundTimeRange = true; + } + } + } + } + } + assertThat(foundActor && foundOperation).isTrue(); + if (policy.getProperties().containsKey("target")) { + assertThat(foundTarget).isTrue(); + } + if (policy.getProperties().containsKey(GuardTranslator.FIELD_CONTROLLOOP)) { + assertThat(foundControlLoop).isTrue(); + } + if (policy.getProperties().containsKey(GuardTranslator.FIELD_TIMERANGE)) { + assertThat(foundTimeRange).isTrue(); + } + } + + private void validateFrequency(ToscaPolicy policy, PolicyType xacmlPolicy) { + for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) { + if (! (rule instanceof RuleType)) { + continue; + } + assertThat(((RuleType)rule).getCondition()).isNotNull(); + assertThat(((RuleType)rule).getCondition().getExpression()).isNotNull(); + } + } + + private void validateMinMax(ToscaPolicy policy, PolicyType xacmlPolicy) { + boolean foundTarget = false; + boolean foundMinOrMax = false; + for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) { + if (! (rule instanceof RuleType)) { + continue; + } + for (AnyOfType anyOf : ((RuleType)rule).getTarget().getAnyOf()) { + assertThat(anyOf.getAllOf()).isNotEmpty(); + for (AllOfType allOf : anyOf.getAllOf()) { + assertThat(allOf.getMatch()).isNotEmpty(); + for (MatchType match : allOf.getMatch()) { + if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_TARGET); + foundTarget = true; + } else if (ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(policy.getProperties().keySet()).containsAnyOf(GuardTranslator.FIELD_MIN, + GuardTranslator.FIELD_MAX); + foundMinOrMax = true; + } + } + } + } + } + assertThat(foundTarget && foundMinOrMax).isTrue(); + } + + private void validateBlacklist(ToscaPolicy policy, PolicyType xacmlPolicy) { + boolean foundBlacklist = false; + for (Object rule : xacmlPolicy.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition()) { + if (! (rule instanceof RuleType)) { + continue; + } + for (AnyOfType anyOf : ((RuleType)rule).getTarget().getAnyOf()) { + assertThat(anyOf.getAllOf()).isNotEmpty(); + for (AllOfType allOf : anyOf.getAllOf()) { + assertThat(allOf.getMatch()).isNotEmpty(); + for (MatchType match : allOf.getMatch()) { + if (ToscaDictionary.ID_RESOURCE_GUARD_TARGETID.toString().equals( + match.getAttributeDesignator().getAttributeId())) { + assertThat(policy.getProperties()).containsKey(GuardTranslator.FIELD_BLACKLIST); + foundBlacklist = true; + } + } + } + } + } + assertThat(foundBlacklist).isTrue(); + } +} diff --git a/applications/guard/src/test/resources/guard.policy-minmax-missing-fields1.yaml b/applications/guard/src/test/resources/guard.policy-minmax-missing-fields1.yaml deleted file mode 100644 index 6a441182..00000000 --- a/applications/guard/src/test/resources/guard.policy-minmax-missing-fields1.yaml +++ /dev/null @@ -1,19 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_0_0 -topology_template: - policies: - - - guard.minmax.missing1: - type: onap.policies.controlloop.guard.MinMax - version: 1.0.0 - metadata: - policy-id : guard.minmax.scaleout - policy-version: 1 - properties: - actor: FOO - recipe: bar -# targets: *. -# clname: ControlLoop-Foo-Bar - min: 1 - max: 5 -# guardActiveStart: 00:00:01-05:00 -# guardActiveEnd: 23:59:59-05:00 diff --git a/applications/guard/src/test/resources/requests/guard.vfCount.3.json b/applications/guard/src/test/resources/requests/guard.vfCount.3.json deleted file mode 100644 index 9faa55d6..00000000 --- a/applications/guard/src/test/resources/requests/guard.vfCount.3.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "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 deleted file mode 100644 index e00d67ae..00000000 --- a/applications/guard/src/test/resources/requests/guard.vfCount.6.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "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/requests/guard.vfCount.1.json b/applications/guard/src/test/resources/requests/guard.vfCount.json index ef1b5f65..7fc7d230 100644 --- a/applications/guard/src/test/resources/requests/guard.vfCount.1.json +++ b/applications/guard/src/test/resources/requests/guard.vfCount.json @@ -9,8 +9,8 @@ "actor": "SO", "recipe": "VF Module Create", "clname": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3", - "target": "vLoadBalancer-00", - "vfCount": "1" + "target": "e6130d03-56f1-4b0a-9a1d-e1b2ebc30e0e", + "vfCount": "0" } } } diff --git a/applications/guard/src/test/resources/test-bad-policies.yaml b/applications/guard/src/test/resources/test-bad-policies.yaml new file mode 100644 index 00000000..df2431d4 --- /dev/null +++ b/applications/guard/src/test/resources/test-bad-policies.yaml @@ -0,0 +1,35 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +topology_template: + policies: + - + frequency-missing-properties: + type: onap.policies.controlloop.guard.common.FrequencyLimiter + type_version: 1.0.0 + version: 1.0.0 + - + frequency-timewindow: + type: onap.policies.controlloop.guard.common.FrequencyLimiter + type_version: 1.0.0 + version: 1.0.0 + properties: + limit: 5 + timeWindow: i am a bad value + - + minmax-notarget: + type: onap.policies.controlloop.guard.common.MinMax + type_version: 1.0.0 + version: 1.0.0 + properties: + - + minmax-nominmax: + type: onap.policies.controlloop.guard.common.MinMax + type_version: 1.0.0 + version: 1.0.0 + properties: + target: foo + - + blacklist-noblacklist: + type: onap.policies.controlloop.guard.common.Blacklist + type_version: 1.0.0 + version: 1.0.0 + properties: diff --git a/applications/guard/src/test/resources/test-directive.yaml b/applications/guard/src/test/resources/test-directive.yaml new file mode 100644 index 00000000..44dfa74b --- /dev/null +++ b/applications/guard/src/test/resources/test-directive.yaml @@ -0,0 +1,4 @@ +controlLoop: + - cl1 + - cl2 +directive: whatisthisvaluesupposedtobe diff --git a/applications/guard/src/test/resources/test-policies.yaml b/applications/guard/src/test/resources/test-policies.yaml new file mode 100644 index 00000000..1ac7271c --- /dev/null +++ b/applications/guard/src/test/resources/test-policies.yaml @@ -0,0 +1,116 @@ +tosca_definitions_version: tosca_simple_yaml_1_1_0 +topology_template: + policies: + - + frequency-default: + type: onap.policies.controlloop.guard.common.FrequencyLimiter + type_version: 1.0.0 + version: 1.0.0 + description: | + This is the default APPC Restart frequency limiter policy for all control loops. + metadata: + policy-id: frequency-default + policy-version: 1.0.0 + properties: + actor: APPC + operation: Restart + timeWindow: 10 + timeUnits: minute + limit: 1 + - + frequency-loop-1: + type: onap.policies.controlloop.guard.common.FrequencyLimiter + type_version: 1.0.0 + version: 1.0.0 + description: | + This frequency limiter is for APPC Restart on a specific control loop. It allows more restarts. + metadata: + policy-id: frequency-loop-1 + policy-version: 1.0.0 + properties: + actor: APPC + operation: Restart + id: loop-1 + timeWindow: 10 + timeUnits: minute + limit: 3 + - + frequency-loop-3: + type: onap.policies.controlloop.guard.common.FrequencyLimiter + type_version: 1.0.0 + version: 1.0.0 + description: | + This frequency limiter is for APPC Restart on a specific control loop. It allows + NO restarts in a time frame. + metadata: + policy-id: frequency-loop-3 + policy-version: 1.0.0 + properties: + actor: APPC + operation: Restart + timeRange: + start_time: T00:00:00Z + end_time: T08:00:00Z + id: loop-3 + timeWindow: 8 + timeUnits: hour + limit: 0 + - + minmax-default: + type: onap.policies.controlloop.guard.common.MinMax + type_version: 1.0.0 + version: 1.0.0 + metadata: + policy-id : minmax-default + policy-version: 1.0.0 + properties: + actor: SO + operation: VF Module Create + target: vf-module-id-1 + min: 1 + max: 5 + - + minmax-vfmodule-loop2: + type: onap.policies.controlloop.guard.common.MinMax + type_version: 1.0.0 + version: 1.0.0 + metadata: + policy-id : minmax-vfmodule-loop2 + policy-version: 1.0.0 + properties: + actor: SO + operation: VF Module Create + id: loop-2 + target: vf-module-id-2 + min: 3 + max: 6 + - + blacklist-1: + type: onap.policies.controlloop.guard.common.Blacklist + type_version: 1.0.0 + version: 1.0.0 + metadata: + policy-id : blacklist-1 + policy-version: 1.0.0 + properties: + actor: APPC + operation: Migrate + id: loop-5 + blacklist: + - vnf1 + - vnf2 + - + unknown-1: + type: onap.policies.controlloop.guard.common.Unknown + type_version: 1.0.0 + version: 1.0.0 + metadata: + policy-id : unknown-1 + policy-version: 1.0.0 + properties: + actor: APPC + operation: Migrate + id: loop-5 + blacklist: + - vnf1 + - vnf2
\ No newline at end of file diff --git a/applications/guard/src/test/resources/vDNS.policy.guard.blacklist.output.tosca.yaml b/applications/guard/src/test/resources/vDNS.policy.guard.blacklist.output.tosca.yaml deleted file mode 100644 index 7d3a54ec..00000000 --- a/applications/guard/src/test/resources/vDNS.policy.guard.blacklist.output.tosca.yaml +++ /dev/null @@ -1,18 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_0_0 -topology_template: - policies: - - - guard.frequency.scaleout: - type: onap.policies.controlloop.guard.Blacklist - version: 1.0.0 - metadata: - policy-id: guard.frequency.scaleout - policy-version: 1 - properties: - actor: SO - recipe: VF Module Create - targets: vLoadBalancer-01 - clname: ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3 - limit: 2 - guardActiveStart: 00:00:00Z - guardActiveEnd: 23:59:59Z diff --git a/applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml b/applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml deleted file mode 100644 index 506a44ed..00000000 --- a/applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml +++ /dev/null @@ -1,20 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_0_0 -topology_template: - policies: - - - guard.frequency.scaleout: - type: onap.policies.controlloop.guard.FrequencyLimiter - version: 1.0.0 - metadata: - policy-id: guard.frequency.scaleout - policy-version: 1 - properties: - actor: SO - recipe: VF Module Create - targets: .* - clname: ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3 - limit: 2 - timeWindow: 10 - timeUnits: minute - guardActiveStart: 00:00:00Z - guardActiveEnd: 23:59:59Z diff --git a/applications/guard/src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml b/applications/guard/src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml deleted file mode 100644 index ff2a423d..00000000 --- a/applications/guard/src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml +++ /dev/null @@ -1,19 +0,0 @@ -tosca_definitions_version: tosca_simple_yaml_1_0_0 -topology_template: - policies: - - - guard.minmax.scaleout: - type: onap.policies.controlloop.guard.MinMax - version: 1.0.0 - metadata: - policy-id : guard.minmax.scaleout - policy-version: 1 - properties: - actor: SO - recipe: VF Module Create - targets: .* - clname: ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3 - min: 2 - max: 5 - guardActiveStart: 00:00:00Z - guardActiveEnd: 23:59:59Z |