diff options
7 files changed, 443 insertions, 219 deletions
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/PolicyApiCaller.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/PolicyApiCaller.java index 9d47517a..632bdcb2 100644 --- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/PolicyApiCaller.java +++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/PolicyApiCaller.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,8 +28,8 @@ import org.onap.policy.common.endpoints.http.client.HttpClientConfigException; import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance; import org.onap.policy.common.endpoints.parameters.RestServerParameters; import org.onap.policy.common.gson.GsonMessageBodyHandler; -import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -75,7 +75,7 @@ public class PolicyApiCaller { * @return the desired policy type * @throws PolicyApiException if an error occurs */ - public ToscaPolicyType getPolicyType(ToscaPolicyTypeIdentifier type) throws PolicyApiException { + public ToscaServiceTemplate getPolicyType(ToscaPolicyTypeIdentifier type) throws PolicyApiException { try { Response resp = httpClient @@ -83,7 +83,7 @@ public class PolicyApiCaller { switch (resp.getStatus()) { case HttpURLConnection.HTTP_OK: - return resp.readEntity(ToscaPolicyType.class); + return resp.readEntity(ToscaServiceTemplate.class); case HttpURLConnection.HTTP_NOT_FOUND: logger.warn("policy-api not found {}", resp); throw new NotFoundException(type.toString()); 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 index ae09ec10..0d1daaa6 100644 --- 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 @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,10 +34,8 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; @@ -58,12 +56,12 @@ import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.coder.StandardYamlCoder; import org.onap.policy.models.decisions.concepts.DecisionRequest; import org.onap.policy.models.decisions.concepts.DecisionResponse; +import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; -import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate; import org.onap.policy.pdp.xacml.application.common.OnapObligation; import org.onap.policy.pdp.xacml.application.common.PolicyApiCaller; import org.onap.policy.pdp.xacml.application.common.PolicyApiException; @@ -86,7 +84,7 @@ public class StdMatchableTranslator extends StdBaseTranslator { private static final Logger LOGGER = LoggerFactory.getLogger(StdMatchableTranslator.class); private static final StandardYamlCoder standardYamlCoder = new StandardYamlCoder(); - private final Map<ToscaPolicyTypeIdentifier, ToscaPolicyType> matchablePolicyTypes = new HashMap<>(); + private final Map<ToscaPolicyTypeIdentifier, ToscaServiceTemplate> matchablePolicyTypes = new HashMap<>(); @Setter private RestServerParameters apiRestParameters; @Setter @@ -236,12 +234,12 @@ public class StdMatchableTranslator extends StdBaseTranslator { // // Get the TOSCA Policy Type for this policy // - Collection<ToscaPolicyType> toscaPolicyTypes = this.getPolicyTypes(toscaPolicy.getTypeIdentifier()); + ToscaServiceTemplate toscaPolicyTypeTemplate = this.findPolicyType(toscaPolicy.getTypeIdentifier()); // // If we don't have any TOSCA policy types, then we cannot know // which properties are matchable. // - if (toscaPolicyTypes.isEmpty()) { + if (toscaPolicyTypeTemplate == null) { throw new ToscaPolicyConversionException( "Cannot retrieve Policy Type definition for policy " + toscaPolicy.getName()); } @@ -270,7 +268,7 @@ public class StdMatchableTranslator extends StdBaseTranslator { // Generate the TargetType - the policy should not be evaluated // unless all the matchable properties it cares about are matched. // - Pair<TargetType, Integer> pairGenerated = generateTargetType(toscaPolicy.getProperties(), toscaPolicyTypes); + Pair<TargetType, Integer> pairGenerated = generateTargetType(toscaPolicy, toscaPolicyTypeTemplate); newPolicyType.setTarget(pairGenerated.getLeft()); // // Now represent the policy as Json @@ -326,97 +324,314 @@ public class StdMatchableTranslator extends StdBaseTranslator { * @param policyTypes Collection of policy Type to find matchable metadata * @return {@code Pair<TargetType, Integer>} Returns a TargetType and a Total Weight of matchables. */ - protected Pair<TargetType, Integer> generateTargetType(Map<String, Object> properties, - Collection<ToscaPolicyType> policyTypes) { + protected Pair<TargetType, Integer> generateTargetType(ToscaPolicy policyType, + ToscaServiceTemplate policyTemplate) { + // + // Our return object + // TargetType targetType = new TargetType(); // - // Iterate the properties + // Top-level list of properties + // + Map<String, Object> properties = policyType.getProperties(); + // + // To start, we know these properties are for this specific Policy Type ID/Version + // + ToscaPolicyTypeIdentifier propertiesPolicyId = policyType.getTypeIdentifier(); + // + // Scan the property map for matchables // - int totalWeight = findMatchableFromMap(properties, policyTypes, targetType); + int totalWeight = findMatchablesInProperties(properties, propertiesPolicyId, policyTemplate, targetType); LOGGER.info("Total weight is {}", totalWeight); return Pair.of(targetType, totalWeight); } - @SuppressWarnings("unchecked") - protected int findMatchableFromList(List<Object> listProperties, Collection<ToscaPolicyType> policyTypes, + protected int findMatchablesInProperties(Map<String, Object> properties, + ToscaPolicyTypeIdentifier propertiesPolicyId, + ToscaServiceTemplate policyTemplate, TargetType targetType) { - LOGGER.info("findMatchableFromList {}", listProperties); + LOGGER.info("findMatchablesInProperties from policy Type {} {}", propertiesPolicyId, properties); + // + // We better have the policy type definition available from the template + // + ToscaPolicyType policyType = getToscaPolicyTypeFromTemplate(propertiesPolicyId, policyTemplate); + if (policyType == null) { + LOGGER.error("Failed to find policy type in template {}", propertiesPolicyId); + return 0; + } + // + // Our total weight to return + // int totalWeight = 0; - for (Object property : listProperties) { - if (property instanceof List) { - totalWeight += findMatchableFromList((List<Object>) property, policyTypes, targetType); - } else if (property instanceof Map) { - totalWeight += findMatchableFromMap((Map<String, Object>) property, policyTypes, targetType); + for (Entry<String, Object> entrySet : properties.entrySet()) { + // + // Find the property details + // + Pair<ToscaProperty, ToscaServiceTemplate> property = findProperty(entrySet.getKey(), + policyType, propertiesPolicyId, policyTemplate); + if (property == null) { + continue; + } + ToscaProperty toscaProperty = property.getLeft(); + LOGGER.info("Found property {} with type {} schema {}", entrySet.getKey(), toscaProperty.getType(), + (toscaProperty.getEntrySchema() == null ? "null" : toscaProperty.getEntrySchema().getType())); + // + // Is it matchable? + // + if (checkIsMatchableProperty(toscaProperty)) { + // + // This will generate the matchables for the property + // + int weight = generateMatchable(targetType, entrySet.getKey(), entrySet.getValue(), + property.getLeft(), property.getRight()); + LOGGER.info("Weight is {}", weight); + totalWeight += weight; + } else { + // + // Not matchable, but we need to check if this contains list or map of datatypes. + // Those will need to be searched for matchables. + // + if ("list".equals(toscaProperty.getType())) { + int weight = findMatchablesInList(entrySet.getKey(), entrySet.getValue(), toscaProperty, + policyTemplate, targetType); + LOGGER.info("Weight list is {}", weight); + totalWeight += weight; + } else if ("map".equals(toscaProperty.getType())) { + int weight = findMatchablesInMap(entrySet.getKey(), entrySet.getValue(), toscaProperty, + policyTemplate, targetType); + LOGGER.info("Weight map is {}", weight); + totalWeight += weight; + } } } return totalWeight; } - protected int findMatchableFromMap(Map<String, Object> properties, Collection<ToscaPolicyType> policyTypes, - TargetType targetType) { - LOGGER.info("findMatchableFromMap {}", properties); + @SuppressWarnings("unchecked") + protected int findMatchablesInList(String listPropertyName, Object listValue, ToscaProperty listProperty, + ToscaServiceTemplate listTemplate, TargetType targetType) { + // + // Don't bother if there is no schema (which should be a problem) or + // its a list of primitives + // + if (listProperty.getEntrySchema() == null) { + LOGGER.error("No entry schema for list property {}", listPropertyName); + return 0; + } + // + // If they are primitives, then no need to go through them. ?? + // + if (isYamlType(listProperty.getEntrySchema().getType())) { + LOGGER.info("list of primitives"); + return 0; + } + // + // Find the datatype + // + ToscaDataType listDataType = listTemplate.getDataTypes().get(listProperty.getEntrySchema().getType()); + if (listDataType == null) { + LOGGER.error("Unable to find datatype {}", listProperty.getEntrySchema().getType()); + return 0; + } + int totalWeight = 0; - for (Entry<String, Object> entrySet : properties.entrySet()) { + for (Object datatypeValue : ((Collection<Object>)listValue)) { // - // Is this a matchable property? + // This should be a map - because this is a list of datatypes. // - if (isMatchable(entrySet.getKey(), policyTypes)) { - LOGGER.info("Found matchable property {}", entrySet.getKey()); - int weight = generateMatchable(targetType, entrySet.getKey(), entrySet.getValue()); - LOGGER.info("Weight is {}", weight); - totalWeight += weight; - } else { + if (! (datatypeValue instanceof Map)) { + LOGGER.error("datatype {} value is not a map {}", listDataType.getName(), datatypeValue.getClass()); + continue; + } + for (Entry<String, Object> entrySet : ((Map<String, Object>)datatypeValue).entrySet()) { + ToscaProperty toscaProperty = listDataType.getProperties().get(entrySet.getKey()); + if (toscaProperty == null) { + LOGGER.error("Failed to find datatype {} property {}", listDataType.getName(), entrySet.getKey()); + continue; + } + LOGGER.info("Found list property {} with type {} schema {}", entrySet.getKey(), toscaProperty.getType(), + (toscaProperty.getEntrySchema() == null ? "null" : toscaProperty.getEntrySchema().getType())); // - // Check if we need to search deeper + // Is it matchable? // - totalWeight += checkDeeperForMatchable(entrySet.getValue(), policyTypes, targetType); + if (checkIsMatchableProperty(toscaProperty)) { + // + // This will generate the matchables for the property + // + int weight = generateMatchable(targetType, entrySet.getKey(), entrySet.getValue(), + toscaProperty, listTemplate); + LOGGER.info("Weight is {}", weight); + totalWeight += weight; + } else { + // + // Not matchable, but we need to check if this contains list or map of datatypes. + // Those will need to be searched for matchables. + // + if ("list".equals(toscaProperty.getType())) { + int weight = findMatchablesInList(entrySet.getKey(), entrySet.getValue(), toscaProperty, + listTemplate, targetType); + LOGGER.info("Weight list is {}", weight); + totalWeight += weight; + } else if ("map".equals(toscaProperty.getType())) { + int weight = findMatchablesInMap(entrySet.getKey(), entrySet.getValue(), toscaProperty, + listTemplate, targetType); + LOGGER.info("Weight map is {}", weight); + totalWeight += weight; + } + } } } + return totalWeight; } @SuppressWarnings("unchecked") - protected int checkDeeperForMatchable(Object property, Collection<ToscaPolicyType> policyTypes, - TargetType targetType) { - if (property instanceof List) { - return findMatchableFromList((List<Object>) property, policyTypes, targetType); - } else if (property instanceof Map) { - return findMatchableFromMap((Map<String, Object>) property, policyTypes, - targetType); - } - LOGGER.info("checkDeeperForMatchable not necessary for {}", property); - return 0; + protected int findMatchablesInMap(String mapPropertyName, Object mapValue, ToscaProperty mapProperty, + ToscaServiceTemplate mapTemplate, TargetType targetType) { + // + // There needs to be a schema. + // + if (mapProperty.getEntrySchema() == null) { + LOGGER.error("No entry schema for map property {}", mapPropertyName); + return 0; + } + // + // If they are primitives, then no need to go through them. ?? + // + if (isYamlType(mapProperty.getEntrySchema().getType())) { + LOGGER.debug("map property {} is primitives", mapPropertyName); + return 0; + } + // + // Find the datatype + // + ToscaDataType mapDataType = mapTemplate.getDataTypes().get(mapProperty.getEntrySchema().getType()); + if (mapDataType == null) { + LOGGER.error("Unable to find datatype {}", mapProperty.getEntrySchema().getType()); + return 0; + } + + int totalWeight = 0; + for (Entry<String, Object> entrySet : ((Map<String, Object>)mapValue).entrySet()) { + ToscaProperty toscaProperty = mapDataType.getProperties().get(entrySet.getKey()); + if (toscaProperty == null) { + LOGGER.error("Failed to find datatype {} property {}", mapDataType.getName(), entrySet.getKey()); + continue; + } + LOGGER.info("Found map property {} with type {} schema {}", entrySet.getKey(), toscaProperty.getType(), + (toscaProperty.getEntrySchema() == null ? "null" : toscaProperty.getEntrySchema().getType())); + // + // Is it matchable? + // + if (checkIsMatchableProperty(toscaProperty)) { + // + // This will generate the matchables for the property + // + int weight = generateMatchable(targetType, entrySet.getKey(), entrySet.getValue(), + toscaProperty, mapTemplate); + LOGGER.info("Weight is {}", weight); + totalWeight += weight; + } else { + // + // Not matchable, but we need to check if this contains list or map of datatypes. + // Those will need to be searched for matchables. + // + if ("list".equals(toscaProperty.getType())) { + int weight = findMatchablesInList(entrySet.getKey(), entrySet.getValue(), toscaProperty, + mapTemplate, targetType); + LOGGER.info("Weight list is {}", weight); + totalWeight += weight; + } else if ("map".equals(toscaProperty.getType())) { + int weight = findMatchablesInMap(entrySet.getKey(), entrySet.getValue(), toscaProperty, + mapTemplate, targetType); + LOGGER.info("Weight map is {}", weight); + totalWeight += weight; + } + } + } + + return totalWeight; } /** - * isMatchable - Iterates through available TOSCA Policy Types to determine if a property - * should be treated as matchable. + * findMatchableProperty - Iterates through available TOSCA Policy Types and return the + * ToscaProperty and template for the property. * * @param propertyName Name of property * @param policyTypes Collection of TOSCA Policy Types to scan - * @return true if matchable + * @return ToscaProperty and ToscaServiceTemplate if matchable */ - protected boolean isMatchable(String propertyName, Collection<ToscaPolicyType> policyTypes) { - for (ToscaPolicyType policyType : policyTypes) { - for (Entry<String, ToscaProperty> propertiesEntry : policyType.getProperties().entrySet()) { - if (checkIsMatchableProperty(propertyName, propertiesEntry)) { - return true; + protected Pair<ToscaProperty, ToscaServiceTemplate> findProperty(String propertyName, + ToscaPolicyType policyType, ToscaPolicyTypeIdentifier propertiesPolicyId, + ToscaServiceTemplate policyTemplate) { + // + // See if the property is defined by the policy template + // + ToscaProperty toscaProperty = policyType.getProperties().get(propertyName); + if (toscaProperty != null) { + // + // Does it contain the matchable property and if so its set to true? + // + return Pair.of(toscaProperty, policyTemplate); + } + LOGGER.debug("property {} is not in policy type {}", propertyName, propertiesPolicyId); + // + // Check its parent policy types + // + ToscaPolicyTypeIdentifier parentId = getParentDerivedFrom(propertiesPolicyId, policyTemplate); + while (parentId != null) { + LOGGER.debug("searching parent policy type {}", parentId); + // + // Search the existing template (should be there during runtime) + // + ToscaPolicyType parentPolicyType = getParentPolicyType(parentId, policyTemplate); + if (parentPolicyType != null) { + toscaProperty = parentPolicyType.getProperties().get(propertyName); + if (toscaProperty != null) { + return Pair.of(toscaProperty, policyTemplate); } // - // Check if its a list or map + // Move to the next parent + // + parentId = getParentDerivedFrom(parentId, policyTemplate); + } else { + LOGGER.warn("Parent policy type is not found {}", parentId); + // + // Find the parent policy type. During JUnit this may be in a separate + // file. We hope that during runtime the template is complete. // - if (isListOrMap(propertiesEntry.getValue().getType()) - && ! isYamlType(propertiesEntry.getValue().getEntrySchema().getType())) { - LOGGER.info("need to search list or map"); + ToscaServiceTemplate parentTemplate = findPolicyType(parentId); + if (parentTemplate != null) { + parentPolicyType = getParentPolicyType(parentId, parentTemplate); + if (parentPolicyType != null) { + toscaProperty = parentPolicyType.getProperties().get(propertyName); + if (toscaProperty != null) { + return Pair.of(toscaProperty, parentTemplate); + } + } + // + // Move to the next parent + // + parentId = getParentDerivedFrom(parentId, parentTemplate); + } else { + LOGGER.error("Unable to find/pull parent policy type {}", parentId); + parentId = null; } } } - LOGGER.info("isMatchable false for {}", propertyName); - return false; + LOGGER.warn("Property {} is NOT found in any template", propertyName); + return null; } - private boolean isListOrMap(String type) { - return "list".equalsIgnoreCase(type) || "map".equalsIgnoreCase(type); + private ToscaPolicyType getToscaPolicyTypeFromTemplate(ToscaPolicyTypeIdentifier propertiesPolicyId, + ToscaServiceTemplate policyTemplate) { + for (Entry<String, ToscaPolicyType> entry : policyTemplate.getPolicyTypes().entrySet()) { + if (propertiesPolicyId.getName().equals(entry.getKey()) + && propertiesPolicyId.getVersion().equals(entry.getValue().getVersion())) { + return entry.getValue(); + } + } + return null; } private boolean isYamlType(String type) { @@ -425,21 +640,18 @@ public class StdMatchableTranslator extends StdBaseTranslator { } /** - * checkIsMatchableProperty - checks the policy contents for matchable field. If the metadata doesn't exist, - * then definitely not. If the property doesn't exist, then definitely not. Otherwise need to have a metadata - * section with the matchable property set to true. + * checkIsMatchableProperty - checks the property metadata to see if matchable exists. * - * @param propertyName String value of property - * @param propertiesEntry Section of the TOSCA Policy Type where properties and metadata sections are held + * @param toscaProperty ToscaProperty * @return true if matchable */ - protected boolean checkIsMatchableProperty(String propertyName, Entry<String, ToscaProperty> propertiesEntry) { - if (! propertiesEntry.getKey().equals(propertyName) - || propertiesEntry.getValue().getMetadata() == null) { + protected boolean checkIsMatchableProperty(ToscaProperty toscaProperty) { + if (toscaProperty.getMetadata() == null) { return false; } - for (Entry<String, String> entrySet : propertiesEntry.getValue().getMetadata().entrySet()) { + for (Entry<String, String> entrySet : toscaProperty.getMetadata().entrySet()) { if ("matchable".equals(entrySet.getKey()) && "true".equals(entrySet.getValue())) { + LOGGER.debug("found matchable of type {}", toscaProperty.getType()); return true; } } @@ -454,12 +666,43 @@ public class StdMatchableTranslator extends StdBaseTranslator { * @param targetType TargetType object to add matches to * @param key Property key * @param value Object is the value - which can be a Collection or single Object + * @param toscaProperty The property that was found + * @param toscaServiceTemplate The template from which the property was found * @return int Weight of the match. */ - @SuppressWarnings("unchecked") - protected int generateMatchable(TargetType targetType, String key, Object value) { + protected int generateMatchable(TargetType targetType, String key, Object value, ToscaProperty toscaProperty, + ToscaServiceTemplate toscaServiceTemplate) { int weight = 0; if (value instanceof Collection) { + // + // Further determine how we treat this collection. We will need the schema + // if it is not available then we have to bail. + // + if (toscaProperty.getEntrySchema() == null) { + LOGGER.error("No schema for property {} of type {}", key, toscaProperty.getType()); + } + if ("list".equals(toscaProperty.getType())) { + return generateMatchableList(targetType, key, value, toscaProperty, toscaServiceTemplate); + } + if ("map".equals(toscaProperty.getType())) { + return generateMatchableMap(targetType, key, value, toscaProperty, toscaServiceTemplate); + } + } else { + AnyOfType anyOf = generateMatches(Arrays.asList(value), + new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + key)); + if (! anyOf.getAllOf().isEmpty()) { + targetType.getAnyOf().add(anyOf); + weight = 1; + } + } + return weight; + } + + @SuppressWarnings("unchecked") + protected int generateMatchableList(TargetType targetType, String key, Object value, ToscaProperty toscaProperty, + ToscaServiceTemplate toscaServiceTemplate) { + int weight = 0; + if (isYamlType(toscaProperty.getEntrySchema().getType())) { AnyOfType anyOf = generateMatches((Collection<Object>) value, new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + key)); if (! anyOf.getAllOf().isEmpty()) { @@ -467,12 +710,27 @@ public class StdMatchableTranslator extends StdBaseTranslator { weight = 1; } } else { - AnyOfType anyOf = generateMatches(Arrays.asList(value), + LOGGER.debug("PLD use datatype for list?"); + } + return weight; + } + + @SuppressWarnings("unchecked") + protected int generateMatchableMap(TargetType targetType, String key, Object value, ToscaProperty toscaProperty, + ToscaServiceTemplate toscaServiceTemplate) { + int weight = 0; + if (isYamlType(toscaProperty.getEntrySchema().getType())) { + // + // PLD TODO - this won't work + // + AnyOfType anyOf = generateMatches((Collection<Object>) value, new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + key)); if (! anyOf.getAllOf().isEmpty()) { targetType.getAnyOf().add(anyOf); weight = 1; } + } else { + LOGGER.debug("PLD use datatype for map?"); } return weight; } @@ -530,73 +788,29 @@ public class StdMatchableTranslator extends StdBaseTranslator { return anyOf; } - /** - * Get Policy Type definitions. This could be previously loaded, or could be - * stored in application path, or may need to be pulled from the API. - * - * - * @param policyTypeId Policy Type Id - * @return A list of PolicyTypes - */ - private List<ToscaPolicyType> getPolicyTypes(ToscaPolicyTypeIdentifier policyTypeId) { - // - // Create identifier from the policy - // - ToscaPolicyTypeIdentifier typeId = new ToscaPolicyTypeIdentifier(policyTypeId); - // - // Find the Policy Type - // - ToscaPolicyType policyType = findPolicyType(typeId); - if (policyType == null) { - return Collections.emptyList(); + private ToscaPolicyTypeIdentifier getParentDerivedFrom(ToscaPolicyTypeIdentifier policyTypeId, + ToscaServiceTemplate template) { + for (Entry<String, ToscaPolicyType> entrySet : template.getPolicyTypes().entrySet()) { + ToscaPolicyType policyType = entrySet.getValue(); + if (entrySet.getKey().equals(policyTypeId.getName()) + && policyType.getVersion().equals(policyTypeId.getVersion()) + && ! "tosca.policies.Root".equals(policyType.getDerivedFrom())) { + return new ToscaPolicyTypeIdentifier(policyType.getDerivedFrom(), "1.0.0"); + } } - // - // Create our return object - // - List<ToscaPolicyType> listTypes = new ArrayList<>(); - listTypes.add(policyType); - // - // Look for parent policy types that could also contain matchable properties - // - ToscaPolicyType childPolicyType = policyType; - while (! childPolicyType.getDerivedFrom().startsWith("tosca.policies.Root")) { - // - // Create parent policy type id. - // - // We will have to assume the same version between child and the - // parent policy type it derives from. - // - // Or do we assume 1.0.0? - // - ToscaPolicyTypeIdentifier parentId = new ToscaPolicyTypeIdentifier(childPolicyType.getDerivedFrom(), - "1.0.0"); - // - // Find the policy type - // - ToscaPolicyType parentPolicyType = findPolicyType(parentId); - if (parentPolicyType == null) { - // - // Probably would be best to throw an exception and - // return nothing back. - // - // But instead we will log a warning - // - LOGGER.warn("Missing parent policy type - proceeding anyway {}", parentId); - // - // Break the loop - // - break; + + return null; + } + + private ToscaPolicyType getParentPolicyType(ToscaPolicyTypeIdentifier policyTypeId, ToscaServiceTemplate template) { + for (Entry<String, ToscaPolicyType> entrySet : template.getPolicyTypes().entrySet()) { + ToscaPolicyType policyType = entrySet.getValue(); + if (entrySet.getKey().equals(policyTypeId.getName()) + && policyType.getVersion().equals(policyTypeId.getVersion())) { + return policyType; } - // - // Great save it - // - listTypes.add(parentPolicyType); - // - // Move to the next parent - // - childPolicyType = parentPolicyType; } - return listTypes; + return null; } /** @@ -607,21 +821,27 @@ public class StdMatchableTranslator extends StdBaseTranslator { * @param policyTypeId ToscaPolicyTypeIdentifier to find * @return ToscaPolicyType object. Can be null if failure. */ - private ToscaPolicyType findPolicyType(ToscaPolicyTypeIdentifier policyTypeId) { + private ToscaServiceTemplate findPolicyType(ToscaPolicyTypeIdentifier policyTypeId) { // // Is it loaded in memory? // - ToscaPolicyType policyType = this.matchablePolicyTypes.get(policyTypeId); - if (policyType == null) { + ToscaServiceTemplate policyTemplate = this.matchablePolicyTypes.get(policyTypeId); + if (policyTemplate == null) { // // Load the policy // - policyType = this.loadPolicyType(policyTypeId); + policyTemplate = this.loadPolicyType(policyTypeId); + // + // Save it + // + if (policyTemplate != null) { + this.matchablePolicyTypes.put(policyTypeId, policyTemplate); + } } // // Yep return it // - return policyType; + return policyTemplate; } /** @@ -632,7 +852,7 @@ public class StdMatchableTranslator extends StdBaseTranslator { * @param policyTypeId ToscaPolicyTypeIdentifier input * @return ToscaPolicyType object. Null if failure. */ - private ToscaPolicyType loadPolicyType(ToscaPolicyTypeIdentifier policyTypeId) { + private ToscaServiceTemplate loadPolicyType(ToscaPolicyTypeIdentifier policyTypeId) { // // Construct what the file name should be // @@ -662,34 +882,8 @@ public class StdMatchableTranslator extends StdBaseTranslator { // LOGGER.info("Read in local policy type {}", policyTypePath.toAbsolutePath()); try { - ToscaServiceTemplate serviceTemplate = standardYamlCoder.decode(new String(bytes, StandardCharsets.UTF_8), + return standardYamlCoder.decode(new String(bytes, StandardCharsets.UTF_8), ToscaServiceTemplate.class); - JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate(); - jtst.fromAuthorative(serviceTemplate); - ToscaServiceTemplate completedJtst = jtst.toAuthorative(); - // - // Search for our Policy Type, there really only should be one but - // this is returned as a map. - // - for ( Entry<String, ToscaPolicyType> entrySet : completedJtst.getPolicyTypes().entrySet()) { - ToscaPolicyType entryPolicyType = entrySet.getValue(); - if (policyTypeId.getName().equals(entryPolicyType.getName()) - && policyTypeId.getVersion().equals(entryPolicyType.getVersion())) { - LOGGER.info("Found existing local policy type {} {}", entryPolicyType.getName(), - entryPolicyType.getVersion()); - // - // Just simply return the policy type right here - // - return entryPolicyType; - } else { - LOGGER.warn("local policy type contains different name version {} {}", entryPolicyType.getName(), - entryPolicyType.getVersion()); - } - } - // - // This would be an error, if the file stored does not match what its supposed to be - // - LOGGER.error("Existing policy type file does not contain right name and version"); } catch (CoderException e) { LOGGER.error("Failed to decode tosca template for {}", policyTypePath, e); } @@ -708,15 +902,16 @@ public class StdMatchableTranslator extends StdBaseTranslator { * @param policyTypePath Path object to store locally * @return ToscaPolicyType object. Null if failure. */ - private synchronized ToscaPolicyType pullPolicyType(ToscaPolicyTypeIdentifier policyTypeId, Path policyTypePath) { + private synchronized ToscaServiceTemplate pullPolicyType(ToscaPolicyTypeIdentifier policyTypeId, + Path policyTypePath) { // // This is what we return // - ToscaPolicyType policyType = null; + ToscaServiceTemplate policyTemplate = null; try { PolicyApiCaller api = new PolicyApiCaller(this.apiRestParameters); - policyType = api.getPolicyType(policyTypeId); + policyTemplate = api.getPolicyType(policyTypeId); } catch (PolicyApiException e) { LOGGER.error("Failed to make API call", e); LOGGER.error("parameters: {} ", this.apiRestParameters); @@ -727,14 +922,14 @@ public class StdMatchableTranslator extends StdBaseTranslator { // Store it locally // try { - standardYamlCoder.encode(policyTypePath.toFile(), policyType); + standardYamlCoder.encode(policyTypePath.toFile(), policyTemplate); } catch (CoderException e) { LOGGER.error("Failed to store {} locally to {}", policyTypeId, policyTypePath, e); } // // Done return the policy type // - return policyType; + return policyTemplate; } /** diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java index e9e8814c..aeb4cf88 100644 --- a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java +++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -70,7 +70,6 @@ import org.onap.policy.common.utils.resources.ResourceUtils; import org.onap.policy.models.decisions.concepts.DecisionRequest; import org.onap.policy.models.decisions.concepts.DecisionResponse; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; -import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate; import org.onap.policy.pdp.xacml.application.common.TestUtilsCommon; @@ -87,7 +86,7 @@ public class StdMatchableTranslatorTest { private static final StandardYamlCoder yamlCoder = new StandardYamlCoder(); private static int port; private static RestServerParameters clientParams; - private static ToscaPolicyType testPolicyType; + private static ToscaServiceTemplate testTemplate; @ClassRule public static final TemporaryFolder policyFolder = new TemporaryFolder(); @@ -144,14 +143,15 @@ public class StdMatchableTranslatorTest { // JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate(); jtst.fromAuthorative(serviceTemplate); - ToscaServiceTemplate completedJtst = jtst.toAuthorative(); + testTemplate = jtst.toAuthorative(); // - // Find the Policy Type - SHOULD only be one + // Make sure the Policy Types are there // - assertEquals(1, completedJtst.getPolicyTypes().size()); - testPolicyType = completedJtst.getPolicyTypes().get("onap.policies.Test"); - assertNotNull(testPolicyType); - logger.info("Test Policy Type {}{}", XacmlPolicyUtils.LINE_SEPARATOR, testPolicyType); + assertEquals(3, testTemplate.getPolicyTypes().size()); + assertNotNull(testTemplate.getPolicyTypes().get("onap.policies.Base")); + assertNotNull(testTemplate.getPolicyTypes().get("onap.policies.base.Middle")); + assertNotNull(testTemplate.getPolicyTypes().get("onap.policies.base.middle.Test")); + logger.info("Test Policy Type {}{}", XacmlPolicyUtils.LINE_SEPARATOR, testTemplate); } @AfterClass @@ -191,6 +191,9 @@ public class StdMatchableTranslatorTest { // for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) { for (ToscaPolicy policy : policies.values()) { + // + // Test that we can convert the policy + // PolicyType translatedPolicy = translator.convertPolicy(policy); assertNotNull(translatedPolicy); assertThat(translatedPolicy.getObligationExpressions().getObligationExpression()).hasSize(1); @@ -282,7 +285,7 @@ public class StdMatchableTranslatorTest { public Response getSpecificVersionOfPolicyType(@PathParam("policyTypeId") String policyTypeId, @PathParam("versionId") String versionId, @HeaderParam("X-ONAP-RequestID") UUID requestId) { logger.info("request for policy type={} version={}", policyTypeId, versionId); - return Response.status(Response.Status.OK).entity(testPolicyType).build(); + return Response.status(Response.Status.OK).entity(testTemplate).build(); } } diff --git a/applications/common/src/test/resources/matchable/onap.policies.Test-1.0.0.yaml b/applications/common/src/test/resources/matchable/onap.policies.Test-1.0.0.yaml index f44a3061..7179c310 100644 --- a/applications/common/src/test/resources/matchable/onap.policies.Test-1.0.0.yaml +++ b/applications/common/src/test/resources/matchable/onap.policies.Test-1.0.0.yaml @@ -1,9 +1,30 @@ tosca_definitions_version: tosca_simple_yaml_1_0_0 policy_types: - onap.policies.Test: + onap.policies.Base: derived_from: tosca.policies.Root version: 1.0.0 properties: + baseNoMatch: + type: string + baseMatch: + type: string + metadata: + matchable: true + onap.policies.base.Middle: + derived_from: onap.policies.Base + version: 1.0.0 + properties: + middleNoMatch: + type: string + middleMatch: + type: string + metadata: + matchable: true + onap.policies.base.middle.Test: + derived_from: onap.policies.base.Middle + type_version: 1.0.0 + version: 1.0.0 + properties: nonmatachableString: type: string matchableString: @@ -30,6 +51,10 @@ policy_types: type: boolean metadata: matchable: true + nonmatchableListInteger: + type: list + entry_schema: + type: integer matchableListString: type: list metadata: @@ -39,7 +64,7 @@ policy_types: propertyOneMap: type: map entry_schema: - type: onap.datatype.level1 + type: onap.datatype.one data_types: onap.datatype.one: derived_from: tosca.datatypes.Root @@ -49,7 +74,7 @@ data_types: oneStringMatchable: type: string metadata: - matachable: true + matchable: true propertyTwoList: type: list entry_schema: @@ -62,7 +87,7 @@ data_types: twoStringMatchable: type: string metadata: - matachable: true + matchable: true propertyThreeMap: type: map entry_schema: @@ -75,4 +100,4 @@ data_types: threeStringMatchable: type: string metadata: - matachable: true
\ No newline at end of file + matchable: true
\ No newline at end of file diff --git a/applications/common/src/test/resources/matchable/test.policies.input.tosca.yaml b/applications/common/src/test/resources/matchable/test.policies.input.tosca.yaml index 9a68d488..80f72b2f 100644 --- a/applications/common/src/test/resources/matchable/test.policies.input.tosca.yaml +++ b/applications/common/src/test/resources/matchable/test.policies.input.tosca.yaml @@ -2,13 +2,17 @@ tosca_definitions_version: tosca_simple_yaml_1_0_0 topology_template: policies: - Test.policy: - type: onap.policies.Test + type: onap.policies.base.middle.Test type_version: 1.0.0 version: 1.0.0 metadata: policy-id: Test.policy policy-version: 1 properties: + baseNoMatch: Do not match the base + baseMatch: base Match + middleNoMatch: Do not match the middle + middleMatch: middle Match nonmatachableString: I am NON matchable matchableString: I should be matched nonmatachableInteger: 0 @@ -17,6 +21,7 @@ topology_template: matchableFloat: 1.1 nonmatachableBoolean: false matachableBoolean: true + nonmatchableListInteger: {0, 1, 2} matchableListString: - match A - match B @@ -25,7 +30,7 @@ topology_template: oneStringMatchable: One should be matched propertyTwoList: - twoString: Two is NOT matchable - twoStringMatachable: Two should be matched + twoStringMatchable: Two should be matched propertyThreeMap: threeString: Three is NOT matchable threeStringMatchable: Three should be matched
\ No newline at end of file diff --git a/applications/naming/src/main/java/org/onap/policy/xacml/pdp/application/naming/NamingPdpApplication.java b/applications/naming/src/main/java/org/onap/policy/xacml/pdp/application/naming/NamingPdpApplication.java index d04fca6a..5d45bfc5 100644 --- a/applications/naming/src/main/java/org/onap/policy/xacml/pdp/application/naming/NamingPdpApplication.java +++ b/applications/naming/src/main/java/org/onap/policy/xacml/pdp/application/naming/NamingPdpApplication.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,14 +22,11 @@ package org.onap.policy.xacml.pdp.application.naming; -import java.nio.file.Path; import java.util.Arrays; import java.util.List; -import org.onap.policy.common.endpoints.parameters.RestServerParameters; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier; import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator; -import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException; -import org.onap.policy.pdp.xacml.application.common.std.StdMatchableTranslator; +import org.onap.policy.pdp.xacml.application.common.std.StdCombinedPolicyResultsTranslator; import org.onap.policy.pdp.xacml.application.common.std.StdXacmlApplicationServiceProvider; public class NamingPdpApplication extends StdXacmlApplicationServiceProvider { @@ -37,7 +34,7 @@ public class NamingPdpApplication extends StdXacmlApplicationServiceProvider { private static final ToscaPolicyTypeIdentifier supportedPolicy = new ToscaPolicyTypeIdentifier( "onap.policies.Naming", "1.0.0"); - private StdMatchableTranslator translator = new StdMatchableTranslator(); + private StdCombinedPolicyResultsTranslator translator = new StdCombinedPolicyResultsTranslator(); @Override public String applicationName() { @@ -50,21 +47,6 @@ public class NamingPdpApplication extends StdXacmlApplicationServiceProvider { } @Override - public void initialize(Path pathForData, RestServerParameters policyApiParameters) - throws XacmlApplicationException { - // - // Store our API parameters and path for translator so it - // can go get Policy Types - // - this.translator.setPathForData(pathForData); - this.translator.setApiRestParameters(policyApiParameters); - // - // Let our super class do its thing - // - super.initialize(pathForData, policyApiParameters); - } - - @Override public synchronized List<ToscaPolicyTypeIdentifier> supportedPolicyTypes() { return Arrays.asList(supportedPolicy); } diff --git a/applications/naming/src/test/java/org/onap/policy/xacml/pdp/application/naming/NamingPdpApplicationTest.java b/applications/naming/src/test/java/org/onap/policy/xacml/pdp/application/naming/NamingPdpApplicationTest.java index 02884b63..0077d0b9 100644 --- a/applications/naming/src/test/java/org/onap/policy/xacml/pdp/application/naming/NamingPdpApplicationTest.java +++ b/applications/naming/src/test/java/org/onap/policy/xacml/pdp/application/naming/NamingPdpApplicationTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,6 +32,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.Map; @@ -42,8 +43,10 @@ import org.apache.commons.lang3.tuple.Pair; import org.assertj.core.api.Condition; 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.endpoints.parameters.RestServerParameters; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; @@ -59,6 +62,7 @@ import org.onap.policy.pdp.xacml.xacmltest.TestUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class NamingPdpApplicationTest { private static final Logger LOGGER = LoggerFactory.getLogger(NamingPdpApplicationTest.class); private static Properties properties = new Properties(); @@ -92,7 +96,6 @@ public class NamingPdpApplicationTest { // // Setup our temporary folder // - // TODO use lambda policyFolder::newFile XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename); propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties", properties, myCreator); @@ -102,7 +105,6 @@ public class NamingPdpApplicationTest { String policy = "onap.policies.Naming"; String policyType = ResourceUtils.getResourceAsString("policytypes/" + policy + ".yaml"); LOGGER.info("Copying {}", policyType); - // TODO investigate UTF-8 Files.write(Paths.get(policyFolder.getRoot().getAbsolutePath(), policy + "-1.0.0.yaml"), policyType.getBytes()); // @@ -188,7 +190,19 @@ public class NamingPdpApplicationTest { // Ask for a decision for available default policies // DecisionResponse response = makeDecision(); - + // + // There is no default policy + // + assertThat(response).isNotNull(); + assertThat(response.getPolicies().size()).isEqualTo(0); + // + // Ask for VNF + // + baseRequest.getResource().put("policy-type", Arrays.asList("onap.policies.Naming")); + // + // Ask for a decision for VNF default policies + // + response = makeDecision(); assertThat(response).isNotNull(); assertThat(response.getPolicies().size()).isEqualTo(1); // |