Adding optimization application finish guard 62/83062/6
authorPamela Dragosh <pdragosh@research.att.com>
Fri, 22 Mar 2019 18:12:52 +0000 (14:12 -0400)
committerPamela Dragosh <pdragosh@research.att.com>
Mon, 25 Mar 2019 17:54:56 +0000 (13:54 -0400)
Created Optimization application and created a translator
for it. The translator makes an assumption that OOF wants
to query on policyScope and policyType properties.

Rearranged some of the test code for re-usability.

Guard policies are now creating for frequency limiter
and min max. Probably could use some clean up.

Upgraded to xacml 2.0.1 to include a fix for handling
null attribute values.

Added some code to test missing values.

Issue-ID: POLICY-1273
Change-Id: Ia3dbfa992bbe0cbb5aa294c38aa2aff430a3230a
Signed-off-by: Pamela Dragosh <pdragosh@research.att.com>
38 files changed:
applications/common/pom.xml
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/OnapPolicyFinderFactory.java
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaDictionary.java
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/XacmlPolicyUtils.java
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyRequest.java
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyResultsTranslator.java
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequest.java [new file with mode: 0644]
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslator.java [new file with mode: 0644]
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMetadataTranslator.java [deleted file]
applications/guard/pom.xml
applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplication.java
applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardPolicyRequest.java [new file with mode: 0644]
applications/guard/src/main/java/org/onap/policy/xacml/pdp/application/guard/LegacyGuardTranslator.java [new file with mode: 0644]
applications/guard/src/test/java/org/onap/policy/xacml/pdp/application/guard/GuardPdpApplicationTest.java
applications/guard/src/test/resources/guard.policy-minmax-missing-fields1.yaml [new file with mode: 0644]
applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml [new file with mode: 0644]
applications/guard/src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml [new file with mode: 0644]
applications/guard/src/test/resources/xacml.properties
applications/monitoring/pom.xml
applications/monitoring/src/main/java/org/onap/policy/xacml/pdp/application/monitoring/MonitoringRequest.java [deleted file]
applications/monitoring/src/test/java/org/onap/policy/xacml/pdp/application/monitoring/MonitoringPdpApplicationTest.java
applications/monitoring/src/test/resources/vDNS.policy.decision.payload.json [deleted file]
applications/monitoring/src/test/resources/xacml.properties
applications/optimization/pom.xml [new file with mode: 0644]
applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplication.java [new file with mode: 0644]
applications/optimization/src/main/resources/META-INF/services/org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider [new file with mode: 0644]
applications/optimization/src/test/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplicationTest.java [new file with mode: 0644]
applications/optimization/src/test/resources/vCPE.policies.optimization.input.tosca.yaml [new file with mode: 0644]
applications/optimization/src/test/resources/xacml.properties [new file with mode: 0644]
applications/pom.xml
main/pom.xml
main/src/test/resources/decisions/decision.guard.shoulddeny.input.json
main/src/test/resources/decisions/decision.guard.shoulddeny.input2.json [new file with mode: 0644]
main/src/test/resources/decisions/decision.guard.shoulddeny.output.json [deleted file]
main/src/test/resources/decisions/decision.guard.shouldpermit.input.json
main/src/test/resources/decisions/decision.guard.shouldpermit.output.json [deleted file]
main/src/test/resources/decisions/decision.optimization.affinity.input.json [new file with mode: 0644]
pom.xml

index 3001730..1e75e0d 100644 (file)
@@ -45,7 +45,7 @@
         <dependency>
             <groupId>com.att.research.xacml</groupId>
             <artifactId>xacml-pdp</artifactId>
-            <version>2.0.0</version>
+            <version>2.0.1</version>
         </dependency>
     </dependencies>
 </project>
index 7da455c..6635201 100644 (file)
 
 package org.onap.policy.pdp.xacml.application.common;
 
+import com.att.research.xacml.std.IdentifierImpl;
 import com.att.research.xacml.std.StdStatusCode;
+import com.att.research.xacml.std.StdVersion;
 import com.att.research.xacml.std.dom.DOMStructureException;
 import com.att.research.xacml.util.FactoryException;
 import com.att.research.xacml.util.XACMLProperties;
+import com.att.research.xacmlatt.pdp.policy.CombiningAlgorithm;
+import com.att.research.xacmlatt.pdp.policy.CombiningAlgorithmFactory;
 import com.att.research.xacmlatt.pdp.policy.Policy;
 import com.att.research.xacmlatt.pdp.policy.PolicyDef;
 import com.att.research.xacmlatt.pdp.policy.PolicyFinder;
 import com.att.research.xacmlatt.pdp.policy.PolicyFinderFactory;
+import com.att.research.xacmlatt.pdp.policy.PolicySet;
+import com.att.research.xacmlatt.pdp.policy.PolicySetChild;
+import com.att.research.xacmlatt.pdp.policy.Target;
 import com.att.research.xacmlatt.pdp.policy.dom.DOMPolicyDef;
 import com.att.research.xacmlatt.pdp.std.StdPolicyFinder;
+import com.att.research.xacmlatt.pdp.util.ATTPDPProperties;
 import com.google.common.base.Splitter;
 import com.google.common.base.Strings;
 
@@ -43,6 +51,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Properties;
+import java.util.UUID;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -212,7 +221,49 @@ public class OnapPolicyFinderFactory extends PolicyFinderFactory {
     protected synchronized void init() {
         if (this.needsInit) {
             logger.debug("Initializing OnapPolicyFinderFactory Properties ");
-            this.rootPolicies       = this.getPolicyDefs(XACMLProperties.PROP_ROOTPOLICIES);
+
+            //
+            // Check for property that combines root policies into one policyset
+            //
+            String combiningAlgorithm = properties.getProperty(
+                    ATTPDPProperties.PROP_POLICYFINDERFACTORY_COMBINEROOTPOLICIES);
+            if (combiningAlgorithm != null) {
+                try {
+                    logger.info("Combining root policies with {}", combiningAlgorithm);
+                    //
+                    // Find the combining algorithm
+                    //
+                    CombiningAlgorithm<PolicySetChild> algorithm = CombiningAlgorithmFactory.newInstance()
+                            .getPolicyCombiningAlgorithm(new IdentifierImpl(combiningAlgorithm));
+                    //
+                    // Create our root policy
+                    //
+                    PolicySet root = new PolicySet();
+                    root.setIdentifier(new IdentifierImpl(UUID.randomUUID().toString()));
+                    root.setVersion(StdVersion.newInstance("1.0"));
+                    root.setTarget(new Target());
+                    //
+                    // Set the algorithm
+                    //
+                    root.setPolicyCombiningAlgorithm(algorithm);
+                    //
+                    // Load all our root policies
+                    //
+                    for (PolicyDef policy : this.getPolicyDefs(XACMLProperties.PROP_ROOTPOLICIES)) {
+                        root.addChild(policy);
+                    }
+                    //
+                    // Set this policy as the root
+                    //
+                    this.rootPolicies = new ArrayList<>();
+                    this.rootPolicies.add(root);
+                } catch (Exception e) {
+                    logger.error("Failed to load Combining Algorithm Factory: {}", e.getLocalizedMessage());
+                }
+            } else {
+                logger.info("Loading root policies");
+                this.rootPolicies       = this.getPolicyDefs(XACMLProperties.PROP_ROOTPOLICIES);
+            }
             this.referencedPolicies = this.getPolicyDefs(XACMLProperties.PROP_REFERENCEDPOLICIES);
             logger.debug("Root Policies: {}", this.rootPolicies.size());
             logger.debug("Referenced Policies: {}", this.referencedPolicies.size());
index 352e51d..0dcafa0 100644 (file)
@@ -43,6 +43,68 @@ public final class ToscaDictionary {
     public static final Identifier ID_RESOURCE_POLICY_TYPE_VERSION =
             new IdentifierImpl(URN_ONAP, "policy-type-version");
 
+    /*
+     * These ID's are for identifying Subjects
+     */
+
+    public static final Identifier ID_SUBJECT_ONAP_NAME =
+            XACML3.ID_SUBJECT_SUBJECT_ID;
+
+    public static final Identifier ID_SUBJECT_ONAP_COMPONENT =
+            new IdentifierImpl(URN_ONAP, "onap-component");
+
+    public static final Identifier ID_SUBJECT_ONAP_INSTANCE =
+            new IdentifierImpl(URN_ONAP, "onap-instance");
+
+    /*
+     * These 2 ID's are for Optimization policies
+     */
+
+    public static final Identifier ID_RESOURCE_POLICY_SCOPE_PROPERTY =
+            new IdentifierImpl(URN_ONAP, "policy-scope-property");
+
+    public static final Identifier ID_RESOURCE_POLICY_TYPE_PROPERTY =
+            new IdentifierImpl(URN_ONAP, "policy-type-property");
+
+    /*
+     * These ID's are for Legacy Guard Policies
+     */
+    public static final Identifier ID_RESOURCE_GUARD_ACTOR =
+            new IdentifierImpl(URN_ONAP, "guard:actor:actor-id");
+    public static final Identifier ID_RESOURCE_GUARD_RECIPE =
+            new IdentifierImpl(URN_ONAP, "guard:operation:operation-id");
+    public static final Identifier ID_RESOURCE_GUARD_CLNAME =
+            new IdentifierImpl(URN_ONAP, "guard:clname:clname-id");
+    public static final Identifier ID_RESOURCE_GUARD_TARGETID =
+            new IdentifierImpl(URN_ONAP, "guard:target:target-id");
+    public static final Identifier ID_SUBJECT_GUARD_REQUESTID =
+            new IdentifierImpl(URN_ONAP, "guard:request:request-id");
+    public static final Identifier ID_RESOURCE_GUARD_VFCOUNT =
+            new IdentifierImpl(URN_ONAP, "guard:target:vf-count");
+    public static final Identifier ID_RESOURCE_GUARD_MIN =
+            new IdentifierImpl(URN_ONAP, "guard:target:min");
+    public static final Identifier ID_RESOURCE_GUARD_MAX =
+            new IdentifierImpl(URN_ONAP, "guard:target:max");
+
+    /*
+     * This id specifically for guard is provided by the
+     * operational history database PIP.
+     */
+    public static final Identifier ID_RESOURCE_GUARD_OPERATIONCOUNT =
+            new IdentifierImpl(URN_ONAP, "guard:operation:operation-count");
+
+    /*
+     * This id is specifically for advice returned from guard
+     */
+    public static final Identifier ID_ADVICE_GUARD =
+            new IdentifierImpl(URN_ONAP, "guard:advice");
+    public static final Identifier ID_ADVICE_GUARD_REQUESTID =
+            new IdentifierImpl(URN_ONAP, "guard:advice:request-id");
+
+    /*
+     * Obligation specific ID's
+     */
+
     public static final Identifier ID_OBLIGATION_REST_BODY =
             new IdentifierImpl(URN_ONAP, "rest:body");
 
@@ -61,6 +123,8 @@ public final class ToscaDictionary {
     public static final Identifier ID_OBLIGATION_MONITORING_ISSUER =
             new IdentifierImpl(URN_ONAP, "issuer:monitoring");
 
+
+
     private ToscaDictionary() {
         super();
     }
index ca327b9..46742af 100644 (file)
 package org.onap.policy.pdp.xacml.application.common;
 
 import com.att.research.xacml.api.Identifier;
-import com.att.research.xacml.api.pdp.PDPEngine;
-import com.att.research.xacml.api.pdp.PDPEngineFactory;
-import com.att.research.xacml.util.FactoryException;
 import com.att.research.xacml.util.XACMLProperties;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -145,6 +145,40 @@ public class XacmlPolicyUtils {
         return rootPolicy;
     }
 
+    /**
+     * Adds in the root policy to the PDP properties object.
+     *
+     * @param properties Input properties
+     * @param rootPolicyPath Path to the root policy file
+     * @return Properties object
+     */
+    public static Properties addRootPolicy(Properties properties, Path rootPolicyPath) {
+        //
+        // Get the current set of referenced policy ids
+        //
+        Set<String> rootPolicies = XACMLProperties.getRootPolicyIDs(properties);
+        //
+        // Construct a unique id
+        //
+        int id = 1;
+        while (true) {
+            String refId = "ref" + id;
+            if (rootPolicies.contains(refId)) {
+                id++;
+            } else {
+                rootPolicies.add(refId);
+                properties.put(refId + DOT_FILE_SUFFIX, rootPolicyPath.toAbsolutePath().toString());
+                break;
+            }
+        }
+        //
+        // Set the new comma separated list
+        //
+        properties.setProperty(XACMLProperties.PROP_ROOTPOLICIES,
+                rootPolicies.stream().collect(Collectors.joining(",")));
+        return properties;
+    }
+
     /**
      * Adds in the referenced policy to the PDP properties object.
      *
@@ -318,23 +352,90 @@ public class XacmlPolicyUtils {
         return Paths.get(rootPath.toAbsolutePath().toString(), "xacml.properties");
     }
 
+    public interface FileCreator {
+        public File createAFile(String filename) throws IOException;
+
+    }
 
     /**
-     * Creates an instance of PDP engine given the Properties object.
+     * Copies a xacml.properties file to another location and all the policies defined within it.
      *
-     * @param properties Incoming Properties object
-     * @return PDPEngine instance or null if failed
+     * @param propertiesPath Path to an existing properties file
+     * @param properties Properties object
+     * @param creator A callback that can create files. Allows JUnit test to pass Temporary folder
+     * @return File object that points to new Properties file
+     * @throws IOException Could not read/write files
      */
-    public static PDPEngine createEngine(Properties properties) {
+    public static File copyXacmlPropertiesContents(String propertiesPath, Properties properties,
+            FileCreator creator) throws IOException {
         //
-        // Now initialize the XACML PDP Engine
+        // Open the properties file
         //
-        try {
-            PDPEngineFactory factory = PDPEngineFactory.newInstance();
-            return factory.newEngine(properties);
-        } catch (FactoryException e) {
-            LOGGER.error("Failed to create XACML PDP Engine {}", e);
+        try (InputStream is = new FileInputStream(propertiesPath)) {
+            //
+            // Load in the properties
+            //
+            properties.load(is);
+            //
+            // Now we create a new xacml.properties in the temporary folder location
+            //
+            File propertiesFile = creator.createAFile("xacml.properties");
+            //
+            // Iterate through any root policies defined
+            //
+            for (String root : XACMLProperties.getRootPolicyIDs(properties)) {
+                //
+                // Get a file
+                //
+                Path rootPath = Paths.get(properties.getProperty(root + DOT_FILE_SUFFIX));
+                LOGGER.debug("Root file {} {}", rootPath, rootPath.getFileName());
+                //
+                // Construct new path for the root policy
+                //
+                File newRootPath = creator.createAFile(rootPath.getFileName().toString());
+                //
+                // Copy the policy file to the temporary folder
+                //
+                com.google.common.io.Files.copy(rootPath.toFile(), newRootPath);
+                //
+                // Change the properties object to point to where the new policy is
+                // in the temporary folder
+                //
+                properties.setProperty(root + DOT_FILE_SUFFIX, newRootPath.getAbsolutePath());
+            }
+            //
+            // Iterate through any referenced policies defined
+            //
+            for (String referenced : XACMLProperties.getReferencedPolicyIDs(properties)) {
+                //
+                // Get a file
+                //
+                Path refPath = Paths.get(properties.getProperty(referenced + DOT_FILE_SUFFIX));
+                LOGGER.debug("Referenced file {} {}", refPath, refPath.getFileName());
+                //
+                // Construct new path for the root policy
+                //
+                File newReferencedPath = creator.createAFile(refPath.getFileName().toString());
+                //
+                // Copy the policy file to the temporary folder
+                //
+                com.google.common.io.Files.copy(refPath.toFile(), newReferencedPath);
+                //
+                // Change the properties object to point to where the new policy is
+                // in the temporary folder
+                //
+                properties.setProperty(referenced + DOT_FILE_SUFFIX, newReferencedPath.getAbsolutePath());
+            }
+            //
+            // Save the new properties file to the temporary folder
+            //
+            try (OutputStream os = new FileOutputStream(propertiesFile.getAbsolutePath())) {
+                properties.store(os, "");
+            }
+            //
+            // Return the new path to the properties folder
+            //
+            return propertiesFile;
         }
-        return null;
     }
 }
index 3914ba6..3038b65 100644 (file)
@@ -27,27 +27,41 @@ import com.att.research.xacml.std.annotations.XACMLRequest;
 import com.att.research.xacml.std.annotations.XACMLResource;
 import com.att.research.xacml.std.annotations.XACMLSubject;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
 import org.onap.policy.models.decisions.concepts.DecisionRequest;
 
+@Getter
+@Setter
+@ToString
 @XACMLRequest(ReturnPolicyIdList = true)
 public class StdCombinedPolicyRequest {
 
-    public StdCombinedPolicyRequest() {
-        super();
-    }
-
     @XACMLSubject(includeInResults = true)
-    String onapName = "DCAE";
+    private String onapName;
 
-    @XACMLResource(includeInResults = true)
-    String resource = "onap.policies.Monitoring";
+    @XACMLSubject(attributeId = "urn:org:onap:onap-component", includeInResults = true)
+    private String onapComponent;
+
+    @XACMLSubject(attributeId = "urn:org:onap:onap-instance",  includeInResults = true)
+    private String onapInstance;
 
     @XACMLAction()
-    String action = "configure";
+    private String action;
+
+    @XACMLResource(includeInResults = true)
+    private Collection<String> resource = new ArrayList<>();
 
+    public StdCombinedPolicyRequest() {
+        super();
+    }
 
     /**
      * Parses the DecisionRequest into a MonitoringRequest.
@@ -55,30 +69,57 @@ public class StdCombinedPolicyRequest {
      * @param decisionRequest Input DecisionRequest
      * @return MonitoringRequest
      */
+    @SuppressWarnings({"unchecked", "rawtypes"})
     public static StdCombinedPolicyRequest createInstance(DecisionRequest decisionRequest) {
+        //
+        // Create our request object
+        //
         StdCombinedPolicyRequest request = new StdCombinedPolicyRequest();
+        //
+        // Add the subject attributes
+        //
         request.onapName = decisionRequest.getOnapName();
+        request.onapComponent = decisionRequest.getOnapComponent();
+        request.onapInstance = decisionRequest.getOnapInstance();
+        //
+        // Add the action attribute
+        //
         request.action = decisionRequest.getAction();
-
+        //
+        // Add the resource attributes
+        //
         Map<String, Object> resources = decisionRequest.getResource();
-        for (Entry<String, Object> entry : resources.entrySet()) {
-            if ("policy-id".equals(entry.getKey())) {
-                //
-                // TODO handle lists of policies
-                //
-                request.resource = entry.getValue().toString();
+        for (Entry<String, Object> entrySet : resources.entrySet()) {
+            if ("policy-id".equals(entrySet.getKey())) {
+                if (entrySet.getValue() instanceof Collection) {
+                    addPolicyIds(request, (Collection) entrySet.getValue());
+                } else if (entrySet.getValue() instanceof String) {
+                    request.resource.add(entrySet.getValue().toString());
+                }
                 continue;
             }
-            if ("policy-type".equals(entry.getKey())) {
-                //
-                // TODO handle lists of policies
-                //
-                request.resource = entry.getValue().toString();
+            if ("policy-type".equals(entrySet.getKey())) {
+                if (entrySet.getValue() instanceof Collection) {
+                    addPolicyTypes(request, (Collection) entrySet.getValue());
+                } else if (entrySet.getValue() instanceof String) {
+                    request.resource.add(entrySet.getValue().toString());
+                }
             }
         }
-        //
-        // TODO handle a bad incoming request. Do that here?
-        //
+        return request;
+    }
+
+    private static StdCombinedPolicyRequest addPolicyIds(StdCombinedPolicyRequest request, Collection<Object> ids) {
+        for (Object id : ids) {
+            request.resource.add(id.toString());
+        }
+        return request;
+    }
+
+    private static StdCombinedPolicyRequest addPolicyTypes(StdCombinedPolicyRequest request, Collection<Object> types) {
+        for (Object type : types) {
+            request.resource.add(type.toString());
+        }
         return request;
     }
 }
index b39c2e6..1679837 100644 (file)
@@ -37,6 +37,7 @@ import com.google.gson.Gson;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -144,40 +145,55 @@ public class StdCombinedPolicyResultsTranslator implements ToscaPolicyTranslator
                 //
                 // Go through obligations
                 //
-                for (Obligation obligation : xacmlResult.getObligations()) {
-                    LOGGER.debug("Obligation: {}", obligation);
-                    for (AttributeAssignment assignment : obligation.getAttributeAssignments()) {
-                        LOGGER.debug("Attribute Assignment: {}", assignment);
-                        //
-                        // We care about the content attribute
-                        //
-                        if (ToscaDictionary.ID_OBLIGATION_POLICY_MONITORING_CONTENTS
-                                .equals(assignment.getAttributeId())) {
-                            //
-                            // The contents are in Json form
-                            //
-                            Object stringContents = assignment.getAttributeValue().getValue();
-                            if (LOGGER.isDebugEnabled()) {
-                                LOGGER.debug("DCAE contents: {}{}", System.lineSeparator(), stringContents);
-                            }
-                            //
-                            // Let's parse it into a map using Gson
-                            //
-                            Gson gson = new Gson();
-                            @SuppressWarnings("unchecked")
-                            Map<String, Object> result = gson.fromJson(stringContents.toString() ,Map.class);
-                            decisionResponse.getPolicies().add(result);
-                        }
-                    }
-                }
-            } else {
-                decisionResponse.setErrorMessage("A better error message");
+                scanObligations(xacmlResult.getObligations(), decisionResponse);
+            }
+            if (xacmlResult.getDecision() == Decision.NOTAPPLICABLE) {
+                //
+                // There is no policy
+                //
+                decisionResponse.setPolicies(new ArrayList<>());
+            }
+            if (xacmlResult.getDecision() == Decision.DENY
+                    || xacmlResult.getDecision() == Decision.INDETERMINATE) {
+                //
+                // TODO we have to return an ErrorResponse object instead
+                //
+                decisionResponse.setStatus("A better error message");
             }
         }
 
         return decisionResponse;
     }
 
+    protected void scanObligations(Collection<Obligation> obligations, DecisionResponse decisionResponse) {
+        for (Obligation obligation : obligations) {
+            LOGGER.debug("Obligation: {}", obligation);
+            for (AttributeAssignment assignment : obligation.getAttributeAssignments()) {
+                LOGGER.debug("Attribute Assignment: {}", assignment);
+                //
+                // We care about the content attribute
+                //
+                if (ToscaDictionary.ID_OBLIGATION_POLICY_MONITORING_CONTENTS
+                        .equals(assignment.getAttributeId())) {
+                    //
+                    // The contents are in Json form
+                    //
+                    Object stringContents = assignment.getAttributeValue().getValue();
+                    if (LOGGER.isDebugEnabled()) {
+                        LOGGER.debug("DCAE contents: {}{}", System.lineSeparator(), stringContents);
+                    }
+                    //
+                    // Let's parse it into a map using Gson
+                    //
+                    Gson gson = new Gson();
+                    @SuppressWarnings("unchecked")
+                    Map<String, Object> result = gson.fromJson(stringContents.toString() ,Map.class);
+                    decisionResponse.getPolicies().add(result);
+                }
+            }
+        }
+    }
+
     @SuppressWarnings("unchecked")
     protected PolicyType convertPolicy(Entry<String, Object> entrySet) throws ToscaPolicyConversionException {
         //
@@ -211,9 +227,6 @@ public class StdCombinedPolicyResultsTranslator implements ToscaPolicyTranslator
         //
         // Generate the TargetType
         //
-        //
-        // There should be a metadata section
-        //
         if (! policyDefinition.containsKey("type")) {
             throw new ToscaPolicyConversionException(policyName + " missing type value");
         }
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequest.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequest.java
new file mode 100644 (file)
index 0000000..086d21d
--- /dev/null
@@ -0,0 +1,141 @@
+/*-
+ * ============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.pdp.xacml.application.common.std;
+
+import com.att.research.xacml.std.annotations.XACMLAction;
+import com.att.research.xacml.std.annotations.XACMLRequest;
+import com.att.research.xacml.std.annotations.XACMLResource;
+import com.att.research.xacml.std.annotations.XACMLSubject;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import org.onap.policy.models.decisions.concepts.DecisionRequest;
+
+@Getter
+@Setter
+@ToString
+@XACMLRequest(ReturnPolicyIdList = true)
+public class StdMatchablePolicyRequest {
+
+    @XACMLSubject(includeInResults = true)
+    private String onapName;
+
+    @XACMLSubject(attributeId = "urn:org:onap:onap-component", includeInResults = true)
+    private String onapComponent;
+
+    @XACMLSubject(attributeId = "urn:org:onap:onap-instance",  includeInResults = true)
+    private String onapInstance;
+
+    @XACMLAction()
+    private String action;
+
+    //
+    // Unfortunately the annotations won't take an object.toString()
+    // So I could not use the ToscaDictionary class to put these id's
+    // into the annotations.
+    //
+    @XACMLResource(attributeId = "urn:org:onap:policy-scope-property", includeInResults = true)
+    Collection<String> policyScopes = new ArrayList<>();
+
+    @XACMLResource(attributeId = "urn:org:onap:policy-type-property", includeInResults = true)
+    Collection<String> policyTypes = new ArrayList<>();
+
+    public StdMatchablePolicyRequest() {
+        super();
+    }
+
+    /**
+     * Parses the DecisionRequest into a MonitoringRequest.
+     *
+     * @param decisionRequest Input DecisionRequest
+     * @return MonitoringRequest
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public static StdMatchablePolicyRequest createInstance(DecisionRequest decisionRequest) {
+        //
+        // Create our request object
+        //
+        StdMatchablePolicyRequest request = new StdMatchablePolicyRequest();
+        //
+        // Add the subject attributes
+        //
+        request.onapName = decisionRequest.getOnapName();
+        request.onapComponent = decisionRequest.getOnapComponent();
+        request.onapInstance = decisionRequest.getOnapInstance();
+        //
+        // Add the action attribute
+        //
+        request.action = decisionRequest.getAction();
+        //
+        // Add the resource attributes
+        //
+        Map<String, Object> resources = decisionRequest.getResource();
+        for (Entry<String, Object> entrySet : resources.entrySet()) {
+            //
+            // Making an assumption that these two fields are matchable.
+            // Its possible we may have to load the policy type model
+            // and use that to find the fields that are matchable.
+            //
+            if ("policyScope".equals(entrySet.getKey())) {
+                if (entrySet.getValue() instanceof Collection) {
+                    addPolicyScopes(request, (Collection) entrySet.getValue());
+                } else if (entrySet.getValue() instanceof String) {
+                    request.policyScopes.add(entrySet.getValue().toString());
+                }
+                continue;
+            }
+            if ("policyType".equals(entrySet.getKey())) {
+                if (entrySet.getValue() instanceof Collection) {
+                    addPolicyTypes(request, (Collection) entrySet.getValue());
+                }
+                if (entrySet.getValue() instanceof String) {
+                    request.policyTypes.add(entrySet.getValue().toString());
+                }
+            }
+        }
+        return request;
+    }
+
+    private static StdMatchablePolicyRequest addPolicyScopes(StdMatchablePolicyRequest request,
+            Collection<Object> scopes) {
+        for (Object scope : scopes) {
+            request.policyScopes.add(scope.toString());
+        }
+        return request;
+    }
+
+    private static StdMatchablePolicyRequest addPolicyTypes(StdMatchablePolicyRequest request,
+            Collection<Object> types) {
+        for (Object type : types) {
+            request.policyTypes.add(type.toString());
+        }
+        return request;
+    }
+}
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslator.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslator.java
new file mode 100644 (file)
index 0000000..8550b12
--- /dev/null
@@ -0,0 +1,400 @@
+/*-
+ * ============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.pdp.xacml.application.common.std;
+
+import com.att.research.xacml.api.AttributeAssignment;
+import com.att.research.xacml.api.DataTypeException;
+import com.att.research.xacml.api.Decision;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.Obligation;
+import com.att.research.xacml.api.Request;
+import com.att.research.xacml.api.Response;
+import com.att.research.xacml.api.Result;
+import com.att.research.xacml.api.XACML3;
+import com.att.research.xacml.std.annotations.RequestParser;
+import com.att.research.xacml.util.XACMLPolicyWriter;
+import com.google.gson.Gson;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionsType;
+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 oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
+
+import org.json.JSONObject;
+import org.onap.policy.models.decisions.concepts.DecisionRequest;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class StdMatchableTranslator implements ToscaPolicyTranslator {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(StdMatchableTranslator.class);
+
+    public StdMatchableTranslator() {
+        super();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<PolicyType> scanAndConvertPolicies(Map<String, Object> toscaObject)
+            throws ToscaPolicyConversionException {
+        //
+        // Our return object
+        //
+        List<PolicyType> scannedPolicies = new ArrayList<>();
+        //
+        // Iterate each of the Policies
+        //
+        List<Object> policies = (List<Object>) toscaObject.get("policies");
+        for (Object policyObject : policies) {
+            //
+            // Get the contents
+            //
+            LOGGER.debug("Found policy {}", policyObject.getClass());
+            Map<String, Object> policyContents = (Map<String, Object>) policyObject;
+            for (Entry<String, Object> entrySet : policyContents.entrySet()) {
+                LOGGER.debug("Entry set {}", entrySet);
+                //
+                // Convert this policy
+                //
+                PolicyType policy = this.convertPolicy(entrySet);
+                try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
+                    XACMLPolicyWriter.writePolicyFile(os, policy);
+                    LOGGER.debug("{}", os);
+                } catch (IOException e) {
+                    LOGGER.error("Failed to convert {}", e);
+                }
+                //
+                // Convert and add in the new policy
+                //
+                scannedPolicies.add(policy);
+            }
+        }
+
+        return scannedPolicies;
+    }
+
+    @Override
+    public Request convertRequest(DecisionRequest request) {
+        LOGGER.debug("Converting Request {}", request);
+        try {
+            return RequestParser.parseRequest(StdMatchablePolicyRequest.createInstance(request));
+        } catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) {
+            LOGGER.error("Failed to convert DecisionRequest: {}", e);
+        }
+        //
+        // TODO throw exception
+        //
+        return null;
+    }
+
+    @Override
+    public DecisionResponse convertResponse(Response xacmlResponse) {
+        LOGGER.debug("Converting Response {}", xacmlResponse);
+        DecisionResponse decisionResponse = new DecisionResponse();
+        //
+        // Iterate through all the results
+        //
+        for (Result xacmlResult : xacmlResponse.getResults()) {
+            //
+            // Check the result
+            //
+            if (xacmlResult.getDecision() == Decision.PERMIT) {
+                //
+                // Setup policies
+                //
+                decisionResponse.setPolicies(new ArrayList<>());
+                //
+                // Go through obligations
+                //
+                scanObligations(xacmlResult.getObligations(), decisionResponse);
+            }
+            if (xacmlResult.getDecision() == Decision.NOTAPPLICABLE) {
+                //
+                // There is no policy
+                //
+                decisionResponse.setPolicies(new ArrayList<>());
+            }
+            if (xacmlResult.getDecision() == Decision.DENY
+                    || xacmlResult.getDecision() == Decision.INDETERMINATE) {
+                //
+                // TODO we have to return an ErrorResponse object instead
+                //
+                decisionResponse.setStatus("A better error message");
+            }
+        }
+
+        return decisionResponse;
+    }
+
+    protected void scanObligations(Collection<Obligation> obligations, DecisionResponse decisionResponse) {
+        for (Obligation obligation : obligations) {
+            LOGGER.debug("Obligation: {}", obligation);
+            for (AttributeAssignment assignment : obligation.getAttributeAssignments()) {
+                LOGGER.debug("Attribute Assignment: {}", assignment);
+                //
+                // We care about the content attribute
+                //
+                if (ToscaDictionary.ID_OBLIGATION_POLICY_MONITORING_CONTENTS
+                        .equals(assignment.getAttributeId())) {
+                    //
+                    // The contents are in Json form
+                    //
+                    Object stringContents = assignment.getAttributeValue().getValue();
+                    if (LOGGER.isDebugEnabled()) {
+                        LOGGER.debug("DCAE contents: {}{}", System.lineSeparator(), stringContents);
+                    }
+                    //
+                    // Let's parse it into a map using Gson
+                    //
+                    Gson gson = new Gson();
+                    @SuppressWarnings("unchecked")
+                    Map<String, Object> result = gson.fromJson(stringContents.toString() ,Map.class);
+                    decisionResponse.getPolicies().add(result);
+                }
+            }
+        }
+
+    }
+
+    @SuppressWarnings("unchecked")
+    protected PolicyType convertPolicy(Entry<String, Object> entrySet) throws ToscaPolicyConversionException {
+        //
+        // Policy name should be at the root
+        //
+        String policyName = entrySet.getKey();
+        Map<String, Object> policyDefinition = (Map<String, Object>) entrySet.getValue();
+        //
+        // Set it as the policy ID
+        //
+        PolicyType newPolicyType = new PolicyType();
+        newPolicyType.setPolicyId(policyName);
+        //
+        // Optional description
+        //
+        if (policyDefinition.containsKey("description")) {
+            newPolicyType.setDescription(policyDefinition.get("description").toString());
+        }
+        //
+        // There should be a metadata section
+        //
+        if (! policyDefinition.containsKey("metadata")) {
+            throw new ToscaPolicyConversionException(policyName + " missing metadata section");
+        }
+        this.fillMetadataSection(newPolicyType,
+                (Map<String, Object>) policyDefinition.get("metadata"));
+        //
+        // Set the combining rule
+        //
+        newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_FIRST_APPLICABLE.stringValue());
+        //
+        // Generate the TargetType
+        //
+        if (! policyDefinition.containsKey("properties")) {
+            throw new ToscaPolicyConversionException(policyName + " missing properties section");
+        }
+        policyDefinition.get("properties");
+        newPolicyType.setTarget(generateTargetType((Map<String, Object>) policyDefinition.get("properties")));
+        //
+        // Now create the Permit Rule
+        // No target since the policy has a target
+        // With obligations.
+        //
+        RuleType rule = new RuleType();
+        rule.setDescription("Default is to PERMIT if the policy matches.");
+        rule.setRuleId(policyName + ":rule");
+        rule.setEffect(EffectType.PERMIT);
+        rule.setTarget(new TargetType());
+        //
+        // Now represent the policy as Json
+        //
+        JSONObject jsonObligation = new JSONObject();
+        jsonObligation.put(policyName, policyDefinition);
+        addObligation(rule, jsonObligation);
+        //
+        // Add the rule to the policy
+        //
+        newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(rule);
+        //
+        // Return our new policy
+        //
+        return newPolicyType;
+    }
+
+    /**
+     * From the TOSCA metadata section, pull in values that are needed into the XACML policy.
+     *
+     * @param policy Policy Object to store the metadata
+     * @param metadata The Metadata TOSCA Map
+     * @return Same Policy Object
+     * @throws ToscaPolicyConversionException If there is something missing from the metadata
+     */
+    protected PolicyType fillMetadataSection(PolicyType policy,
+            Map<String, Object> metadata) throws ToscaPolicyConversionException {
+        if (! metadata.containsKey("policy-id")) {
+            throw new ToscaPolicyConversionException(policy.getPolicyId() + " missing metadata policy-id");
+        } else {
+            //
+            // Do nothing here - the XACML PolicyId is used from TOSCA Policy Name field
+            //
+        }
+        if (! metadata.containsKey("policy-version")) {
+            throw new ToscaPolicyConversionException(policy.getPolicyId() + " missing metadata policy-version");
+        } else {
+            //
+            // Add in the Policy Version
+            //
+            policy.setVersion(metadata.get("policy-version").toString());
+        }
+        return policy;
+    }
+
+    /**
+     * For generating target type, we are making an assumption that the
+     * policyScope and policyType are the fields that OOF wants to match on.
+     *
+     * <P>In the future, we would need to receive the Policy Type specification
+     * from the PAP so we can dynamically see which fields are matchable.
+     *
+     * <P>Note: I am making an assumption that the matchable fields are what
+     * the OOF wants to query a policy on.
+     *
+     * @param properties Properties section of policy
+     * @return TargetType object
+     */
+    @SuppressWarnings("unchecked")
+    protected TargetType generateTargetType(Map<String, Object> properties) {
+        TargetType targetType = new TargetType();
+        //
+        // Iterate the properties
+        //
+        for (Entry<String, Object> entrySet : properties.entrySet()) {
+            //
+            // Find policyScope and policyType
+            //
+            if (entrySet.getKey().equals("policyScope")) {
+                LOGGER.debug("Found policyScope: {}", entrySet.getValue());
+                if (entrySet.getValue() instanceof Collection) {
+                    targetType.getAnyOf().add(generateMatches((Collection<Object>) entrySet.getValue(),
+                            ToscaDictionary.ID_RESOURCE_POLICY_SCOPE_PROPERTY));
+                } else if (entrySet.getValue() instanceof String) {
+                    targetType.getAnyOf().add(generateMatches(Arrays.asList(entrySet.getValue()),
+                            ToscaDictionary.ID_RESOURCE_POLICY_SCOPE_PROPERTY));
+                }
+            }
+            if (entrySet.getKey().equals("policyType")) {
+                LOGGER.debug("Found policyType: {}", entrySet.getValue());
+                if (entrySet.getValue() instanceof Collection) {
+                    targetType.getAnyOf().add(generateMatches((Collection<Object>) entrySet.getValue(),
+                            ToscaDictionary.ID_RESOURCE_POLICY_TYPE_PROPERTY));
+                } else if (entrySet.getValue() instanceof String) {
+                    targetType.getAnyOf().add(generateMatches(Arrays.asList(entrySet.getValue()),
+                            ToscaDictionary.ID_RESOURCE_POLICY_TYPE_PROPERTY));
+                }
+            }
+        }
+
+        return targetType;
+    }
+
+    protected AnyOfType generateMatches(Collection<Object> matchables, Identifier attributeId) {
+        //
+        // This is our outer AnyOf - which is an OR
+        //
+        AnyOfType anyOf = new AnyOfType();
+        for (Object matchable : matchables) {
+            //
+            // Create a match for this
+            //
+            MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
+                    XACML3.ID_FUNCTION_STRING_EQUAL,
+                    matchable.toString(),
+                    XACML3.ID_DATATYPE_STRING,
+                    attributeId,
+                    XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
+            //
+            // Now create an anyOf (OR)
+            //
+            anyOf.getAllOf().add(ToscaPolicyTranslatorUtils.buildAllOf(match));
+        }
+        return anyOf;
+    }
+
+    protected RuleType addObligation(RuleType rule, JSONObject jsonPolicy) {
+        //
+        // Convert the YAML Policy to JSON Object
+        //
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("JSON Optimization Policy {}{}", System.lineSeparator(), jsonPolicy);
+        }
+        //
+        // Create an AttributeValue for it
+        //
+        AttributeValueType value = new AttributeValueType();
+        value.setDataType(ToscaDictionary.ID_OBLIGATION_POLICY_MONITORING_DATATYPE.stringValue());
+        value.getContent().add(jsonPolicy.toString());
+        //
+        // Create our AttributeAssignmentExpression where we will
+        // store the contents of the policy in JSON format.
+        //
+        AttributeAssignmentExpressionType expressionType = new AttributeAssignmentExpressionType();
+        expressionType.setAttributeId(ToscaDictionary.ID_OBLIGATION_POLICY_MONITORING_CONTENTS.stringValue());
+        ObjectFactory factory = new ObjectFactory();
+        expressionType.setExpression(factory.createAttributeValue(value));
+        //
+        // Create an ObligationExpression for it
+        //
+        ObligationExpressionType obligation = new ObligationExpressionType();
+        obligation.setFulfillOn(EffectType.PERMIT);
+        obligation.setObligationId(ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue());
+        obligation.getAttributeAssignmentExpression().add(expressionType);
+        //
+        // Now we can add it into the rule
+        //
+        ObligationExpressionsType obligations = new ObligationExpressionsType();
+        obligations.getObligationExpression().add(obligation);
+        rule.setObligationExpressions(obligations);
+        return rule;
+    }
+
+}
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMetadataTranslator.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMetadataTranslator.java
deleted file mode 100644 (file)
index 11651f4..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*-
- * ============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.pdp.xacml.application.common.std;
-
-import com.att.research.xacml.api.Request;
-import com.att.research.xacml.api.Response;
-import com.att.research.xacml.util.XACMLPolicyWriter;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
-
-import org.onap.policy.models.decisions.concepts.DecisionRequest;
-import org.onap.policy.models.decisions.concepts.DecisionResponse;
-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;
-
-public class StdMetadataTranslator implements ToscaPolicyTranslator {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(StdMetadataTranslator.class);
-
-    public StdMetadataTranslator() {
-        super();
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public List<PolicyType> scanAndConvertPolicies(Map<String, Object> toscaObject)
-            throws ToscaPolicyConversionException {
-        //
-        // Our return object
-        //
-        List<PolicyType> scannedPolicies = new ArrayList<>();
-        //
-        // Iterate each of the Policies
-        //
-        List<Object> policies = (List<Object>) toscaObject.get("policies");
-        for (Object policyObject : policies) {
-            //
-            // Get the contents
-            //
-            LOGGER.debug("Found policy {}", policyObject.getClass());
-            Map<String, Object> policyContents = (Map<String, Object>) policyObject;
-            for (Entry<String, Object> entrySet : policyContents.entrySet()) {
-                LOGGER.debug("Entry set {}", entrySet);
-                //
-                // Convert this policy
-                //
-                PolicyType policy = this.convertPolicy(entrySet);
-                try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
-                    XACMLPolicyWriter.writePolicyFile(os, policy);
-                    LOGGER.debug("{}", os);
-                } catch (IOException e) {
-                    LOGGER.error("Failed to convert {}", e);
-                }
-                //
-                // Convert and add in the new policy
-                //
-                scannedPolicies.add(policy);
-            }
-        }
-
-        return scannedPolicies;
-    }
-
-    @Override
-    public Request convertRequest(DecisionRequest request) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public DecisionResponse convertResponse(Response xacmlResponse) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    private PolicyType convertPolicy(Entry<String, Object> entrySet) throws ToscaPolicyConversionException {
-
-        return null;
-    }
-
-}
index 7ee3da0..6696e55 100644 (file)
     <description>This modules contain an application that implements onap.Guard policy-types for XACML PDP.</description>
 
     <dependencies>
-        <dependency>
-            <groupId>com.google.code.gson</groupId>
-            <artifactId>gson</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.onap.policy.common</groupId>
-            <artifactId>common-parameters</artifactId>
-            <version>${policy.common.version}</version>
-        </dependency>
         <dependency>
             <groupId>org.onap.policy.xacml-pdp.applications</groupId>
             <artifactId>common</artifactId>
index 1838523..1b12fca 100644 (file)
@@ -24,19 +24,23 @@ 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.XACMLPolicyWriter;
 import com.google.common.collect.Lists;
 
+import java.io.IOException;
+import java.nio.file.Path;
 import java.util.Arrays;
 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;
 
 import org.onap.policy.models.decisions.concepts.DecisionRequest;
 import org.onap.policy.models.decisions.concepts.DecisionResponse;
 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
-import org.onap.policy.pdp.xacml.application.common.std.StdMetadataTranslator;
+import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
 import org.onap.policy.pdp.xacml.application.common.std.StdXacmlApplicationServiceProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -52,7 +56,7 @@ public class GuardPdpApplication extends StdXacmlApplicationServiceProvider {
     private static final Logger LOGGER = LoggerFactory.getLogger(GuardPdpApplication.class);
     private static final String STRING_VERSION100 = "1.0.0";
     private Map<String, String> supportedPolicyTypes = new HashMap<>();
-    private StdMetadataTranslator translator = new StdMetadataTranslator();
+    private LegacyGuardTranslator translator = new LegacyGuardTranslator();
 
     /** Constructor.
      *
@@ -103,9 +107,37 @@ public class GuardPdpApplication extends StdXacmlApplicationServiceProvider {
                 throw new ToscaPolicyConversionException("Converted 0 policies");
             }
             //
-            // TODO update properties, save to disk, etc.
+            // Create a copy of the properties object
             //
-        } catch (ToscaPolicyConversionException e) {
+            Properties newProperties = this.getProperties();
+            //
+            // Iterate through the policies
+            //
+            for (PolicyType newPolicy : listPolicies) {
+                //
+                // Construct the filename
+                //
+                Path refPath = XacmlPolicyUtils.constructUniquePolicyFilename(newPolicy, this.getDataPath());
+                //
+                // Write the policy to disk
+                // Maybe check for an error
+                //
+                XACMLPolicyWriter.writePolicyFile(refPath, newPolicy);
+                //
+                // Add root policy to properties object
+                //
+                XacmlPolicyUtils.addRootPolicy(newProperties, refPath);
+            }
+            //
+            // Write the properties to disk
+            //
+            XacmlPolicyUtils.storeXacmlProperties(newProperties,
+                    XacmlPolicyUtils.getPropertiesPath(this.getDataPath()));
+            //
+            // Reload the engine
+            //
+            this.createEngine(newProperties);
+        } catch (IOException | ToscaPolicyConversionException e) {
             LOGGER.error("Failed to loadPolicies {}", e);
         }
     }
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
new file mode 100644 (file)
index 0000000..0b5b567
--- /dev/null
@@ -0,0 +1,163 @@
+/*-
+ * ============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.std.annotations.XACMLAction;
+import com.att.research.xacml.std.annotations.XACMLRequest;
+import com.att.research.xacml.std.annotations.XACMLResource;
+import com.att.research.xacml.std.annotations.XACMLSubject;
+
+import java.util.Map;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import org.onap.policy.models.decisions.concepts.DecisionRequest;
+
+@Getter
+@Setter
+@ToString
+@XACMLRequest(ReturnPolicyIdList = true)
+public class LegacyGuardPolicyRequest {
+
+    private static final String STR_GUARD = "guard";
+
+    @XACMLSubject(includeInResults = true)
+    private String onapName;
+
+    @XACMLSubject(includeInResults = true, attributeId = "urn:org:onap:onap-component")
+    private String onapComponent;
+
+    @XACMLSubject(includeInResults = true, attributeId = "urn:org:onap:onap-instance")
+    private String onapInstance;
+
+    @XACMLSubject(includeInResults = true, attributeId = "urn:org:onap:guard:request:request-id")
+    private String requestId;
+
+    @XACMLAction
+    private String action = STR_GUARD;
+
+    @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:clname:clname-id")
+    private String clnameId;
+
+    @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:actor:actor-id")
+    private String actorId;
+
+    @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:operation:operation-id")
+    private String operationId;
+
+    @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:target-id")
+    private String targetId;
+
+    @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:vf-count")
+    private Integer vfCount;
+
+    @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:min")
+    private Integer min;
+
+    @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:target:max")
+    private Integer max;
+
+    @XACMLResource(includeInResults = true, attributeId = "urn:org:onap:guard:operation:operation-count")
+    private Integer operationCount;
+
+    public LegacyGuardPolicyRequest() {
+        super();
+    }
+
+    /**
+     * Parses the DecisionRequest into a StdMetadataPolicyRequest.
+     *
+     * @param decisionRequest Input DecisionRequest
+     * @return StdMetadataPolicyRequest
+     */
+    @SuppressWarnings("unchecked")
+    public static LegacyGuardPolicyRequest createInstance(DecisionRequest decisionRequest) {
+        //
+        // Create our return object
+        //
+        LegacyGuardPolicyRequest request = new LegacyGuardPolicyRequest();
+        //
+        // Add the subject attributes
+        //
+        request.onapName = decisionRequest.getOnapName();
+        request.onapComponent = decisionRequest.getOnapComponent();
+        request.onapInstance = decisionRequest.getOnapInstance();
+        request.requestId = decisionRequest.getRequestId();
+        //
+        // Now pull from the resources
+        //
+        Map<String, Object> resources = decisionRequest.getResource();
+        //
+        // Just in case nothing is in there
+        //
+        if (resources == null || resources.isEmpty() || ! resources.containsKey(STR_GUARD)) {
+            //
+            // Perhaps we throw an exception and then caller
+            // can put together a response
+            //
+            return request;
+        }
+        Map<String, Object> guard = (Map<String, Object>) resources.get(STR_GUARD);
+        if (guard == null || guard.isEmpty()) {
+            //
+            // again, same problem throw an exception?
+            //
+            return request;
+        }
+        //
+        // Find our fields
+        //
+        if (guard.containsKey("actor")) {
+            request.actorId = guard.get("actor").toString();
+        }
+        if (guard.containsKey("recipe")) {
+            request.operationId = guard.get("recipe").toString();
+        }
+        if (guard.containsKey("clname")) {
+            request.clnameId = guard.get("clname").toString();
+        }
+        if (guard.containsKey("targets")) {
+            request.targetId = guard.get("targets").toString();
+        }
+        if (guard.containsKey("vfCount")) {
+            request.vfCount = Integer.decode(guard.get("vfCount").toString());
+        }
+        if (guard.containsKey("min")) {
+            request.min = Integer.decode(guard.get("min").toString());
+        }
+        if (guard.containsKey("max")) {
+            request.max = Integer.decode(guard.get("max").toString());
+        }
+        //
+        // TODO - remove this when the PIP is hooked up
+        //
+        if (guard.containsKey("operationCount")) {
+            request.operationCount = Integer.decode(guard.get("operationCount").toString());
+        }
+
+        return request;
+    }
+
+}
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
new file mode 100644 (file)
index 0000000..81340b4
--- /dev/null
@@ -0,0 +1,740 @@
+/*-
+ * ============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.DataTypeException;
+import com.att.research.xacml.api.Decision;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.Request;
+import com.att.research.xacml.api.Response;
+import com.att.research.xacml.api.Result;
+import com.att.research.xacml.api.XACML3;
+import com.att.research.xacml.std.annotations.RequestParser;
+import com.att.research.xacml.util.XACMLPolicyWriter;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionsType;
+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.ApplyType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
+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 oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
+
+import org.onap.policy.models.decisions.concepts.DecisionRequest;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LegacyGuardTranslator implements ToscaPolicyTranslator {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(LegacyGuardTranslator.class);
+
+    private static final String FIELD_POLICIES = "policies";
+    private static final String FIELD_TOPOLOGY_TEMPLATE = "topology_template";
+    private static final String FIELD_GUARD_ACTIVE_START = "guardActiveStart";
+    private static final String FIELD_GUARD_ACTIVE_END = "guardActiveEnd";
+
+    public LegacyGuardTranslator() {
+        super();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<PolicyType> scanAndConvertPolicies(Map<String, Object> toscaObject)
+            throws ToscaPolicyConversionException {
+        //
+        // Our return object
+        //
+        List<PolicyType> scannedPolicies = new ArrayList<>();
+        //
+        // Find the Policies
+        //
+        List<Object> policies;
+
+        if (toscaObject.containsKey(FIELD_POLICIES)) {
+            policies = (List<Object>) toscaObject.get(FIELD_POLICIES);
+        } else if (toscaObject.containsKey(FIELD_TOPOLOGY_TEMPLATE)) {
+            Map<String, Object> topologyTemplate = (Map<String, Object>) toscaObject.get(FIELD_TOPOLOGY_TEMPLATE);
+            if (topologyTemplate.containsKey(FIELD_POLICIES)) {
+                policies = (List<Object>) topologyTemplate.get(FIELD_POLICIES);
+            } else {
+                LOGGER.warn("topologyTemplate does not contain policies");
+                return scannedPolicies;
+            }
+        } else {
+            LOGGER.warn("Failed to find policies or topologyTemplate");
+            return scannedPolicies;
+        }
+        //
+        // Iterate each of the Policies
+        //
+        for (Object policyObject : policies) {
+            //
+            // Get the contents
+            //
+            LOGGER.debug("Found policy {}", policyObject.getClass());
+            Map<String, Object> policyContents = (Map<String, Object>) policyObject;
+            for (Entry<String, Object> entrySet : policyContents.entrySet()) {
+                LOGGER.debug("Entry set {}", entrySet);
+                //
+                // Convert this policy
+                //
+                PolicyType policy = this.convertPolicy(entrySet);
+                if (policy == null) {
+                    //
+                    // Somehow there wasn't enough information to create
+                    // a policy
+                    //
+                    LOGGER.debug("Failed to convert policy");
+                    continue;
+                }
+                //
+                // Debug dump this
+                //
+                try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
+                    XACMLPolicyWriter.writePolicyFile(os, policy);
+                    LOGGER.debug("{}", os);
+                } catch (IOException e) {
+                    LOGGER.error("Failed to convert {}", e);
+                }
+                //
+                // Convert and add in the new policy
+                //
+                scannedPolicies.add(policy);
+            }
+        }
+
+        return scannedPolicies;
+    }
+
+    @Override
+    public Request convertRequest(DecisionRequest request) {
+        LOGGER.debug("Converting Request {}", request);
+        try {
+            return RequestParser.parseRequest(LegacyGuardPolicyRequest.createInstance(request));
+        } catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) {
+            LOGGER.error("Failed to convert DecisionRequest: {}", e);
+        }
+        //
+        // TODO throw exception
+        //
+        return null;
+    }
+
+
+    @Override
+    public DecisionResponse convertResponse(Response xacmlResponse) {
+        LOGGER.debug("Converting Response {}", xacmlResponse);
+        DecisionResponse decisionResponse = new DecisionResponse();
+        //
+        // Iterate through all the results
+        //
+        for (Result xacmlResult : xacmlResponse.getResults()) {
+            //
+            // Check the result
+            //
+            if (xacmlResult.getDecision() == Decision.PERMIT) {
+                //
+                // Just simply return a Permit response
+                //
+                decisionResponse.setStatus(Decision.PERMIT.toString());
+            }
+            if (xacmlResult.getDecision() == Decision.DENY) {
+                //
+                // Just simply return a Deny response
+                //
+                decisionResponse.setStatus(Decision.DENY.toString());
+            }
+            if (xacmlResult.getDecision() == Decision.NOTAPPLICABLE) {
+                //
+                // There is no guard policy, so we return a permit
+                //
+                decisionResponse.setStatus(Decision.PERMIT.toString());
+            }
+        }
+
+        return decisionResponse;
+    }
+
+    @SuppressWarnings("unchecked")
+    private PolicyType convertPolicy(Entry<String, Object> entrySet) throws ToscaPolicyConversionException {
+        //
+        // Policy name should be at the root
+        //
+        String policyName = entrySet.getKey();
+        Map<String, Object> policyDefinition = (Map<String, Object>) entrySet.getValue();
+        //
+        // Set it as the policy ID
+        //
+        PolicyType newPolicyType = new PolicyType();
+        newPolicyType.setPolicyId(policyName);
+        //
+        // Optional description
+        //
+        if (policyDefinition.containsKey("description")) {
+            newPolicyType.setDescription(policyDefinition.get("description").toString());
+        }
+        //
+        // There should be a metadata section
+        //
+        if (! policyDefinition.containsKey("metadata")) {
+            throw new ToscaPolicyConversionException(policyName + " missing metadata section");
+        }
+        this.fillMetadataSection(newPolicyType,
+                (Map<String, Object>) policyDefinition.get("metadata"));
+        //
+        // Set the combining rule
+        //
+        newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue());
+        //
+        // Generate the TargetType
+        //
+        if (! policyDefinition.containsKey("properties")) {
+            throw new ToscaPolicyConversionException(policyName + " missing properties section");
+        }
+        newPolicyType.setTarget(this.generateTargetType((Map<String, Object>) policyDefinition.get("properties")));
+        //
+        // Now create the Permit Rule
+        //
+        RuleType rule = generatePermitRule(policyName, policyDefinition.get("type").toString(),
+                (Map<String, Object>) policyDefinition.get("properties"));
+        //
+        // Check if we were able to create the rule
+        //
+        if (rule == null) {
+            LOGGER.warn("Failed to create rule");
+            return null;
+        }
+        //
+        // Add the rule to the policy
+        //
+        newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(rule);
+        //
+        // Return our new policy
+        //
+        return newPolicyType;
+    }
+
+    /**
+     * From the TOSCA metadata section, pull in values that are needed into the XACML policy.
+     *
+     * @param policy Policy Object to store the metadata
+     * @param metadata The Metadata TOSCA Map
+     * @return Same Policy Object
+     * @throws ToscaPolicyConversionException If there is something missing from the metadata
+     */
+    protected PolicyType fillMetadataSection(PolicyType policy,
+            Map<String, Object> metadata) throws ToscaPolicyConversionException {
+        if (! metadata.containsKey("policy-id")) {
+            throw new ToscaPolicyConversionException(policy.getPolicyId() + " missing metadata policy-id");
+        } else {
+            //
+            // Do nothing here - the XACML PolicyId is used from TOSCA Policy Name field
+            //
+        }
+        if (! metadata.containsKey("policy-version")) {
+            throw new ToscaPolicyConversionException(policy.getPolicyId() + " missing metadata policy-version");
+        } else {
+            //
+            // Add in the Policy Version
+            //
+            policy.setVersion(metadata.get("policy-version").toString());
+        }
+        return policy;
+    }
+
+    protected TargetType generateTargetType(Map<String, Object> properties) {
+        //
+        // Go through potential properties
+        //
+        AllOfType allOf = new AllOfType();
+        if (properties.containsKey("actor")) {
+            addMatch(allOf, properties.get("actor"), ToscaDictionary.ID_RESOURCE_GUARD_ACTOR);
+        }
+        if (properties.containsKey("recipe")) {
+            addMatch(allOf, properties.get("recipe"), ToscaDictionary.ID_RESOURCE_GUARD_RECIPE);
+        }
+        if (properties.containsKey("targets")) {
+            addMatch(allOf, properties.get("targets"), ToscaDictionary.ID_RESOURCE_GUARD_TARGETID);
+        }
+        if (properties.containsKey("clname")) {
+            addMatch(allOf, properties.get("clname"), ToscaDictionary.ID_RESOURCE_GUARD_CLNAME);
+        }
+        if (properties.containsKey("targets")) {
+            addMatch(allOf, properties.get("targets"), ToscaDictionary.ID_RESOURCE_GUARD_TARGETID);
+        }
+        //
+        // Create target
+        //
+        TargetType target = new TargetType();
+        AnyOfType anyOf = new AnyOfType();
+        anyOf.getAllOf().add(allOf);
+        target.getAnyOf().add(anyOf);
+        return target;
+    }
+
+    private static AllOfType addMatch(AllOfType allOf, Object value, Identifier attributeId) {
+        if (value instanceof String) {
+            if (".*".equals(value.toString())) {
+                //
+                // There's no point to even have a match
+                //
+                return allOf;
+            } else {
+                //
+                // Exact match
+                //
+                MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
+                    XACML3.ID_FUNCTION_STRING_EQUAL,
+                    value,
+                    XACML3.ID_DATATYPE_STRING,
+                    attributeId,
+                    XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
+
+                allOf.getMatch().add(match);
+            }
+            return allOf;
+        }
+        if (value instanceof Collection) {
+            //
+            // TODO support a collection of that attribute
+            //
+        }
+        return allOf;
+    }
+
+    private static RuleType generatePermitRule(String policyName, String policyType, Map<String, Object> properties) {
+        //
+        // Now determine which policy type we are generating
+        //
+        if ("onap.policies.controlloop.guard.FrequencyLimiter".equals(policyType)) {
+            return generateFrequencyPermit(policyName, properties);
+        } else if ("onap.policies.controlloop.guard.MinMax".equals(policyType)) {
+            return generateMinMaxPermit(policyName, properties);
+        }
+        return null;
+    }
+
+    private static RuleType generateFrequencyPermit(String policyName, Map<String, Object> properties) {
+        //
+        // See if its possible to generate a count
+        //
+        Integer limit = null;
+        if (properties.containsKey("limit")) {
+            limit = Integer.decode(properties.get("limit").toString());
+        }
+        if (limit == null) {
+            LOGGER.debug("Must have a limit value for frequency guard policy to be created");
+            return null;
+        }
+        //
+        // Get the properties that are common among guards
+        //
+        String timeWindow = null;
+        if (properties.containsKey("timeWindow")) {
+            timeWindow = properties.get("timeWindow").toString();
+        }
+        String timeUnits = null;
+        if (properties.containsKey("timeUnits")) {
+            timeUnits = properties.get("timeUnits").toString();
+        }
+        String guardActiveStart = null;
+        if (properties.containsKey(FIELD_GUARD_ACTIVE_START)) {
+            guardActiveStart = properties.get(FIELD_GUARD_ACTIVE_START).toString();
+        }
+        String guardActiveEnd = null;
+        if (properties.containsKey(FIELD_GUARD_ACTIVE_END)) {
+            guardActiveEnd = properties.get(FIELD_GUARD_ACTIVE_END).toString();
+        }
+        //
+        // Generate the time in range
+        //
+        final ApplyType timeRange = generateTimeInRange(guardActiveStart, guardActiveEnd);
+        //
+        // Generate a count
+        //
+        final ApplyType countCheck = generateCountCheck(limit, timeWindow, timeUnits);
+        //
+        // Now combine into an And
+        //
+        ApplyType applyAnd = new ApplyType();
+        applyAnd.setDescription("return true if all the apply's are true.");
+        applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue());
+        applyAnd.getExpression().add(new ObjectFactory().createApply(timeRange));
+        applyAnd.getExpression().add(new ObjectFactory().createApply(countCheck));
+        //
+        // And create an outer negation of the And
+        //
+        ApplyType applyNot = new ApplyType();
+        applyNot.setDescription("Negate the and");
+        applyNot.setFunctionId(XACML3.ID_FUNCTION_NOT.stringValue());
+        applyNot.getExpression().add(new ObjectFactory().createApply(applyAnd));
+
+        //
+        // Create our condition
+        //
+        final ConditionType condition = new ConditionType();
+        condition.setExpression(new ObjectFactory().createApply(applyNot));
+
+        //
+        // Now we can create our rule
+        //
+        RuleType permit = new RuleType();
+        permit.setDescription("Default is to PERMIT if the policy matches.");
+        permit.setRuleId(policyName + ":rule");
+        permit.setEffect(EffectType.PERMIT);
+        permit.setTarget(new TargetType());
+        //
+        // Add the condition
+        //
+        permit.setCondition(condition);
+        //
+        // TODO Add the advice - Is the request id needed to be returned?
+        //
+        // permit.setAdviceExpressions(adviceExpressions);
+        //
+        // Done
+        //
+        return permit;
+    }
+
+    private static RuleType generateMinMaxPermit(String policyName, Map<String, Object> properties) {
+        //
+        // Get the properties that are common among guards
+        //
+        String guardActiveStart = null;
+        if (properties.containsKey(FIELD_GUARD_ACTIVE_START)) {
+            guardActiveStart = properties.get(FIELD_GUARD_ACTIVE_START).toString();
+        }
+        String guardActiveEnd = null;
+        if (properties.containsKey(FIELD_GUARD_ACTIVE_END)) {
+            guardActiveEnd = properties.get(FIELD_GUARD_ACTIVE_END).toString();
+        }
+        //
+        // Generate the time in range
+        //
+        final ApplyType timeRange = generateTimeInRange(guardActiveStart, guardActiveEnd);
+        //
+        // See if its possible to generate a count
+        //
+        Integer min = null;
+        if (properties.containsKey("min")) {
+            min = Integer.decode(properties.get("min").toString());
+        }
+        Integer max = null;
+        if (properties.containsKey("max")) {
+            max = Integer.decode(properties.get("max").toString());
+        }
+        final ApplyType minApply = generateMinCheck(min);
+        final ApplyType maxApply = generateMaxCheck(max);
+        //
+        // Make sure we have at least something to check here,
+        // otherwise there really is no point to this policy.
+        //
+        if (timeRange == null && minApply == null && maxApply == null) {
+            return null;
+        }
+        //
+        // Create our rule
+        //
+        RuleType permit = new RuleType();
+        permit.setDescription("Default is to PERMIT if the policy matches.");
+        permit.setRuleId(policyName + ":rule");
+        permit.setEffect(EffectType.PERMIT);
+        permit.setTarget(new TargetType());
+        //
+        // Create our condition
+        //
+        final ConditionType condition = new ConditionType();
+        //
+        // Check if we have all the fields (this can be a little
+        // ugly) but the ultimate goal is to simplify the policy
+        // condition to only check for necessary attributes.
+        //
+        ObjectFactory factory = new ObjectFactory();
+        if (timeRange != null && minApply != null && maxApply != null) {
+            //
+            // All 3 must apply
+            //
+            ApplyType applyAnd = new ApplyType();
+            applyAnd.setDescription("return true if all the apply's are true.");
+            applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue());
+            applyAnd.getExpression().add(factory.createApply(timeRange));
+            applyAnd.getExpression().add(factory.createApply(minApply));
+            applyAnd.getExpression().add(factory.createApply(maxApply));
+            //
+            // Add into the condition
+            //
+            condition.setExpression(factory.createApply(applyAnd));
+        } else {
+            //
+            // At least one of these applies is null. We need at least
+            // two to require the And apply. Otherwise there is no need
+            // for an outer And apply as the single condition can work
+            // on its own.
+            //
+            if (timeRange != null && minApply == null && maxApply == null) {
+                //
+                // Only the time range check is necessary
+                //
+                condition.setExpression(factory.createApply(timeRange));
+            } else if (timeRange == null && minApply != null && maxApply == null) {
+                //
+                // Only the min check is necessary
+                //
+                condition.setExpression(factory.createApply(minApply));
+            } else if (timeRange == null && minApply == null) {
+                //
+                // Only the max check is necessary
+                //
+                condition.setExpression(factory.createApply(maxApply));
+            } else {
+                //
+                // Ok we will need an outer And and have at least the
+                // time range and either min or max check
+                //
+                ApplyType applyAnd = new ApplyType();
+                applyAnd.setDescription("return true if all the apply's are true.");
+                applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue());
+                if (timeRange != null) {
+                    applyAnd.getExpression().add(factory.createApply(timeRange));
+                }
+                if (minApply != null) {
+                    applyAnd.getExpression().add(factory.createApply(minApply));
+                }
+                if (maxApply != null) {
+                    applyAnd.getExpression().add(factory.createApply(maxApply));
+                }
+                //
+                // Add into the condition
+                //
+                condition.setExpression(factory.createApply(applyAnd));
+            }
+        }
+        //
+        // Add the condition
+        //
+        permit.setCondition(condition);
+        //
+        // TODO Add the advice - Is the request id needed to be returned?
+        //
+        // permit.setAdviceExpressions(adviceExpressions);
+        //
+        // Done
+        //
+        return permit;
+    }
+
+    private static ApplyType generateTimeInRange(String start, String end) {
+        if (start == null || end == null) {
+            LOGGER.warn("Missing time range start {} end {}", start, end);
+            return null;
+        }
+        if (start.isEmpty() || end.isEmpty()) {
+            LOGGER.warn("Empty time range start {} end {}", start, end);
+            return null;
+        }
+
+        AttributeDesignatorType designator = new AttributeDesignatorType();
+        designator.setAttributeId(XACML3.ID_ENVIRONMENT_CURRENT_TIME.stringValue());
+        designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT.stringValue());
+        designator.setDataType(XACML3.ID_DATATYPE_TIME.stringValue());
+
+        AttributeValueType valueStart = new AttributeValueType();
+        valueStart.setDataType(XACML3.ID_DATATYPE_TIME.stringValue());
+        valueStart.getContent().add(start);
+
+        AttributeValueType valueEnd = new AttributeValueType();
+        valueEnd.setDataType(XACML3.ID_DATATYPE_TIME.stringValue());
+        valueEnd.getContent().add(end);
+
+        ObjectFactory factory = new ObjectFactory();
+
+        ApplyType applyOneAndOnly = new ApplyType();
+        applyOneAndOnly.setDescription("Unbag the current time");
+        applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_TIME_ONE_AND_ONLY.stringValue());
+        applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
+
+        ApplyType applyTimeInRange = new ApplyType();
+        applyTimeInRange.setDescription("return true if current time is in range.");
+        applyTimeInRange.setFunctionId(XACML3.ID_FUNCTION_TIME_IN_RANGE.stringValue());
+        applyTimeInRange.getExpression().add(factory.createApply(applyOneAndOnly));
+        applyTimeInRange.getExpression().add(factory.createAttributeValue(valueStart));
+        applyTimeInRange.getExpression().add(factory.createAttributeValue(valueEnd));
+
+        return applyTimeInRange;
+    }
+
+    private static ApplyType generateCountCheck(Integer limit, String timeWindow, String timeUnits) {
+        AttributeDesignatorType designator = new AttributeDesignatorType();
+        designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_OPERATIONCOUNT.stringValue());
+        designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
+        designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
+        //
+        // TODO Add this back in when the operational database PIP is configured.
+        // The issuer indicates that the PIP will be providing this attribute during
+        // the decision making.
+        //
+        // Right now I am faking the count value by re-using the request-id field
+        //
+        //String issuer = "org:onap:xacml:guard:historydb:tw:" + timeWindow + ":" + timeUnits;
+        //designator.setIssuer(issuer);
+
+        AttributeValueType valueLimit = new AttributeValueType();
+        valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
+        //
+        // Yes really use toString(), the marshaller will
+        // throw an exception if this is an integer object
+        // and not a string.
+        //
+        valueLimit.getContent().add(limit.toString());
+
+        ObjectFactory factory = new ObjectFactory();
+
+        ApplyType applyOneAndOnly = new ApplyType();
+        applyOneAndOnly.setDescription("Unbag the limit");
+        applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue());
+        applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
+
+        ApplyType applyGreaterThanEqual = new ApplyType();
+        applyGreaterThanEqual.setDescription("return true if current count is greater than or equal.");
+        applyGreaterThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_GREATER_THAN_OR_EQUAL.stringValue());
+        applyGreaterThanEqual.getExpression().add(factory.createApply(applyOneAndOnly));
+        applyGreaterThanEqual.getExpression().add(factory.createAttributeValue(valueLimit));
+
+        return applyGreaterThanEqual;
+    }
+
+    private static ApplyType generateMinCheck(Integer min) {
+        if (min == null) {
+            return null;
+        }
+        AttributeDesignatorType designator = new AttributeDesignatorType();
+        designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.stringValue());
+        designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
+        designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
+        //
+        //
+        //
+        AttributeValueType valueLimit = new AttributeValueType();
+        valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
+        //
+        // Yes really use toString(), the marshaller will
+        // throw an exception if this is an integer object
+        // and not a string.
+        //
+        valueLimit.getContent().add(min.toString());
+        ObjectFactory factory = new ObjectFactory();
+
+        ApplyType applyOneAndOnly = new ApplyType();
+        applyOneAndOnly.setDescription("Unbag the min");
+        applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue());
+        applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
+
+        ApplyType applyGreaterThanEqual = new ApplyType();
+        applyGreaterThanEqual.setDescription("return true if current count is greater than or equal.");
+        applyGreaterThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_GREATER_THAN_OR_EQUAL.stringValue());
+        applyGreaterThanEqual.getExpression().add(factory.createApply(applyOneAndOnly));
+        applyGreaterThanEqual.getExpression().add(factory.createAttributeValue(valueLimit));
+
+        return applyGreaterThanEqual;
+    }
+
+    private static ApplyType generateMaxCheck(Integer max) {
+        if (max == null) {
+            return null;
+        }
+        AttributeDesignatorType designator = new AttributeDesignatorType();
+        designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.stringValue());
+        designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
+        designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
+        //
+        //
+        //
+        AttributeValueType valueLimit = new AttributeValueType();
+        valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
+        //
+        // Yes really use toString(), the marshaller will
+        // throw an exception if this is an integer object
+        // and not a string.
+        //
+        valueLimit.getContent().add(max.toString());
+        ObjectFactory factory = new ObjectFactory();
+
+        ApplyType applyOneAndOnly = new ApplyType();
+        applyOneAndOnly.setDescription("Unbag the min");
+        applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue());
+        applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
+
+        ApplyType applyGreaterThanEqual = new ApplyType();
+        applyGreaterThanEqual.setDescription("return true if current count is less than or equal.");
+        applyGreaterThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN_OR_EQUAL.stringValue());
+        applyGreaterThanEqual.getExpression().add(factory.createApply(applyOneAndOnly));
+        applyGreaterThanEqual.getExpression().add(factory.createAttributeValue(valueLimit));
+
+        return applyGreaterThanEqual;
+    }
+
+    private static AdviceExpressionsType generateRequestIdAdvice() {
+        AdviceExpressionType adviceExpression = new AdviceExpressionType();
+        adviceExpression.setAppliesTo(EffectType.PERMIT);
+        adviceExpression.setAdviceId(ToscaDictionary.ID_ADVICE_GUARD.stringValue());
+
+        AttributeDesignatorType designator = new AttributeDesignatorType();
+        designator.setAttributeId(ToscaDictionary.ID_SUBJECT_GUARD_REQUESTID.stringValue());
+        designator.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue());
+        designator.setDataType(XACML3.ID_DATATYPE_STRING.stringValue());
+
+        AttributeAssignmentExpressionType assignment = new AttributeAssignmentExpressionType();
+        assignment.setAttributeId(ToscaDictionary.ID_ADVICE_GUARD_REQUESTID.stringValue());
+        assignment.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue());
+        assignment.setExpression(new ObjectFactory().createAttributeDesignator(designator));
+
+        adviceExpression.getAttributeAssignmentExpression().add(assignment);
+
+        AdviceExpressionsType adviceExpressions = new AdviceExpressionsType();
+        adviceExpressions.getAdviceExpression().add(adviceExpression);
+
+        return adviceExpressions;
+    }
+}
index ae4193d..ff137e1 100644 (file)
 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.util.XACMLProperties;
-import com.google.common.io.Files;
-import com.google.gson.Gson;
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Properties;
 import java.util.ServiceLoader;
+import java.util.UUID;
 
-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.serialization.DecisionRequestMessageBodyHandler;
-import org.onap.policy.models.decisions.serialization.DecisionResponseMessageBodyHandler;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
+import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.yaml.snakeyaml.Yaml;
 
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class GuardPdpApplicationTest {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(GuardPdpApplicationTest.class);
     private static Properties properties = new Properties();
     private static File propertiesFile;
     private static XacmlApplicationServiceProvider service;
-    private static DecisionRequest requestSinglePolicy;
-
-    private static Gson gsonDecisionRequest;
-    private static Gson gsonDecisionResponse;
+    private static DecisionRequest requestGuardPermit;
+    private static DecisionRequest requestGuardDeny;
+    private static DecisionRequest requestGuardDeny2;
+    private static StandardCoder gson = new StandardCoder();
 
     @ClassRule
     public static final TemporaryFolder policyFolder = new TemporaryFolder();
 
-    @Before
-    public void setUp() throws Exception {
+    /**
+     * 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 {
+        //
+        // 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<XacmlApplicationServiceProvider> 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<XacmlApplicationServiceProvider> 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.debug("{}", strDump);
+        //
+        // Tell it to initialize based on the properties file
+        // we just built for it.
+        //
+        service.initialize(propertiesFile.toPath().getParent());
+    }
 
+    @Test
+    public void test1Basics() throws CoderException, IOException {
+        //
+        // Load Single Decision Request
+        //
+        requestGuardPermit = gson.decode(
+                TextFileUtils.getTextFileAsString(
+                    "../../main/src/test/resources/decisions/decision.guard.shouldpermit.input.json"),
+                    DecisionRequest.class);
+        //
+        // Load Single Decision Request
+        //
+        requestGuardDeny = gson.decode(TextFileUtils.getTextFileAsString(
+                "../../main/src/test/resources/decisions/decision.guard.shoulddeny.input.json"),
+                DecisionRequest.class);
+        //
+        // Load Single Decision Request
+        //
+        requestGuardDeny2 = gson.decode(TextFileUtils.getTextFileAsString(
+                "../../main/src/test/resources/decisions/decision.guard.shoulddeny.input2.json"),
+                DecisionRequest.class);
+        //
+        // Make sure there's an application name
+        //
+        assertThat(service.applicationName()).isNotEmpty();
+        //
+        // Decisions
+        //
+        assertThat(service.actionDecisionsSupported().size()).isEqualTo(1);
+        assertThat(service.actionDecisionsSupported()).contains("guard");
+        //
+        // Ensure it has the supported policy types and
+        // can support the correct policy types.
+        //
+        assertThat(service.supportedPolicyTypes()).isNotEmpty();
+        assertThat(service.supportedPolicyTypes().size()).isEqualTo(2);
+        assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.FrequencyLimiter", "1.0.0"))
+            .isTrue();
+        assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.FrequencyLimiter", "1.0.1"))
+            .isFalse();
+        assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.MinMax", "1.0.0")).isTrue();
+        assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.MinMax", "1.0.1")).isFalse();
+        assertThat(service.canSupportPolicyType("onap.foo", "1.0.1")).isFalse();
     }
 
     @Test
-    public void testBasics() {
-        assertThatCode(() -> {
+    public void test2NoPolicies() {
+        //
+        // Ask for a decision
+        //
+        DecisionResponse response = service.makeDecision(requestGuardPermit);
+        LOGGER.info("Decision {}", response);
+
+        assertThat(response).isNotNull();
+        assertThat(response.getStatus()).isEqualTo("Permit");
+    }
+
+    @Test
+    public void test3FrequencyLimiter() throws CoderException, FileNotFoundException, IOException {
+        //
+        // Now load the vDNS frequency limiter Policy - make sure
+        // the pdp can support it and have it load
+        // into the PDP.
+        //
+        try (InputStream is = new FileInputStream("src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml")) {
             //
-            // Create our Gson builder
+            // Have yaml parse it
             //
-            gsonDecisionRequest = new DecisionRequestMessageBodyHandler().getGson();
-            gsonDecisionResponse = new DecisionResponseMessageBodyHandler().getGson();
+            Yaml yaml = new Yaml();
+            Map<String, Object> toscaObject = yaml.load(is);
             //
-            // Load Single Decision Request
+            // Load the policies
             //
-            requestSinglePolicy = gsonDecisionRequest.fromJson(
-                    TextFileUtils
-                        .getTextFileAsString("../../main/src/test/resources/decisions/decision.single.input.json"),
-                        DecisionRequest.class);
+            service.loadPolicies(toscaObject);
             //
-            // Copy all the properties and root policies to the temporary folder
+            // Ask for a decision - should get permit
             //
-            try (InputStream is = new FileInputStream("src/test/resources/xacml.properties")) {
-                //
-                // Load it in
-                //
-                properties.load(is);
-                propertiesFile = policyFolder.newFile("xacml.properties");
-                //
-                // Copy the root policies
-                //
-                for (String root : XACMLProperties.getRootPolicyIDs(properties)) {
-                    //
-                    // Get a file
-                    //
-                    Path rootPath = Paths.get(properties.getProperty(root + ".file"));
-                    LOGGER.debug("Root file {} {}", rootPath, rootPath.getFileName());
-                    //
-                    // Construct new file name
-                    //
-                    File newRootPath = policyFolder.newFile(rootPath.getFileName().toString());
-                    //
-                    // Copy it
-                    //
-                    Files.copy(rootPath.toFile(), newRootPath);
-                    assertThat(newRootPath).exists();
-                    //
-                    // Point to where the new policy is in the temp dir
-                    //
-                    properties.setProperty(root + ".file", newRootPath.getAbsolutePath());
-                }
-                try (OutputStream os = new FileOutputStream(propertiesFile.getAbsolutePath())) {
-                    properties.store(os, "");
-                    assertThat(propertiesFile).exists();
-                }
-            }
+            DecisionResponse response = service.makeDecision(requestGuardPermit);
+            LOGGER.info("Looking for Permit Decision {}", response);
+
+            assertThat(response).isNotNull();
+            assertThat(response.getStatus()).isNotNull();
+            assertThat(response.getStatus()).isEqualTo("Permit");
             //
-            // Load service
+            // Dump it out as Json
             //
-            ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
-                    ServiceLoader.load(XacmlApplicationServiceProvider.class);
+            LOGGER.info(gson.encode(response));
             //
-            // Iterate through them - I could store the object as
-            // XacmlApplicationServiceProvider pointer.
+            // Ask for a decision - should get deny
             //
-            // Try this later.
+            response = service.makeDecision(requestGuardDeny2);
+            LOGGER.info("Looking for Deny Decision {}", response);
+            assertThat(response).isNotNull();
+            assertThat(response.getStatus()).isNotNull();
+            assertThat(response.getStatus()).isEqualTo("Deny");
             //
-            StringBuilder strDump = new StringBuilder("Loaded applications:" + System.lineSeparator());
-            Iterator<XacmlApplicationServiceProvider> 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.debug("{}", strDump);
+            // Dump it out as Json
+            //
+            LOGGER.info(gson.encode(response));
+        }
+    }
+
+    @Test
+    public void test4MinMax() throws CoderException, FileNotFoundException, IOException {
+        //
+        // Now load the vDNS min max Policy - make sure
+        // the pdp can support it and have it load
+        // into the PDP.
+        //
+        try (InputStream is = new FileInputStream("src/test/resources/vDNS.policy.guard.minmax.output.tosca.yaml")) {
+            //
+            // Have yaml parse it
+            //
+            Yaml yaml = new Yaml();
+            Map<String, Object> toscaObject = yaml.load(is);
+            //
+            // Load the policies
+            //
+            service.loadPolicies(toscaObject);
+            //
+            // Ask for a decision - should get permit
+            //
+            DecisionResponse response = service.makeDecision(requestGuardPermit);
+            LOGGER.info("Looking for Permit Decision {}", response);
+
+            assertThat(response).isNotNull();
+            assertThat(response.getStatus()).isNotNull();
+            assertThat(response.getStatus()).isEqualTo("Permit");
+            //
+            // Dump it out as Json
+            //
+            LOGGER.info(gson.encode(response));
+            //
+            // Ask for a decision - should get deny
+            //
+            response = service.makeDecision(requestGuardDeny);
+            LOGGER.info("Looking for Deny Decision {}", response);
+            assertThat(response).isNotNull();
+            assertThat(response.getStatus()).isNotNull();
+            assertThat(response.getStatus()).isEqualTo("Deny");
+            //
+            // Dump it out as Json
+            //
+            LOGGER.info(gson.encode(response));
+        }
+    }
+
+    @Test
+    public void test5MissingFields() throws FileNotFoundException, IOException {
+        LOGGER.debug("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.
+        //
+        try (InputStream is = new FileInputStream("src/test/resources/guard.policy-minmax-missing-fields1.yaml")) {
             //
-            // Tell it to initialize based on the properties file
-            // we just built for it.
+            // Have yaml parse it
             //
-            service.initialize(propertiesFile.toPath().getParent());
+            Yaml yaml = new Yaml();
+            Map<String, Object> toscaObject = yaml.load(is);
             //
-            // Make sure there's an application name
+            // Load the policies
             //
-            assertThat(service.applicationName()).isNotEmpty();
+            service.loadPolicies(toscaObject);
             //
-            // Decisions
+            // We can create a DecisionRequest on the fly - no need
+            // to have it in the .json files
             //
-            assertThat(service.actionDecisionsSupported().size()).isEqualTo(1);
-            assertThat(service.actionDecisionsSupported()).contains("guard");
+            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);
             //
-            // Ensure it has the supported policy types and
-            // can support the correct policy types.
+            // Ask for a decision - should get permit
             //
-            assertThat(service.supportedPolicyTypes()).isNotEmpty();
-            assertThat(service.supportedPolicyTypes().size()).isEqualTo(2);
-            assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.FrequencyLimiter", "1.0.0"))
-                .isTrue();
-            assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.FrequencyLimiter", "1.0.1"))
-                .isFalse();
-            assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.MinMax", "1.0.0")).isTrue();
-            assertThat(service.canSupportPolicyType("onap.policies.controlloop.guard.MinMax", "1.0.1")).isFalse();
-            assertThat(service.canSupportPolicyType("onap.foo", "1.0.1")).isFalse();
+            DecisionResponse response = service.makeDecision(request);
+            LOGGER.info("Looking for Permit Decision {}", response);
+            assertThat(response).isNotNull();
+            assertThat(response.getStatus()).isNotNull();
+            assertThat(response.getStatus()).isEqualTo("Permit");
             //
-            // Ensure it supports decisions
+            // Try a deny
             //
-            assertThat(service.actionDecisionsSupported()).contains("guard");
-        }).doesNotThrowAnyException();
+            guard.put("vfCount", "10");
+            resource.put("guard", guard);
+            request.setResource(resource);
+            response = service.makeDecision(request);
+            LOGGER.info("Looking for Deny Decision {}", response);
+            assertThat(response).isNotNull();
+            assertThat(response.getStatus()).isNotNull();
+            assertThat(response.getStatus()).isEqualTo("Deny");
+        }
     }
 }
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
new file mode 100644 (file)
index 0000000..6a44118
--- /dev/null
@@ -0,0 +1,19 @@
+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/vDNS.policy.guard.frequency.output.tosca.yaml b/applications/guard/src/test/resources/vDNS.policy.guard.frequency.output.tosca.yaml
new file mode 100644 (file)
index 0000000..03afd5e
--- /dev/null
@@ -0,0 +1,20 @@
+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: scaleOut
+          targets: .*
+          clname: ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3
+          limit: 1
+          timeWindow: 10
+          timeUnits: minute
+          guardActiveStart: 00:00:01-05:00
+          guardActiveEnd: 23:59:59-05:00
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
new file mode 100644 (file)
index 0000000..5ac7601
--- /dev/null
@@ -0,0 +1,19 @@
+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: scaleOut
+          targets: .*
+          clname: ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3
+          min: 1
+          max: 5
+          guardActiveStart: 00:00:01-05:00
+          guardActiveEnd: 23:59:59-05:00
index b32a936..9bd7bfb 100644 (file)
@@ -20,18 +20,13 @@ xacml.att.functionDefinitionFactory=com.att.research.xacmlatt.pdp.std.StdFunctio
 xacml.att.policyFinderFactory=org.onap.policy.pdp.xacml.application.common.OnapPolicyFinderFactory
 
 #
-# ONAP Implementation Factories
+# Use a root combining algorithm
 #
-#xacml.att.policyFinderFactory=org.onap.policy.pdp.xacml.application.common.OnapApplicationPolicyFinder
+xacml.att.policyFinderFactory.combineRootPolicies=urn:oasis:names:tc:xacml:3.0:policy-combining-algorithm:permit-unless-deny
 
-#
-# NOTE: If you are testing against a RESTful PDP, then the PDP must be configured with the
-# policies and PIP configuration as defined below. Otherwise, this is the configuration that
-# the embedded PDP uses.
-#
 
 # Policies to load
 #
-xacml.rootPolicies=guard
-guard.file=src/main/resources/RootGuardPolicy.xml
+#xacml.rootPolicies=guard
+#guard.file=src/main/resources/RootGuardPolicy.xml
 
index 018c372..d477bee 100644 (file)
     <description>This modules contains applications that implement policy-types for XACML PDP.</description>
 
     <dependencies>
-        <dependency>
-            <groupId>com.google.code.gson</groupId>
-            <artifactId>gson</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.onap.policy.common</groupId>
-            <artifactId>common-parameters</artifactId>
-            <version>${policy.common.version}</version>
-        </dependency>
         <dependency>
             <groupId>org.onap.policy.xacml-pdp.applications</groupId>
             <artifactId>common</artifactId>
diff --git a/applications/monitoring/src/main/java/org/onap/policy/xacml/pdp/application/monitoring/MonitoringRequest.java b/applications/monitoring/src/main/java/org/onap/policy/xacml/pdp/application/monitoring/MonitoringRequest.java
deleted file mode 100644 (file)
index ce0bd3f..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP Policy Decision Models
- * ================================================================================
- * 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.monitoring;
-
-import com.att.research.xacml.std.annotations.XACMLAction;
-import com.att.research.xacml.std.annotations.XACMLRequest;
-import com.att.research.xacml.std.annotations.XACMLResource;
-import com.att.research.xacml.std.annotations.XACMLSubject;
-
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.onap.policy.models.decisions.concepts.DecisionRequest;
-
-@XACMLRequest(ReturnPolicyIdList = true)
-public class MonitoringRequest {
-
-    @XACMLSubject(includeInResults = true)
-    String onapName = "DCAE";
-
-    @XACMLResource(includeInResults = true)
-    String resource = "onap.policies.Monitoring";
-
-    @XACMLAction()
-    String action = "configure";
-
-
-    /**
-     * Parses the DecisionRequest into a MonitoringRequest.
-     *
-     * @param decisionRequest Input DecisionRequest
-     * @return MonitoringRequest
-     */
-    public static MonitoringRequest createInstance(DecisionRequest decisionRequest) {
-        MonitoringRequest request = new MonitoringRequest();
-        request.onapName = decisionRequest.getOnapName();
-        request.action = decisionRequest.getAction();
-
-        Map<String, Object> resources = decisionRequest.getResource();
-        for (Entry<String, Object> entry : resources.entrySet()) {
-            if ("policy-id".equals(entry.getKey())) {
-                //
-                // TODO handle lists of policies
-                //
-                request.resource = entry.getValue().toString();
-                continue;
-            }
-            if ("policy-type".equals(entry.getKey())) {
-                //
-                // TODO handle lists of policies
-                //
-                request.resource = entry.getValue().toString();
-            }
-        }
-        //
-        // TODO handle a bad incoming request. Do that here?
-        //
-        return request;
-    }
-}
index d3624a6..4af4bac 100644 (file)
 package org.onap.policy.xacml.pdp.application.monitoring;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatCode;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-
-import com.att.research.xacml.util.XACMLProperties;
-import com.google.common.io.Files;
-import com.google.gson.Gson;
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -46,19 +37,22 @@ import java.util.ServiceLoader;
 
 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.models.decisions.serialization.DecisionRequestMessageBodyHandler;
-import org.onap.policy.models.decisions.serialization.DecisionResponseMessageBodyHandler;
-import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
+import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.yaml.snakeyaml.Yaml;
 
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class MonitoringPdpApplicationTest {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(MonitoringPdpApplicationTest.class);
@@ -67,210 +61,166 @@ public class MonitoringPdpApplicationTest {
     private static XacmlApplicationServiceProvider service;
     private static DecisionRequest requestSinglePolicy;
 
-    private static Gson gsonDecisionRequest;
-    private static Gson gsonDecisionResponse;
+    private static StandardCoder gson = new StandardCoder();
 
     @ClassRule
     public static final TemporaryFolder policyFolder = new TemporaryFolder();
 
     /**
-     * Load a test engine.
+     * 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() {
-        assertThatCode(() -> {
-            //
-            // Create our Gson builder
-            //
-            gsonDecisionRequest = new DecisionRequestMessageBodyHandler().getGson();
-            gsonDecisionResponse = new DecisionResponseMessageBodyHandler().getGson();
-            //
-            // Load Single Decision Request
-            //
-            requestSinglePolicy = gsonDecisionRequest.fromJson(
-                    TextFileUtils
-                        .getTextFileAsString("../../main/src/test/resources/decisions/decision.single.input.json"),
-                        DecisionRequest.class);
-            //
-            // Copy all the properties and root policies to the temporary folder
-            //
-            try (InputStream is = new FileInputStream("src/test/resources/xacml.properties")) {
-                //
-                // Load it in
-                //
-                properties.load(is);
-                propertiesFile = policyFolder.newFile("xacml.properties");
-                //
-                // Copy the root policies
-                //
-                for (String root : XACMLProperties.getRootPolicyIDs(properties)) {
-                    //
-                    // Get a file
-                    //
-                    Path rootPath = Paths.get(properties.getProperty(root + ".file"));
-                    LOGGER.debug("Root file {} {}", rootPath, rootPath.getFileName());
-                    //
-                    // Construct new file name
-                    //
-                    File newRootPath = policyFolder.newFile(rootPath.getFileName().toString());
-                    //
-                    // Copy it
-                    //
-                    Files.copy(rootPath.toFile(), newRootPath);
-                    assertThat(newRootPath).exists();
-                    //
-                    // Point to where the new policy is in the temp dir
-                    //
-                    properties.setProperty(root + ".file", newRootPath.getAbsolutePath());
-                }
-                try (OutputStream os = new FileOutputStream(propertiesFile.getAbsolutePath())) {
-                    properties.store(os, "");
-                    assertThat(propertiesFile).exists();
-                }
-            }
-            //
-            // Load service
-            //
-            ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
-                    ServiceLoader.load(XacmlApplicationServiceProvider.class);
-            //
-            // Iterate through them - I could store the object as
-            // XacmlApplicationServiceProvider pointer.
+    public static void setup() throws Exception {
+        //
+        // Load Single Decision Request
+        //
+        requestSinglePolicy = gson.decode(
+                TextFileUtils
+                    .getTextFileAsString("../../main/src/test/resources/decisions/decision.single.input.json"),
+                    DecisionRequest.class);
+        //
+        // Setup our temporary folder
+        //
+        XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename);
+        propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties",
+                properties, myCreator);
+        //
+        // Load XacmlApplicationServiceProvider service
+        //
+        ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
+                ServiceLoader.load(XacmlApplicationServiceProvider.class);
+        //
+        // Look for our class instance and save it
+        //
+        StringBuilder strDump = new StringBuilder("Loaded applications:" + System.lineSeparator());
+        Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
+        while (iterator.hasNext()) {
+            XacmlApplicationServiceProvider application = iterator.next();
             //
-            // Try this later.
+            // Is it our service?
             //
-            StringBuilder strDump = new StringBuilder("Loaded applications:" + System.lineSeparator());
-            Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
-            while (iterator.hasNext()) {
-                XacmlApplicationServiceProvider application = iterator.next();
+            if (application instanceof MonitoringPdpApplication) {
                 //
-                // Is it our service?
+                // Should be the first and only one
                 //
-                if (application instanceof MonitoringPdpApplication) {
-                    //
-                    // 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());
+                assertThat(service).isNull();
+                service = application;
             }
-            LOGGER.debug("{}", strDump);
-            //
-            // Tell it to initialize based on the properties file
-            // we just built for it.
-            //
-            service.initialize(propertiesFile.toPath().getParent());
-            //
-            // Make sure there's an application name
-            //
-            assertThat(service.applicationName()).isNotEmpty();
-            //
-            // Ensure it has the supported policy types and
-            // can support the correct policy types.
-            //
-            assertThat(service.canSupportPolicyType("onap.Monitoring", "1.0.0")).isTrue();
-            assertThat(service.canSupportPolicyType("onap.Monitoring", "1.5.0")).isTrue();
-            assertThat(service.canSupportPolicyType("onap.policies.monitoring.foobar", "1.0.1")).isTrue();
-            assertThat(service.canSupportPolicyType("onap.foobar", "1.0.0")).isFalse();
-            assertThat(service.supportedPolicyTypes()).contains("onap.Monitoring");
-            //
-            // Ensure it supports decisions
-            //
-            assertThat(service.actionDecisionsSupported()).contains("configure");
-        }).doesNotThrowAnyException();
+            strDump.append(application.applicationName());
+            strDump.append(" supports ");
+            strDump.append(application.supportedPolicyTypes());
+            strDump.append(System.lineSeparator());
+        }
+        LOGGER.debug("{}", strDump);
+        //
+        // Tell it to initialize based on the properties file
+        // we just built for it.
+        //
+        service.initialize(propertiesFile.toPath().getParent());
     }
 
     @Test
-    public void testNoPolicies() {
+    public void test1Basics() {
         //
-        // Make a simple decision - NO policies are loaded
+        // Make sure there's an application name
         //
-        assertThatCode(() -> {
-            //
-            // Ask for a decision
-            //
-            DecisionResponse response = service.makeDecision(requestSinglePolicy);
-            LOGGER.info("Decision {}", response);
+        assertThat(service.applicationName()).isNotEmpty();
+        //
+        // Ensure it has the supported policy types and
+        // can support the correct policy types.
+        //
+        assertThat(service.canSupportPolicyType("onap.Monitoring", "1.0.0")).isTrue();
+        assertThat(service.canSupportPolicyType("onap.Monitoring", "1.5.0")).isTrue();
+        assertThat(service.canSupportPolicyType("onap.policies.monitoring.foobar", "1.0.1")).isTrue();
+        assertThat(service.canSupportPolicyType("onap.foobar", "1.0.0")).isFalse();
+        assertThat(service.supportedPolicyTypes()).contains("onap.Monitoring");
+        //
+        // Ensure it supports decisions
+        //
+        assertThat(service.actionDecisionsSupported()).contains("configure");
+    }
 
-            assertThat(response).isNotNull();
-            assertThat(response.getErrorMessage()).isNullOrEmpty();
-            assertThat(response.getPolicies().size()).isEqualTo(0);
+    @Test
+    public void test2NoPolicies() {
+        //
+        // Ask for a decision
+        //
+        DecisionResponse response = service.makeDecision(requestSinglePolicy);
+        LOGGER.info("Decision {}", response);
 
-        }).doesNotThrowAnyException();
+        assertThat(response).isNotNull();
+        assertThat(response.getPolicies().size()).isEqualTo(0);
     }
 
     @SuppressWarnings("unchecked")
     @Test
-    public void testvDnsPolicy() {
+    public void test3AddvDnsPolicy() throws IOException, CoderException {
         //
         // Now load the vDNS Policy - make sure
         // the pdp can support it and have it load
         // into the PDP.
         //
-        assertThatCode(() -> {
-            try (InputStream is = new FileInputStream("src/test/resources/vDNS.policy.input.yaml")) {
-                Yaml yaml = new Yaml();
-                Map<String, Object> toscaObject = yaml.load(is);
-                List<Object> policies = (List<Object>) toscaObject.get("policies");
-                //
-                // What we should really do is split the policies out from the ones that
-                // are not supported to ones that are. And then load these.
+        try (InputStream is = new FileInputStream("src/test/resources/vDNS.policy.input.yaml")) {
+            //
+            // Have yaml parse it
+            //
+            Yaml yaml = new Yaml();
+            Map<String, Object> toscaObject = yaml.load(is);
+            List<Object> policies = (List<Object>) toscaObject.get("policies");
+            //
+            // Sanity check to ensure the policy type and version are supported
+            //
+            for (Object policyObject : policies) {
                 //
-                // In another future review....
+                // Get the contents
                 //
-                for (Object policyObject : policies) {
+                Map<String, Object> policyContents = (Map<String, Object>) policyObject;
+                for (Entry<String, Object> entrySet : policyContents.entrySet()) {
+                    LOGGER.info("Entry set {}", entrySet.getKey());
+                    Map<String, Object> policyDefinition = (Map<String, Object>) entrySet.getValue();
                     //
-                    // Get the contents
+                    // Find the type and make sure the engine supports it
                     //
-                    Map<String, Object> policyContents = (Map<String, Object>) policyObject;
-                    for (Entry<String, Object> entrySet : policyContents.entrySet()) {
-                        LOGGER.info("Entry set {}", entrySet.getKey());
-                        Map<String, Object> policyDefinition = (Map<String, Object>) entrySet.getValue();
-                        //
-                        // Find the type and make sure the engine supports it
-                        //
-                        assertThat(policyDefinition.containsKey("type")).isTrue();
-                        assertThat(service.canSupportPolicyType(
-                                policyDefinition.get("type").toString(),
-                                policyDefinition.get("version").toString()))
-                            .isTrue();
-                    }
+                    assertThat(policyDefinition.containsKey("type")).isTrue();
+                    assertThat(service.canSupportPolicyType(
+                            policyDefinition.get("type").toString(),
+                            policyDefinition.get("version").toString()))
+                        .isTrue();
                 }
-                //
-                // Just go ahead and load them all for now
-                //
-                // Assuming all are supported etc.
-                //
-                service.loadPolicies(toscaObject);
-                //
-                // Ask for a decision
-                //
-                DecisionResponse response = service.makeDecision(requestSinglePolicy);
-                LOGGER.info("Decision {}", response);
-
-                assertThat(response).isNotNull();
-                assertThat(response.getPolicies().size()).isEqualTo(1);
-                //
-                // Dump it out as Json
-                //
-                LOGGER.info(gsonDecisionResponse.toJson(response));
             }
-        }).doesNotThrowAnyException();
+            //
+            // Load the policies
+            //
+            service.loadPolicies(toscaObject);
+            //
+            // Ask for a decision
+            //
+            DecisionResponse response = service.makeDecision(requestSinglePolicy);
+            LOGGER.info("Decision {}", response);
+
+            assertThat(response).isNotNull();
+            assertThat(response.getPolicies().size()).isEqualTo(1);
+            //
+            // Dump it out as Json
+            //
+            LOGGER.info(gson.encode(response));
+        }
     }
 
     @Test
-    public void testBadPolicies() {
+    public void test4BadPolicies() {
+        /*
+         *
+         * THESE TEST SHOULD BE MOVED INTO THE API PROJECT
+         *
         //
         // No need for service, just test some of the methods
         // for bad policies
         //
         MonitoringPdpApplication onapPdpEngine = new MonitoringPdpApplication();
 
-        /*
         assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> {
             try (InputStream is =
                     new FileInputStream("src/test/resources/test.monitoring.policy.missingmetadata.yaml")) {
diff --git a/applications/monitoring/src/test/resources/vDNS.policy.decision.payload.json b/applications/monitoring/src/test/resources/vDNS.policy.decision.payload.json
deleted file mode 100644 (file)
index e69de29..0000000
index 9b5330d..56a92d6 100644 (file)
@@ -19,14 +19,6 @@ xacml.att.functionDefinitionFactory=com.att.research.xacmlatt.pdp.std.StdFunctio
 #
 xacml.att.policyFinderFactory=org.onap.policy.pdp.xacml.application.common.OnapPolicyFinderFactory
 
-#
-# NOTE: If you are testing against a RESTful PDP, then the PDP must be configured with the
-# policies and PIP configuration as defined below. Otherwise, this is the configuration that
-# the embedded PDP uses.
-#
-
-policytypes=onap.Monitoring, onap.policies.monitoring.cdap.tca.hi.lo.app
-
 # Policies to load
 #
 xacml.rootPolicies=monitoring
diff --git a/applications/optimization/pom.xml b/applications/optimization/pom.xml
new file mode 100644 (file)
index 0000000..0723ec5
--- /dev/null
@@ -0,0 +1,43 @@
+<!--
+  ============LICENSE_START=======================================================
+  ONAP Policy Engine - XACML PDP
+  ================================================================================
+  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=========================================================
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.onap.policy.xacml-pdp.applications</groupId>
+        <artifactId>applications</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>optimization</artifactId>
+
+    <name>${project.artifactId}</name>
+    <description>This modules contains applications that implement policy-types for XACML PDP.</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onap.policy.xacml-pdp.applications</groupId>
+            <artifactId>common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplication.java b/applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplication.java
new file mode 100644 (file)
index 0000000..4a4a604
--- /dev/null
@@ -0,0 +1,164 @@
+/*-
+ * ============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.optimization;
+
+import com.att.research.xacml.api.Request;
+import com.att.research.xacml.api.Response;
+import com.att.research.xacml.util.XACMLPolicyWriter;
+import com.google.common.collect.Lists;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Arrays;
+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;
+
+import org.onap.policy.models.decisions.concepts.DecisionRequest;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
+import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
+import org.onap.policy.pdp.xacml.application.common.std.StdMatchableTranslator;
+import org.onap.policy.pdp.xacml.application.common.std.StdXacmlApplicationServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OptimizationPdpApplication extends StdXacmlApplicationServiceProvider {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(OptimizationPdpApplication.class);
+    private static final String STRING_VERSION100 = "1.0.0";
+
+    private StdMatchableTranslator translator = new StdMatchableTranslator();
+    private Map<String, String> supportedPolicyTypes = new HashMap<>();
+
+    /**
+     * Constructor.
+     */
+    public OptimizationPdpApplication() {
+        this.supportedPolicyTypes.put("onap.policies.optimization.AffinityPolicy", STRING_VERSION100);
+        this.supportedPolicyTypes.put("onap.policies.optimization.DistancePolicy", STRING_VERSION100);
+        this.supportedPolicyTypes.put("onap.policies.optimization.HpaPolicy", STRING_VERSION100);
+        this.supportedPolicyTypes.put("onap.policies.optimization.OptimizationPolicy", STRING_VERSION100);
+        this.supportedPolicyTypes.put("onap.policies.optimization.PciPolicy", STRING_VERSION100);
+        this.supportedPolicyTypes.put("onap.policies.optimization.QueryPolicy", STRING_VERSION100);
+        this.supportedPolicyTypes.put("onap.policies.optimization.SubscriberPolicy", STRING_VERSION100);
+        this.supportedPolicyTypes.put("onap.policies.optimization.Vim_fit", STRING_VERSION100);
+        this.supportedPolicyTypes.put("onap.policies.optimization.VnfPolicy", STRING_VERSION100);
+    }
+
+    @Override
+    public String applicationName() {
+        return "Optimization Application";
+    }
+
+    @Override
+    public List<String> actionDecisionsSupported() {
+        return Arrays.asList("optimize");
+    }
+
+    @Override
+    public synchronized List<String> supportedPolicyTypes() {
+        return Lists.newArrayList(supportedPolicyTypes.keySet());
+    }
+
+    @Override
+    public boolean canSupportPolicyType(String policyType, String policyTypeVersion) {
+        //
+        // For the time being, restrict this if the version isn't known.
+        // Could be too difficult to support changing of versions dynamically.
+        //
+        if (! this.supportedPolicyTypes.containsKey(policyType)) {
+            return false;
+        }
+        //
+        // Must match version exactly
+        //
+        return this.supportedPolicyTypes.get(policyType).equals(policyTypeVersion);
+    }
+
+    @Override
+    public synchronized void loadPolicies(Map<String, Object> toscaPolicies) {
+        try {
+            //
+            // Convert the policies first
+            //
+            List<PolicyType> listPolicies = translator.scanAndConvertPolicies(toscaPolicies);
+            if (listPolicies.isEmpty()) {
+                throw new ToscaPolicyConversionException("Converted 0 policies");
+            }
+            //
+            // Create a copy of the properties object
+            //
+            Properties newProperties = this.getProperties();
+            //
+            // Iterate through the policies
+            //
+            for (PolicyType newPolicy : listPolicies) {
+                //
+                // Construct the filename
+                //
+                Path refPath = XacmlPolicyUtils.constructUniquePolicyFilename(newPolicy, this.getDataPath());
+                //
+                // Write the policy to disk
+                // Maybe check for an error
+                //
+                XACMLPolicyWriter.writePolicyFile(refPath, newPolicy);
+                //
+                // Add root policy to properties object
+                //
+                XacmlPolicyUtils.addRootPolicy(newProperties, refPath);
+            }
+            //
+            // Write the properties to disk
+            //
+            XacmlPolicyUtils.storeXacmlProperties(newProperties,
+                    XacmlPolicyUtils.getPropertiesPath(this.getDataPath()));
+            //
+            // Reload the engine
+            //
+            this.createEngine(newProperties);
+        } catch (IOException | ToscaPolicyConversionException e) {
+            LOGGER.error("Failed to loadPolicies {}", e);
+        }
+    }
+
+    @Override
+    public synchronized DecisionResponse makeDecision(DecisionRequest request) {
+        //
+        // Convert to a XacmlRequest
+        //
+        Request xacmlRequest = translator.convertRequest(request);
+        //
+        // Now get a decision
+        //
+        Response xacmlResponse = this.xacmlDecision(xacmlRequest);
+        //
+        // Convert to a DecisionResponse
+        //
+        return translator.convertResponse(xacmlResponse);
+    }
+
+}
diff --git a/applications/optimization/src/main/resources/META-INF/services/org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider b/applications/optimization/src/main/resources/META-INF/services/org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider
new file mode 100644 (file)
index 0000000..ffb7e80
--- /dev/null
@@ -0,0 +1 @@
+org.onap.policy.xacml.pdp.application.optimization.OptimizationPdpApplication
\ No newline at end of file
diff --git a/applications/optimization/src/test/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplicationTest.java b/applications/optimization/src/test/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplicationTest.java
new file mode 100644 (file)
index 0000000..efbf730
--- /dev/null
@@ -0,0 +1,211 @@
+/*-
+ * ============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.optimization;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.ServiceLoader;
+
+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.XacmlApplicationServiceProvider;
+import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.yaml.snakeyaml.Yaml;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class OptimizationPdpApplicationTest {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(OptimizationPdpApplicationTest.class);
+    private static Properties properties = new Properties();
+    private static File propertiesFile;
+    private static XacmlApplicationServiceProvider service;
+    private static StandardCoder gson = new StandardCoder();
+    private static DecisionRequest requestAffinity;
+
+    @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 {
+        //
+        // Load Single Decision Request
+        //
+        requestAffinity = gson.decode(
+                TextFileUtils
+                    .getTextFileAsString(
+                            "../../main/src/test/resources/decisions/decision.optimization.affinity.input.json"),
+                    DecisionRequest.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<XacmlApplicationServiceProvider> applicationLoader =
+                ServiceLoader.load(XacmlApplicationServiceProvider.class);
+        //
+        // Iterate through Xacml application services and find
+        // the optimization service. Save it for use throughout
+        // all the Junit tests.
+        //
+        StringBuilder strDump = new StringBuilder("Loaded applications:" + System.lineSeparator());
+        Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
+        while (iterator.hasNext()) {
+            XacmlApplicationServiceProvider application = iterator.next();
+            //
+            // Is it our service?
+            //
+            if (application instanceof OptimizationPdpApplication) {
+                //
+                // 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.debug("{}", strDump);
+        //
+        // Tell it to initialize based on the properties file
+        // we just built for it.
+        //
+        service.initialize(propertiesFile.toPath().getParent());
+    }
+
+    @Test
+    public void test1Basics() {
+        //
+        // Make sure there's an application name
+        //
+        assertThat(service.applicationName()).isNotEmpty();
+        //
+        // Decisions
+        //
+        assertThat(service.actionDecisionsSupported().size()).isEqualTo(1);
+        assertThat(service.actionDecisionsSupported()).contains("optimize");
+        //
+        // Ensure it has the supported policy types and
+        // can support the correct policy types.
+        //
+        assertThat(service.canSupportPolicyType("onap.policies.optimization.AffinityPolicy", "1.0.0")).isTrue();
+        assertThat(service.canSupportPolicyType("onap.foobar", "1.0.0")).isFalse();
+    }
+
+    @Test
+    public void test2NoPolicies() {
+        //
+        // Ask for a decision
+        //
+        DecisionResponse response = service.makeDecision(requestAffinity);
+        LOGGER.info("Decision {}", response);
+
+        assertThat(response).isNotNull();
+        assertThat(response.getPolicies().size()).isEqualTo(0);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void test3AddOptimizationPolicies() throws CoderException, FileNotFoundException, IOException {
+        //
+        // Now load the optimization policies
+        //
+        try (InputStream is = new FileInputStream("src/test/resources/vCPE.policies.optimization.input.tosca.yaml")) {
+            //
+            // Have yaml parse it
+            //
+            Yaml yaml = new Yaml();
+            Map<String, Object> toscaObject = yaml.load(is);
+            List<Object> policies = (List<Object>) toscaObject.get("policies");
+            //
+            // Sanity check to ensure the policy type and version are supported
+            //
+            for (Object policyObject : policies) {
+                //
+                // Get the contents
+                //
+                Map<String, Object> policyContents = (Map<String, Object>) policyObject;
+                for (Entry<String, Object> entrySet : policyContents.entrySet()) {
+                    LOGGER.info("Entry set {}", entrySet.getKey());
+                    Map<String, Object> policyDefinition = (Map<String, Object>) entrySet.getValue();
+                    //
+                    // Find the type and make sure the engine supports it
+                    //
+                    assertThat(policyDefinition.containsKey("type")).isTrue();
+                    assertThat(service.canSupportPolicyType(
+                            policyDefinition.get("type").toString(),
+                            policyDefinition.get("version").toString()))
+                        .isTrue();
+                }
+            }
+            //
+            // Load the policies
+            //
+            service.loadPolicies(toscaObject);
+            //
+            // Ask for a decision
+            //
+            DecisionResponse response = service.makeDecision(requestAffinity);
+            LOGGER.info("Decision {}", response);
+
+            assertThat(response).isNotNull();
+            assertThat(response.getPolicies().size()).isEqualTo(1);
+            //
+            // Dump it out as Json
+            //
+            LOGGER.info(gson.encode(response));
+        }
+    }
+
+}
diff --git a/applications/optimization/src/test/resources/vCPE.policies.optimization.input.tosca.yaml b/applications/optimization/src/test/resources/vCPE.policies.optimization.input.tosca.yaml
new file mode 100644 (file)
index 0000000..2fc7c14
--- /dev/null
@@ -0,0 +1,137 @@
+tosca_definitions_version: tosca_simple_yaml_1_0_0
+topology_template:
+policies:
+    - 
+        OSDF_CASABLANCA.Affinity_vCPE_1:
+            type: onap.policies.optimization.AffinityPolicy
+            version: 1.0.0
+            metadata:
+                policy-id: OSDF_CASABLANCA.Affinity_vCPE_1
+                policy-version: 1
+            properties:
+                identity: affinity_vCPE
+                policyScope: [vCPE, US, INTERNATIONAL, ip, vGMuxInfra, vG]
+                affinityProperties: 
+                    qualifier: same
+                    category: complex
+                policyType: zone
+                resources: [vGMuxInfra, vG]
+    -
+        OSDF_CASABLANCA.Capacity_vG_1:
+            type: onap.policies.optimization.Vim_fit
+            version: 1.0.0
+            metadata:
+                policy-id: OSDF_CASABLANCA.Capacity_vG_1
+                policy-version: 1
+            properties:
+                identity: capacity_vG
+                policyScope: [VCPE, US, INTERNATIONAL, ip, vG]
+                resources: [vG]
+                capacityProperty: 
+                   controller: multicloud
+                   request: "{\"vCPU\": 10, \"Memory\": {\"quantity\": {\"get_param\": \"REQUIRED_MEM\"}, \"unit\": \"GB\"}, \"Storage\": {\"quantity\": {\"get_param\": \"REQUIRED_DISK\"}, \"unit\": \"GB\"}}"
+                policyType: vim_fit
+                applicableResources: any
+    -
+        OSDF_CASABLANCA.Distance_vG_1:
+            type: onap.policies.optimization.DistancePolicy
+            version: 1.0.0
+            metadata:
+                policy-id: OSDF_CASABLANCA.Distance_vG_1
+                policy-version: 1
+            properties:
+                distanceProperties: 
+                    locationInfo: customer_loc
+                    distance: 
+                        value: 1500
+                        operator: "<"
+                        unit: km
+                identity: "distance-vG"
+                resources: [vG]
+                policyScope: [vCPE, US, INTERNATIONAL, ip, vG]
+                policyType: distance_to_location
+                applicableResources: any
+    -
+        OSDF_CASABLANCA.hpa_policy_vG_1:
+            type: onap.policies.optimization.HpaPolicy
+            version: 1.0.0
+            metadata:
+                policy-id: OSDF_CASABLANCA.hpa_policy_vG_1
+                policy-version: 1
+            properties:
+                resources: [vG]
+                identity: "hpa-vG"
+                policyScope: [vCPE, US, INTERNATIONAL, ip, vG]
+                policyType: hpa            
+                # NONE OF THE FLAVORFEATURES CAME OUT RIGHT
+    -
+        OSDF_CASABLANCA.queryPolicy_vCPE:
+            type: onap.policies.optimization.QueryPolicy
+            version: 1.0.0
+            metadata:
+                policy-id: OSDF_CASABLANCA.queryPolicy_vCPE
+                policy-version: 1
+            properties:
+                queryProperties: 
+                    - 
+                        attribute: locationId
+                        attribute_location: customerLocation
+                        value: ""
+                    - 
+                        attribute: id
+                        attribute_location: "vpnInfo.vpnId"
+                        value: ""
+                    - 
+                        attribute: upstreamBW
+                        attribute_location: "vpnInfo.upstreamBW"
+                        value: ""
+                    - 
+                        attribute: customerLatitude
+                        attribute_location: customerLatitude
+                        value: 1.1
+                    - 
+                        attribute: customerLongitude
+                        attribute_location: customerLongitude
+                        value: 2.2
+                serviceName: vCPE
+                policyScope: [vCPE, US, INTERNATIONAL, ip, vGMuxInfra, vG]
+                policyType: request_param_query
+                identity: vCPE_Query_Policy            
+            
+    -
+        OSDF_CASABLANCA.SubscriberPolicy_v1:
+            type: onap.policies.optimization.SubscriberPolicy
+            version: 1.0.0
+            metadata:
+                policy-id: OSDF_CASABLANCA.SubscriberPolicy_v1
+                policy-version: 1
+            properties:
+                identity: subscriber_vCPE
+                policyScope: [vCPE, subscriber_x, subscriber_y, subscriberPolicy]
+                properties: 
+                    subscriberName: [subscriber_x, subscriber_y]
+                    subscriberRole: ["PVT Homing"]
+                    provStatus: [CAPPED]
+                policyType: subscriberPolicy
+                serviceName: vCPE
+    -
+        OSDF_CASABLANCA.vnfPolicy_vG:
+            type: onap.policies.optimization.VnfPolicy
+            version: 1.0.0
+            metadata:
+                policy-id: OSDF_CASABLANCA.vnfPolicy_vG
+                policy-version: 1
+            properties:
+                identity: vnf_vG
+                policyScope: [vCPE, US, INTERNATIONAL, ip, vG]
+                policyType: vnfPolicy
+                resources: [vG]
+                applicableResources: any
+                vnfProperties: 
+                    - 
+                        inventoryProvider: aai
+                        serviceType: ""
+                        inventoryType: cloud
+                        customerId: ""
+                        orchestrationStatus: ""
+                        equipmentRole: ""
\ No newline at end of file
diff --git a/applications/optimization/src/test/resources/xacml.properties b/applications/optimization/src/test/resources/xacml.properties
new file mode 100644 (file)
index 0000000..5ea247c
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# Properties that the embedded PDP engine uses to configure and load
+#
+# Standard API Factories
+#
+xacml.dataTypeFactory=com.att.research.xacml.std.StdDataTypeFactory
+xacml.pdpEngineFactory=com.att.research.xacmlatt.pdp.ATTPDPEngineFactory
+xacml.pepEngineFactory=com.att.research.xacml.std.pep.StdEngineFactory
+xacml.pipFinderFactory=com.att.research.xacml.std.pip.StdPIPFinderFactory
+xacml.traceEngineFactory=com.att.research.xacml.std.trace.LoggingTraceEngineFactory
+#
+# AT&T PDP Implementation Factories
+#
+xacml.att.evaluationContextFactory=com.att.research.xacmlatt.pdp.std.StdEvaluationContextFactory
+xacml.att.combiningAlgorithmFactory=com.att.research.xacmlatt.pdp.std.StdCombiningAlgorithmFactory
+xacml.att.functionDefinitionFactory=com.att.research.xacmlatt.pdp.std.StdFunctionDefinitionFactory
+#
+# ONAP PDP Implementation Factories
+#
+xacml.att.policyFinderFactory=org.onap.policy.pdp.xacml.application.common.OnapPolicyFinderFactory
+
+#
+# Use a root combining algorithm
+#
+xacml.att.policyFinderFactory.combineRootPolicies=urn:com:att:xacml:3.0:policy-combining-algorithm:combined-permit-overrides
+
+#
+# Policies to load
+#
+xacml.rootPolicies=
+xacml.referencedPolicies=
\ No newline at end of file
index 8d5d4b2..0a1cac0 100644 (file)
@@ -35,6 +35,7 @@
     <module>common</module>
     <module>monitoring</module>
     <module>guard</module>
+    <module>optimization</module>
   </modules>
 
 
index f4b0c9f..872a5a0 100644 (file)
             <artifactId>guard</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.onap.policy.xacml-pdp.applications</groupId>
+            <artifactId>optimization</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 
     <build>
index ba9b554..65d40c0 100644 (file)
@@ -1,14 +1,15 @@
 {
   "ONAPName": "Policy",
-  "ONAPComponent": "DCAE",
-  "ONAPInstance": "optional-tbd",
+  "ONAPComponent": "drools-pdp",
+  "ONAPInstance": "usecase-template",
+  "requestId": "unique-request-id-2",
   "action": "guard",
   "resource": {
       "guard": {
           "actor": "SO",
           "recipe": "scaleOut",
           "clname": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3",
-          "vfcount" : "5"
+          "operationCount" : "1"
       }
   }
 }
\ No newline at end of file
diff --git a/main/src/test/resources/decisions/decision.guard.shoulddeny.input2.json b/main/src/test/resources/decisions/decision.guard.shoulddeny.input2.json
new file mode 100644 (file)
index 0000000..29dfc3d
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "ONAPName": "Policy",
+  "ONAPComponent": "drools-pdp",
+  "ONAPInstance": "usecase-template",
+  "requestId": "unique-request-id-2",
+  "action": "guard",
+  "resource": {
+      "guard": {
+          "actor": "SO",
+          "recipe": "scaleOut",
+          "clname": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3",
+          "vfCount" : "6"
+      }
+  }
+}
\ No newline at end of file
diff --git a/main/src/test/resources/decisions/decision.guard.shoulddeny.output.json b/main/src/test/resources/decisions/decision.guard.shoulddeny.output.json
deleted file mode 100644 (file)
index 3752fe4..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-    "status": "deny"
-}
\ No newline at end of file
index 324d495..92e933f 100644 (file)
@@ -1,14 +1,16 @@
 {
   "ONAPName": "Policy",
-  "ONAPComponent": "DCAE",
-  "ONAPInstance": "optional-tbd",
+  "ONAPComponent": "drools-pdp",
+  "ONAPInstance": "usecase-template",
+  "requestId": "unique-request-id-1",
   "action": "guard",
   "resource": {
       "guard": {
           "actor": "SO",
           "recipe": "scaleOut",
           "clname": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3",
-          "vfcount" : "1"
+          "operationCount": "0",
+          "vfCount": "1"
       }
   }
 }
\ No newline at end of file
diff --git a/main/src/test/resources/decisions/decision.guard.shouldpermit.output.json b/main/src/test/resources/decisions/decision.guard.shouldpermit.output.json
deleted file mode 100644 (file)
index a193926..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-    "status": "permit"
-}
\ No newline at end of file
diff --git a/main/src/test/resources/decisions/decision.optimization.affinity.input.json b/main/src/test/resources/decisions/decision.optimization.affinity.input.json
new file mode 100644 (file)
index 0000000..1794ace
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "ONAPName": "OOF",
+  "ONAPComponent": "OOF-component",
+  "ONAPInstance": "OOF-component-instance",
+  "action": "optimize",
+  "resource": {
+      "policyScope": ["vCPE", "US", "INTERNATIONAL", "ip", "vGMuxInfra", "vG"],
+      "policyType": "zone"
+  }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 7783865..1559f96 100644 (file)
--- a/pom.xml
+++ b/pom.xml
             <artifactId>snakeyaml</artifactId>
             <version>1.24</version>
         </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.json</groupId>
             <artifactId>json</artifactId>
         </dependency>
         <dependency>
             <groupId>org.onap.policy.models</groupId>
-            <artifactId>models-decisions</artifactId>
+            <artifactId>policy-models-decisions</artifactId>
             <version>${policy.models.version}</version>
         </dependency>        
         <dependency>