diff options
10 files changed, 290 insertions, 21 deletions
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/TestUtils.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/TestUtils.java index fa32516d..50eb50bf 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/TestUtils.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/TestUtils.java @@ -22,6 +22,8 @@ package org.onap.policy.pdp.xacml.application.common; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -30,9 +32,12 @@ import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.resources.ResourceUtils; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.Yaml; public class TestUtils { + private static final Logger LOGGER = LoggerFactory.getLogger(TestUtils.class); private static final StandardCoder standardCoder = new StandardCoder(); private TestUtils() { @@ -47,8 +52,15 @@ public class TestUtils { * @throws CoderException exception if it cannot be decoded * @throws XacmlApplicationException If the application cannot load the policy */ - public static void loadPolicies(String resourceFile, XacmlApplicationServiceProvider service) + public static List<ToscaPolicy> loadPolicies(String resourceFile, XacmlApplicationServiceProvider service) throws CoderException, XacmlApplicationException { + // + // Our return object + // + List<ToscaPolicy> loadedPolicies = new ArrayList<>(); + // + // Decode it + // String policyYaml = ResourceUtils.getResourceAsString(resourceFile); Yaml yaml = new Yaml(); Object yamlObject = yaml.load(policyYaml); @@ -58,11 +70,15 @@ public class TestUtils { // Get the policies // for (Map<String, ToscaPolicy> policies : serviceTemplate.getToscaTopologyTemplate().getPolicies()) { - for (Entry<String, ToscaPolicy> entrySet : policies.entrySet()) { - service.loadPolicy(entrySet.getValue()); + for (ToscaPolicy policy : policies.values()) { + if (service.loadPolicy(policy)) { + loadedPolicies.add(policy); + } else { + LOGGER.error("Application failed to load policy"); + } } } - + return loadedPolicies; } } diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/XacmlApplicationServiceProvider.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/XacmlApplicationServiceProvider.java index c1682fb7..d4cce5c1 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/XacmlApplicationServiceProvider.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/XacmlApplicationServiceProvider.java @@ -83,7 +83,14 @@ public interface XacmlApplicationServiceProvider { * * @param toscaPolicy object */ - void loadPolicy(ToscaPolicy toscaPolicy) throws XacmlApplicationException; + boolean loadPolicy(ToscaPolicy toscaPolicy) throws XacmlApplicationException; + + /** + * unloadPolicy a Tosca Policy. + * + * @param toscaPolicy object + */ + boolean unloadPolicy(ToscaPolicy toscaPolicy) throws XacmlApplicationException; /** * Makes a decision given the incoming request and returns a response. diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/XacmlPolicyUtils.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/XacmlPolicyUtils.java index 364b6519..2a5f21f0 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/XacmlPolicyUtils.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/XacmlPolicyUtils.java @@ -215,6 +215,50 @@ public class XacmlPolicyUtils { } /** + * Removes a root policy from the Properties object. Both in the line + * that identifies the policy and the .file property that points to the path. + * + * @param properties Input Properties object to remove + * @param rootPolicyPath The policy file path + * @return Properties object + */ + public static Properties removeRootPolicy(Properties properties, Path rootPolicyPath) { + // + // Get the current set of referenced policy ids + // + StringJoiner join = new StringJoiner(","); + boolean found = false; + Set<String> rootPolicies = XACMLProperties.getRootPolicyIDs(properties); + for (String refPolicy : rootPolicies) { + String refPolicyFile = refPolicy + DOT_FILE_SUFFIX; + // + // If the key and value match, then it will return true + // + if (properties.remove(refPolicyFile, rootPolicyPath.toString())) { + // + // Record that we actually removed it + // + found = true; + } else { + // + // Retain it + // + join.add(refPolicy); + } + } + // + // Did we remove it? + // + if (found) { + // + // Now update the list of referenced properties + // + properties.setProperty(XACMLProperties.PROP_ROOTPOLICIES, join.toString()); + } + return properties; + } + + /** * Removes a referenced policy from the Properties object. Both in the line * that identifies the policy and the .file property that points to the path. * diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdXacmlApplicationServiceProvider.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdXacmlApplicationServiceProvider.java index 5f84154f..95a642e9 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdXacmlApplicationServiceProvider.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdXacmlApplicationServiceProvider.java @@ -37,7 +37,9 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Properties; import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType; @@ -60,6 +62,7 @@ public abstract class StdXacmlApplicationServiceProvider implements XacmlApplica private Path pathForData = null; private Properties pdpProperties = null; private PDPEngine pdpEngine = null; + private Map<ToscaPolicy, Path> mapLoadedPolicies = new HashMap<>(); public StdXacmlApplicationServiceProvider() { super(); @@ -115,7 +118,7 @@ public abstract class StdXacmlApplicationServiceProvider implements XacmlApplica @Override public List<ToscaPolicyTypeIdentifier> supportedPolicyTypes() { - return Collections.emptyList(); + throw new UnsupportedOperationException("Please override and implement supportedPolicyTypes"); } @Override @@ -124,7 +127,7 @@ public abstract class StdXacmlApplicationServiceProvider implements XacmlApplica } @Override - public synchronized void loadPolicy(ToscaPolicy toscaPolicy) { + public synchronized boolean loadPolicy(ToscaPolicy toscaPolicy) { try { // // Convert the policies first @@ -167,13 +170,77 @@ public abstract class StdXacmlApplicationServiceProvider implements XacmlApplica // Save the properties // this.pdpProperties = newProperties; + // + // Save in our map + // + this.mapLoadedPolicies.put(toscaPolicy, refPath); } catch (IOException | ToscaPolicyConversionException e) { LOGGER.error("Failed to loadPolicies {}", e); + return false; + } + return true; + } + + @Override + public synchronized boolean unloadPolicy(ToscaPolicy toscaPolicy) throws XacmlApplicationException { + // + // Find it in our map + // + Path refPolicy = this.mapLoadedPolicies.get(toscaPolicy); + if (refPolicy == null) { + LOGGER.error("Failed to find ToscaPolicy {} in our map size {}", toscaPolicy.getMetadata(), + this.mapLoadedPolicies.size()); + return false; + } + // + // Create a copy of the properties object + // + Properties newProperties = this.getProperties(); + // + // Remove it from the properties + // + XacmlPolicyUtils.removeRootPolicy(newProperties, refPolicy); + // + // We can delete the file + // + try { + Files.delete(refPolicy); + } catch (IOException e) { + LOGGER.error("Failed to delete policy {} from disk {}", toscaPolicy.getMetadata(), + refPolicy.toAbsolutePath().toString(), e); } + // + // Write the properties to disk + // + try { + XacmlPolicyUtils.storeXacmlProperties(newProperties, + XacmlPolicyUtils.getPropertiesPath(this.getDataPath())); + } catch (IOException e) { + LOGGER.error("Failed to save the properties to disk {}", newProperties); + } + // + // Reload the engine + // + this.createEngine(newProperties); + // + // Save the properties + // + this.pdpProperties = newProperties; + // + // Save in our map + // + if (this.mapLoadedPolicies.remove(toscaPolicy) == null) { + LOGGER.error("Failed to remove toscaPolicy {} from internal map size {}", toscaPolicy.getMetadata(), + this.mapLoadedPolicies.size()); + } + // + // Not sure if any of the errors above warrant returning false + // + return true; } @Override - public synchronized DecisionResponse makeDecision(DecisionRequest request) { + public DecisionResponse makeDecision(DecisionRequest request) { // // Convert to a XacmlRequest // diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/XacmlPolicyUtilsTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/XacmlPolicyUtilsTest.java index fe0f675d..ed63bb9c 100644 --- a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/XacmlPolicyUtilsTest.java +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/XacmlPolicyUtilsTest.java @@ -225,7 +225,7 @@ public class XacmlPolicyUtilsTest { } @Test - public void testRemovingProperties() { + public void testRemovingReferencedProperties() { // // Dump what we are starting with // @@ -261,4 +261,27 @@ public class XacmlPolicyUtilsTest { XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER); assertThat(properties.getProperty("refstart4.file")).isNullOrEmpty(); } + + @Test + public void testRemovingRootProperties() { + // + // Dump what we are starting with + // + XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER); + // + // Remove root policies + // + Path ref = Paths.get("src/test/resources/root.xml"); + XacmlPolicyUtils.removeRootPolicy(properties, ref); + XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER); + assertThat(properties.getProperty("root.file")).isNullOrEmpty(); + + // + // Test one that isn't in there + // + ref = Paths.get("src/test/resources/NotThere.xml"); + XacmlPolicyUtils.removeRootPolicy(properties, ref); + XacmlPolicyUtils.debugDumpPolicyProperties(properties, LOGGER); + assertThat(properties.getProperty("refstart3.file")).isNotBlank(); + } } diff --git a/applications/monitoring/src/test/java/org/onap/policy/xacml/pdp/application/monitoring/MonitoringPdpApplicationTest.java b/applications/monitoring/src/test/java/org/onap/policy/xacml/pdp/application/monitoring/MonitoringPdpApplicationTest.java index cc11dcf6..9b26df16 100644 --- a/applications/monitoring/src/test/java/org/onap/policy/xacml/pdp/application/monitoring/MonitoringPdpApplicationTest.java +++ b/applications/monitoring/src/test/java/org/onap/policy/xacml/pdp/application/monitoring/MonitoringPdpApplicationTest.java @@ -27,6 +27,7 @@ import static org.assertj.core.api.Assertions.assertThat; import java.io.File; import java.io.IOException; import java.util.Iterator; +import java.util.List; import java.util.Properties; import java.util.ServiceLoader; @@ -41,6 +42,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.TestUtils; import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException; @@ -161,7 +163,8 @@ public class MonitoringPdpApplicationTest { // // Now load the optimization policies // - TestUtils.loadPolicies("src/test/resources/vDNS.policy.input.yaml", service); + final List<ToscaPolicy> loadedPolicies = TestUtils.loadPolicies("src/test/resources/vDNS.policy.input.yaml", + service); // // Ask for a decision // @@ -174,6 +177,21 @@ public class MonitoringPdpApplicationTest { // Dump it out as Json // LOGGER.info(gson.encode(response)); + LOGGER.info("Now testing unloading of policy"); + // + // Now unload it + // + for (ToscaPolicy policy : loadedPolicies) { + assertThat(service.unloadPolicy(policy)).isTrue(); + } + // + // Ask for a decision + // + response = service.makeDecision(requestSinglePolicy); + LOGGER.info("Decision {}", response); + + assertThat(response).isNotNull(); + assertThat(response.getPolicies().size()).isEqualTo(0); } @Test diff --git a/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpMessage.java b/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpMessage.java index 809e43d0..1253ff28 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpMessage.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpMessage.java @@ -22,7 +22,6 @@ package org.onap.policy.pdpx.main.comm; -import java.net.UnknownHostException; import org.onap.policy.common.utils.network.NetworkUtil; import org.onap.policy.models.pdp.concepts.PdpStateChange; import org.onap.policy.models.pdp.concepts.PdpStatus; @@ -111,7 +110,7 @@ public class XacmlPdpMessage { status.setPdpGroup(message.getPdpGroup()); status.setPdpSubgroup(message.getPdpSubgroup()); status.setSupportedPolicyTypes(XacmlPdpApplicationManager.getToscaPolicyTypeIdents()); - status.setPolicies(XacmlPdpApplicationManager.getToscaPolicies()); + status.setPolicies(XacmlPdpApplicationManager.getToscaPolicyIdentifiers()); return status; } diff --git a/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisher.java b/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisher.java index 716421c7..4c9d0c21 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisher.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisher.java @@ -20,6 +20,8 @@ package org.onap.policy.pdpx.main.comm; +import java.util.HashSet; +import java.util.Set; import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient; import org.onap.policy.models.pdp.concepts.PdpStatus; import org.onap.policy.models.pdp.concepts.PdpUpdate; @@ -45,9 +47,26 @@ public class XacmlPdpUpdatePublisher { public static void handlePdpUpdate(PdpUpdate message, TopicSinkClient client) { if (!message.getPolicies().isEmpty() || message.getPolicies() != null) { - // Load the policies on PDP applications - for (ToscaPolicy toscaPolicy : message.getPolicies()) { - XacmlPdpApplicationManager.loadDeployedPolicy(toscaPolicy); + + Set<ToscaPolicy> incomingPolicies = + new HashSet<>(message.getPolicies()); + Set<ToscaPolicy> deployedPolicies = + new HashSet<>(XacmlPdpApplicationManager.getToscaPolicies().keySet()); + + // Undeploy a policy + // if incoming policies do not contain the deployed policy then remove it from PDP + for (ToscaPolicy policy : deployedPolicies) { + if (!incomingPolicies.contains(policy)) { + XacmlPdpApplicationManager.removeUndeployedPolicy(policy); + } + } + + // Deploy a policy + // if deployed policies do not contain the incoming policy load it + for (ToscaPolicy policy : incomingPolicies) { + if (!deployedPolicies.contains(policy)) { + XacmlPdpApplicationManager.loadDeployedPolicy(policy); + } } } diff --git a/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpApplicationManager.java b/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpApplicationManager.java index 09805593..785d7591 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpApplicationManager.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpApplicationManager.java @@ -29,6 +29,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.ServiceLoader; +import java.util.stream.Collectors; import org.onap.policy.models.decisions.concepts.DecisionRequest; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier; @@ -45,7 +46,10 @@ public class XacmlPdpApplicationManager { private static ServiceLoader<XacmlApplicationServiceProvider> applicationLoader; private static Map<String, XacmlApplicationServiceProvider> providerActionMap = new HashMap<>(); private static List<ToscaPolicyTypeIdentifier> toscaPolicyTypeIdents = new ArrayList<>(); - private static List<ToscaPolicyIdentifier> toscaPolicies = new ArrayList<>(); + private static List<ToscaPolicyIdentifier> toscaPolicyIdents = new ArrayList<>(); + private static List<ToscaPolicy> toscaPolicies = new ArrayList<>(); + private static Map<ToscaPolicy, XacmlApplicationServiceProvider> mapLoadedPolicies = new HashMap<>(); + private XacmlPdpApplicationManager() { super(); @@ -115,11 +119,55 @@ public class XacmlPdpApplicationManager { return providerActionMap.get(request.getAction()); } + /** + * getToscaPolicies. + * + * @return the map containing ToscaPolicies + */ + public static Map<ToscaPolicy, XacmlApplicationServiceProvider> getToscaPolicies() { + return mapLoadedPolicies; + } + + /** + * getToscaPolicyIdentifiers. + * + * @return list of ToscaPolicyIdentifier + */ + public static List<ToscaPolicyIdentifier> getToscaPolicyIdentifiers() { + // + // converting map to return List of ToscaPolicyIdentiers + // + return mapLoadedPolicies.keySet().stream().map(ToscaPolicy::getIdentifier).collect(Collectors.toList()); + } + public static List<ToscaPolicyTypeIdentifier> getToscaPolicyTypeIdents() { return toscaPolicyTypeIdents; } /** + * Finds the appropriate application and removes the policy. + * + * @param policy Incoming policy + */ + public static void removeUndeployedPolicy(ToscaPolicy policy) { + + for (XacmlApplicationServiceProvider application : applicationLoader) { + try { + if (application.unloadPolicy(policy)) { + LOGGER.info("Unloaded ToscaPolicy {} from application {}", policy.getMetadata(), + application.applicationName()); + if (mapLoadedPolicies.remove(policy) == null) { + LOGGER.error("Failed to remove unloaded policy {} from map size {}", policy.getMetadata(), + mapLoadedPolicies.size()); + } + } + } catch (XacmlApplicationException e) { + LOGGER.error("Failed to undeploy the Tosca Policy", e); + } + } + } + + /** * Finds the appropriate application and loads the policy. * * @param policy Incoming policy @@ -134,7 +182,11 @@ public class XacmlPdpApplicationManager { // just use the first one found. // if (application.canSupportPolicyType(policy.getTypeIdentifier())) { - application.loadPolicy(policy); + if (application.loadPolicy(policy)) { + LOGGER.info("Loaded ToscaPolicy {} into application {}", policy.getMetadata(), + application.applicationName()); + mapLoadedPolicies.put(policy, application); + } return; } } catch (XacmlApplicationException e) { @@ -143,10 +195,6 @@ public class XacmlPdpApplicationManager { } } - public static List<ToscaPolicyIdentifier> getToscaPolicies() { - return toscaPolicies; - } - /** * Returns the current count of policy types supported. This could be misleading a bit * as some applications can support wildcard of policy types. Eg. onap.Monitoring.* as diff --git a/packages/policy-xacmlpdp-tarball/src/main/package/tarball/assembly.xml b/packages/policy-xacmlpdp-tarball/src/main/package/tarball/assembly.xml index e08be24d..3b027650 100644 --- a/packages/policy-xacmlpdp-tarball/src/main/package/tarball/assembly.xml +++ b/packages/policy-xacmlpdp-tarball/src/main/package/tarball/assembly.xml @@ -42,6 +42,7 @@ <includes> <include>*.json</include> <include>*.xml</include> + <include>*.properties</include> </includes> <outputDirectory>/etc</outputDirectory> <lineEnding>unix</lineEnding> @@ -58,5 +59,32 @@ <outputDirectory>/etc/ssl</outputDirectory> <lineEnding>keep</lineEnding> </fileSet> + <fileSet> + <directory>${project.basedir}/src/main/resources/apps/guard + </directory> + <includes> + <include>*.properties</include> + </includes> + <outputDirectory>/apps/guard</outputDirectory> + <lineEnding>unix</lineEnding> + </fileSet> + <fileSet> + <directory>${project.basedir}/src/main/resources/apps/monitoring + </directory> + <includes> + <include>*.properties</include> + </includes> + <outputDirectory>/apps/monitoring</outputDirectory> + <lineEnding>unix</lineEnding> + </fileSet> + <fileSet> + <directory>${project.basedir}/src/main/resources/apps/optimization + </directory> + <includes> + <include>*.properties</include> + </includes> + <outputDirectory>/apps/optimization</outputDirectory> + <lineEnding>unix</lineEnding> + </fileSet> </fileSets> </assembly> |