2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
 
   6    Modifications Copyright (C) 2019-2020 Nordix Foundation.
 
   7  * ================================================================================
 
   8  * Licensed under the Apache License, Version 2.0 (the "License");
 
   9  * you may not use this file except in compliance with the License.
 
  10  * You may obtain a copy of the License at
 
  12  *      http://www.apache.org/licenses/LICENSE-2.0
 
  14  * Unless required by applicable law or agreed to in writing, software
 
  15  * distributed under the License is distributed on an "AS IS" BASIS,
 
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  17  * See the License for the specific language governing permissions and
 
  18  * limitations under the License.
 
  20  * SPDX-License-Identifier: Apache-2.0
 
  21  * ============LICENSE_END=========================================================
 
  24 package org.onap.policy.xacml.pdp.application.optimization;
 
  26 import static org.assertj.core.api.Assertions.assertThat;
 
  27 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 
  28 import static org.mockito.Mockito.mock;
 
  29 import static org.mockito.Mockito.when;
 
  31 import com.att.research.xacml.api.Response;
 
  32 import com.google.common.collect.Lists;
 
  34 import java.nio.file.Files;
 
  35 import java.nio.file.Paths;
 
  36 import java.util.Collection;
 
  37 import java.util.Iterator;
 
  38 import java.util.List;
 
  40 import java.util.Map.Entry;
 
  41 import java.util.Properties;
 
  42 import java.util.ServiceLoader;
 
  43 import org.apache.commons.lang3.tuple.Pair;
 
  44 import org.assertj.core.api.Condition;
 
  45 import org.junit.BeforeClass;
 
  46 import org.junit.ClassRule;
 
  47 import org.junit.FixMethodOrder;
 
  48 import org.junit.Test;
 
  49 import org.junit.rules.TemporaryFolder;
 
  50 import org.junit.runners.MethodSorters;
 
  51 import org.onap.policy.common.endpoints.parameters.RestServerParameters;
 
  52 import org.onap.policy.common.utils.coder.CoderException;
 
  53 import org.onap.policy.common.utils.coder.StandardCoder;
 
  54 import org.onap.policy.common.utils.coder.StandardYamlCoder;
 
  55 import org.onap.policy.common.utils.resources.ResourceUtils;
 
  56 import org.onap.policy.common.utils.resources.TextFileUtils;
 
  57 import org.onap.policy.models.decisions.concepts.DecisionRequest;
 
  58 import org.onap.policy.models.decisions.concepts.DecisionResponse;
 
  59 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
 
  60 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
 
  61 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
 
  62 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
 
  63 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
 
  64 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
 
  65 import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
 
  66 import org.onap.policy.pdp.xacml.xacmltest.TestUtils;
 
  67 import org.slf4j.Logger;
 
  68 import org.slf4j.LoggerFactory;
 
  70 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 
  71 public class OptimizationPdpApplicationTest {
 
  73     private static final Logger LOGGER = LoggerFactory.getLogger(OptimizationPdpApplicationTest.class);
 
  74     private static Properties properties = new Properties();
 
  75     private static File propertiesFile;
 
  76     private static XacmlApplicationServiceProvider service;
 
  77     private static StandardCoder gson = new StandardCoder();
 
  78     private static DecisionRequest baseRequest;
 
  79     private static RestServerParameters clientParams;
 
  80     private static String[] listPolicyTypeFiles = {
 
  81         "onap.policies.Optimization",
 
  82         "onap.policies.optimization.Resource",
 
  83         "onap.policies.optimization.Service",
 
  84         "onap.policies.optimization.resource.AffinityPolicy",
 
  85         "onap.policies.optimization.resource.DistancePolicy",
 
  86         "onap.policies.optimization.resource.HpaPolicy",
 
  87         "onap.policies.optimization.resource.OptimizationPolicy",
 
  88         "onap.policies.optimization.resource.PciPolicy",
 
  89         "onap.policies.optimization.service.QueryPolicy",
 
  90         "onap.policies.optimization.service.SubscriberPolicy",
 
  91         "onap.policies.optimization.resource.Vim_fit",
 
  92         "onap.policies.optimization.resource.VnfPolicy"};
 
  95     public static final TemporaryFolder policyFolder = new TemporaryFolder();
 
  98      * Copies the xacml.properties and policies files into
 
  99      * temporary folder and loads the service provider saving
 
 100      * instance of provider off for other tests to use.
 
 103     public static void setUp() throws Exception {
 
 104         clientParams = mock(RestServerParameters.class);
 
 105         when(clientParams.getHost()).thenReturn("localhost");
 
 106         when(clientParams.getPort()).thenReturn(6969);
 
 108         // Load Single Decision Request
 
 110         baseRequest = gson.decode(
 
 112                     .getTextFileAsString(
 
 113                             "src/test/resources/decision.optimization.input.json"),
 
 114                     DecisionRequest.class);
 
 116         // Setup our temporary folder
 
 118         XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename);
 
 119         propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties",
 
 120                 properties, myCreator);
 
 122         // Copy the test policy types into data area
 
 124         for (String policy : listPolicyTypeFiles) {
 
 125             String policyType = ResourceUtils.getResourceAsString("policytypes/" + policy + ".yaml");
 
 126             LOGGER.info("Copying {}", policyType);
 
 127             Files.write(Paths.get(policyFolder.getRoot().getAbsolutePath(), policy + "-1.0.0.yaml"),
 
 128                     policyType.getBytes());
 
 133         ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
 
 134                 ServiceLoader.load(XacmlApplicationServiceProvider.class);
 
 136         // Iterate through Xacml application services and find
 
 137         // the optimization service. Save it for use throughout
 
 138         // all the Junit tests.
 
 140         StringBuilder strDump = new StringBuilder("Loaded applications:" + XacmlPolicyUtils.LINE_SEPARATOR);
 
 141         Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
 
 142         while (iterator.hasNext()) {
 
 143             XacmlApplicationServiceProvider application = iterator.next();
 
 145             // Is it our service?
 
 147             if (application instanceof OptimizationPdpApplication) {
 
 149                 // Should be the first and only one
 
 151                 assertThat(service).isNull();
 
 152                 service = application;
 
 154             strDump.append(application.applicationName());
 
 155             strDump.append(" supports ");
 
 156             strDump.append(application.supportedPolicyTypes());
 
 157             strDump.append(XacmlPolicyUtils.LINE_SEPARATOR);
 
 159         LOGGER.debug("{}", strDump);
 
 160         assertThat(service).isNotNull();
 
 162         // Tell it to initialize based on the properties file
 
 163         // we just built for it.
 
 165         service.initialize(propertiesFile.toPath().getParent(), clientParams);
 
 169      * Simply test some of the simple methods for the application.
 
 172     public void test01Basics() {
 
 174         // Make sure there's an application name
 
 176         assertThat(service.applicationName()).isNotEmpty();
 
 178         // Does it return the correct decisions
 
 180         assertThat(service.actionDecisionsSupported().size()).isEqualTo(1);
 
 181         assertThat(service.actionDecisionsSupported()).contains("optimize");
 
 183         // Ensure it has the supported policy types and
 
 184         // can support the correct policy types.
 
 186         assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
 
 187                 "onap.policies.optimization.resource.AffinityPolicy", "1.0.0"))).isTrue();
 
 188         assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
 
 189                 "onap.policies.optimization.service.SubscriberPolicy", "1.0.0"))).isTrue();
 
 190         assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
 
 191                 "onap.policies.optimization.service.CustomUseCase", "1.0.0"))).isTrue();
 
 192         assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
 
 193                 "onap.foobar", "1.0.0"))).isFalse();
 
 197      * With no policies loaded, there should be 0 policies returned.
 
 199      * @throws CoderException CoderException
 
 202     public void test02NoPolicies() throws CoderException {
 
 204         // Ask for a decision when there are no policies loaded
 
 206         LOGGER.info("Request {}", gson.encode(baseRequest));
 
 207         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
 
 208         LOGGER.info("Decision {}", decision.getKey());
 
 210         assertThat(decision.getKey()).isNotNull();
 
 211         assertThat(decision.getKey().getPolicies()).isEmpty();
 
 215      * Should return ONLY default policies.
 
 217      * @throws XacmlApplicationException could not load policies
 
 220     public void test03OptimizationDefault() throws XacmlApplicationException {
 
 222         // Now load all the optimization policies
 
 224         List<ToscaPolicy> loadedPolicies = TestUtils.loadPolicies("src/test/resources/test-optimization-policies.yaml",
 
 226         assertThat(loadedPolicies).isNotNull().hasSize(14);
 
 228         // Ask for a decision for available default policies
 
 230         DecisionResponse response = makeDecision();
 
 232         assertThat(response).isNotNull();
 
 233         assertThat(response.getPolicies()).hasSize(2);
 
 237         validateDecision(response, baseRequest);
 
 241      * Should only return default HPA policy type.
 
 243     @SuppressWarnings("unchecked")
 
 245     public void test04OptimizationDefaultHpa() {
 
 247         // Add in policy type
 
 249         List<String> policyTypes = Lists.newArrayList("onap.policies.optimization.resource.HpaPolicy");
 
 250         baseRequest.getResource().put("policy-type", policyTypes);
 
 252         // Ask for a decision for default HPA policy
 
 254         DecisionResponse response = makeDecision();
 
 256         assertThat(response).isNotNull();
 
 257         assertThat(response.getPolicies()).hasSize(1);
 
 258         response.getPolicies().forEach((key, value) -> {
 
 259             assertThat(((Map<String, Object>) value)).containsEntry("type",
 
 260                             "onap.policies.optimization.resource.HpaPolicy");
 
 265         validateDecision(response, baseRequest);
 
 269      * Refine for US only policies.
 
 271     @SuppressWarnings("unchecked")
 
 273     public void test05OptimizationDefaultGeography() throws CoderException {
 
 275         // Remove all the policy-type resources from the request
 
 279         // Add US to the geography list
 
 281         ((List<String>) baseRequest.getResource().get("geography")).add("US");
 
 283         // Ask for a decision for default US Policy
 
 285         DecisionResponse response = makeDecision();
 
 286         assertThat(response).isNotNull();
 
 287         assertThat(response.getPolicies()).hasSize(2);
 
 291         validateDecision(response, baseRequest);
 
 295      * Add more refinement for service.
 
 297     @SuppressWarnings("unchecked")
 
 299     public void test06OptimizationDefaultGeographyAndService() {
 
 301         // Add vCPE to the service list
 
 303         ((List<String>) baseRequest.getResource().get("services")).add("vCPE");
 
 305         // Ask for a decision for default US policy for vCPE service
 
 307         DecisionResponse response = makeDecision();
 
 309         assertThat(response).isNotNull();
 
 310         assertThat(response.getPolicies()).hasSize(3);
 
 314         validateDecision(response, baseRequest);
 
 318      * Add more refinement for specific resource.
 
 320     @SuppressWarnings("unchecked")
 
 322     public void test07OptimizationDefaultGeographyAndServiceAndResource() {
 
 324         // Add vG to the resource list
 
 326         ((List<String>) baseRequest.getResource().get("resources")).add("vG");
 
 328         // Ask for a decision for default US service vCPE resource vG policy
 
 330         DecisionResponse response = makeDecision();
 
 332         assertThat(response).isNotNull();
 
 333         assertThat(response.getPolicies()).hasSize(6);
 
 337         validateDecision(response, baseRequest);
 
 341      * Now we need to add in subscriberName in order to get scope for gold.
 
 343     @SuppressWarnings("unchecked")
 
 345     public void test08OptimizationGeographyAndServiceAndResourceAndScopeIsGoldSubscriber() {
 
 347         // Add gold as a scope
 
 349         ((List<String>) baseRequest.getContext().get("subscriberName")).add("subscriber_a");
 
 351         // Ask for a decision for specific US vCPE vG gold
 
 353         DecisionResponse response = makeDecision();
 
 355         assertThat(response).isNotNull();
 
 356         assertThat(response.getPolicies()).hasSize(6);
 
 357         assertThat(response.getAdvice()).hasSize(2);
 
 361         validateDecision(response, baseRequest);
 
 365      * Add a subscriber that should be platinum.
 
 367     @SuppressWarnings("unchecked")
 
 369     public void test09OptimizationGeographyAndServiceAndResourceAndScopeGoldOrPlatinumSubscriber() {
 
 371         // Add platinum to the scope list: this is now gold OR platinum
 
 373         ((List<String>) baseRequest.getResource().get("scope")).remove("gold");
 
 374         ((List<String>) baseRequest.getContext().get("subscriberName")).add("subscriber_x");
 
 376         // Ask for a decision for specific US vCPE vG (gold or platinum)
 
 378         DecisionResponse response = makeDecision();
 
 380         assertThat(response).isNotNull();
 
 381         assertThat(response.getPolicies()).hasSize(8);
 
 382         assertThat(response.getAdvice()).hasSize(2);
 
 386         validateDecision(response, baseRequest);
 
 390      * Remove gold subscriber, keep the platinum one.
 
 392     @SuppressWarnings("unchecked")
 
 394     public void test10OptimizationGeographyAndServiceAndResourceAndScopeNotGoldStillPlatinum() {
 
 396         // Add gold as a scope
 
 398         ((List<String>) baseRequest.getResource().get("scope")).remove("gold");
 
 399         ((List<String>) baseRequest.getResource().get("scope")).remove("platinum");
 
 400         ((List<String>) baseRequest.getContext().get("subscriberName")).remove("subscriber_a");
 
 402         // Ask for a decision for specific US vCPE vG gold
 
 404         DecisionResponse response = makeDecision();
 
 406         assertThat(response).isNotNull();
 
 407         assertThat(response.getPolicies()).hasSize(7);
 
 411         validateDecision(response, baseRequest);
 
 415      * Filter by Affinity policy.
 
 418     public void test11OptimizationPolicyTypeDefault() {
 
 420         // Add in policy type
 
 422         List<String> policyTypes = Lists.newArrayList("onap.policies.optimization.resource.AffinityPolicy");
 
 423         baseRequest.getResource().put("policy-type", policyTypes);
 
 425         // Ask for a decision for default
 
 427         DecisionResponse response = makeDecision();
 
 429         assertThat(response).isNotNull();
 
 430         assertThat(response.getPolicies()).hasSize(1);
 
 434         validateDecision(response, baseRequest);
 
 438      * Now filter by HPA policy type.
 
 440     @SuppressWarnings("unchecked")
 
 442     public void test12OptimizationPolicyTypeDefault() {
 
 444         // Add in another policy type
 
 446         ((List<String>) baseRequest.getResource().get("policy-type"))
 
 447             .add("onap.policies.optimization.resource.HpaPolicy");
 
 449         // Ask for a decision for default
 
 451         DecisionResponse response = makeDecision();
 
 453         assertThat(response).isNotNull();
 
 454         assertThat(response.getPolicies()).hasSize(2);
 
 458         validateDecision(response, baseRequest);
 
 462     public void test999BadSubscriberPolicies() throws Exception {
 
 463         final StandardYamlCoder yamlCoder = new StandardYamlCoder();
 
 467         String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/bad-subscriber-policies.yaml");
 
 469         // Serialize it into a class
 
 471         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
 
 472         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
 
 473         jtst.fromAuthorative(serviceTemplate);
 
 475         // Make sure all the fields are setup properly
 
 477         ToscaServiceTemplate completedJtst = jtst.toAuthorative();
 
 481         for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
 
 482             for (ToscaPolicy policy : policies.values()) {
 
 483                 if ("missing-subscriberProperties".equals(policy.getName())) {
 
 484                     assertThatExceptionOfType(XacmlApplicationException.class).isThrownBy(() ->
 
 485                         service.loadPolicy(policy));
 
 486                 } else if ("missing-subscriberName".equals(policy.getName())) {
 
 487                     assertThatExceptionOfType(XacmlApplicationException.class).isThrownBy(() ->
 
 488                         service.loadPolicy(policy));
 
 489                 } else if ("missing-subscriberRole".equals(policy.getName())) {
 
 490                     assertThatExceptionOfType(XacmlApplicationException.class).isThrownBy(() ->
 
 491                         service.loadPolicy(policy));
 
 497     private DecisionResponse makeDecision() {
 
 498         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
 
 499         LOGGER.info("Request Resources {}", baseRequest.getResource());
 
 500         LOGGER.info("Decision {}", decision.getKey());
 
 501         for (Entry<String, Object> entrySet : decision.getKey().getPolicies().entrySet()) {
 
 502             LOGGER.info("Policy {}", entrySet.getKey());
 
 504         return decision.getKey();
 
 507     @SuppressWarnings("unchecked")
 
 508     private void validateDecision(DecisionResponse decision, DecisionRequest request) {
 
 509         for (Entry<String, Object> entrySet : decision.getPolicies().entrySet()) {
 
 510             LOGGER.info("Decision Returned Policy {}", entrySet.getKey());
 
 511             assertThat(entrySet.getValue()).isInstanceOf(Map.class);
 
 512             Map<String, Object> policyContents = (Map<String, Object>) entrySet.getValue();
 
 513             assertThat(policyContents).containsKey("properties");
 
 514             assertThat(policyContents.get("properties")).isInstanceOf(Map.class);
 
 515             Map<String, Object> policyProperties = (Map<String, Object>) policyContents.get("properties");
 
 517             validateMatchable((Collection<String>) request.getResource().get("scope"),
 
 518                     (Collection<String>) policyProperties.get("scope"));
 
 520             validateMatchable((Collection<String>) request.getResource().get("services"),
 
 521                     (Collection<String>) policyProperties.get("services"));
 
 523             validateMatchable((Collection<String>) request.getResource().get("resources"),
 
 524                     (Collection<String>) policyProperties.get("resources"));
 
 526             validateMatchable((Collection<String>) request.getResource().get("geography"),
 
 527                     (Collection<String>) policyProperties.get("geography"));
 
 531     private void validateMatchable(Collection<String> requestList, Collection<String> policyProperties) {
 
 532         LOGGER.info("Validating matchable: {} with {}", policyProperties, requestList);
 
 534         // Null or empty implies '*' - that is any value is acceptable
 
 537         if (policyProperties == null || policyProperties.isEmpty()) {
 
 540         Condition<String> condition = new Condition<>(
 
 541                 requestList::contains,
 
 542                 "Request list is contained");
 
 543         assertThat(policyProperties).haveAtLeast(1, condition);
 
 547     @SuppressWarnings("unchecked")
 
 548     private void cleanOutResources() {
 
 549         ((List<String>) baseRequest.getResource().get("scope")).clear();
 
 550         ((List<String>) baseRequest.getResource().get("services")).clear();
 
 551         ((List<String>) baseRequest.getResource().get("resources")).clear();
 
 552         ((List<String>) baseRequest.getResource().get("geography")).clear();
 
 553         if (((List<String>) baseRequest.getResource().get("policy-type")) != null) {
 
 554             baseRequest.getResource().remove("policy-type");