Add optimization subscriber request
[policy/xacml-pdp.git] / applications / optimization / src / test / java / org / onap / policy / xacml / pdp / application / optimization / OptimizationPdpApplicationTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6    Modifications Copyright (C) 2019 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
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  * SPDX-License-Identifier: Apache-2.0
21  * ============LICENSE_END=========================================================
22  */
23
24 package org.onap.policy.xacml.pdp.application.optimization;
25
26 import static org.assertj.core.api.Assertions.assertThat;
27 import static org.mockito.Mockito.mock;
28 import static org.mockito.Mockito.when;
29
30 import com.att.research.xacml.api.Response;
31 import com.google.common.collect.Lists;
32 import java.io.File;
33 import java.nio.file.Files;
34 import java.nio.file.Paths;
35 import java.util.Collection;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Map.Entry;
40 import java.util.Properties;
41 import java.util.ServiceLoader;
42 import org.apache.commons.lang3.tuple.Pair;
43 import org.assertj.core.api.Condition;
44 import org.junit.BeforeClass;
45 import org.junit.ClassRule;
46 import org.junit.FixMethodOrder;
47 import org.junit.Test;
48 import org.junit.rules.TemporaryFolder;
49 import org.junit.runners.MethodSorters;
50 import org.onap.policy.common.endpoints.parameters.RestServerParameters;
51 import org.onap.policy.common.utils.coder.CoderException;
52 import org.onap.policy.common.utils.coder.StandardCoder;
53 import org.onap.policy.common.utils.resources.ResourceUtils;
54 import org.onap.policy.common.utils.resources.TextFileUtils;
55 import org.onap.policy.models.decisions.concepts.DecisionRequest;
56 import org.onap.policy.models.decisions.concepts.DecisionResponse;
57 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
58 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
59 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
60 import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
61 import org.onap.policy.pdp.xacml.xacmltest.TestUtils;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
66 public class OptimizationPdpApplicationTest {
67
68     private static final Logger LOGGER = LoggerFactory.getLogger(OptimizationPdpApplicationTest.class);
69     private static Properties properties = new Properties();
70     private static File propertiesFile;
71     private static XacmlApplicationServiceProvider service;
72     private static StandardCoder gson = new StandardCoder();
73     private static DecisionRequest baseRequest;
74     private static RestServerParameters clientParams;
75     private static String[] listPolicyTypeFiles = {
76         "onap.policies.Optimization",
77         "onap.policies.optimization.Resource",
78         "onap.policies.optimization.Service",
79         "onap.policies.optimization.resource.AffinityPolicy",
80         "onap.policies.optimization.resource.DistancePolicy",
81         "onap.policies.optimization.resource.HpaPolicy",
82         "onap.policies.optimization.resource.OptimizationPolicy",
83         "onap.policies.optimization.resource.PciPolicy",
84         "onap.policies.optimization.service.QueryPolicy",
85         "onap.policies.optimization.service.SubscriberPolicy",
86         "onap.policies.optimization.resource.Vim_fit",
87         "onap.policies.optimization.resource.VnfPolicy"};
88
89     @ClassRule
90     public static final TemporaryFolder policyFolder = new TemporaryFolder();
91
92     /**
93      * Copies the xacml.properties and policies files into
94      * temporary folder and loads the service provider saving
95      * instance of provider off for other tests to use.
96      */
97     @BeforeClass
98     public static void setUp() throws Exception {
99         clientParams = mock(RestServerParameters.class);
100         when(clientParams.getHost()).thenReturn("localhost");
101         when(clientParams.getPort()).thenReturn(6969);
102         //
103         // Load Single Decision Request
104         //
105         baseRequest = gson.decode(
106                 TextFileUtils
107                     .getTextFileAsString(
108                             "src/test/resources/decision.optimization.input.json"),
109                     DecisionRequest.class);
110         //
111         // Setup our temporary folder
112         //
113         XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename);
114         propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties",
115                 properties, myCreator);
116         //
117         // Copy the test policy types into data area
118         //
119         for (String policy : listPolicyTypeFiles) {
120             String policyType = ResourceUtils.getResourceAsString("policytypes/" + policy + ".yaml");
121             LOGGER.info("Copying {}", policyType);
122             Files.write(Paths.get(policyFolder.getRoot().getAbsolutePath(), policy + "-1.0.0.yaml"),
123                     policyType.getBytes());
124         }
125         //
126         // Load service
127         //
128         ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
129                 ServiceLoader.load(XacmlApplicationServiceProvider.class);
130         //
131         // Iterate through Xacml application services and find
132         // the optimization service. Save it for use throughout
133         // all the Junit tests.
134         //
135         StringBuilder strDump = new StringBuilder("Loaded applications:" + XacmlPolicyUtils.LINE_SEPARATOR);
136         Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
137         while (iterator.hasNext()) {
138             XacmlApplicationServiceProvider application = iterator.next();
139             //
140             // Is it our service?
141             //
142             if (application instanceof OptimizationPdpApplication) {
143                 //
144                 // Should be the first and only one
145                 //
146                 assertThat(service).isNull();
147                 service = application;
148             }
149             strDump.append(application.applicationName());
150             strDump.append(" supports ");
151             strDump.append(application.supportedPolicyTypes());
152             strDump.append(XacmlPolicyUtils.LINE_SEPARATOR);
153         }
154         LOGGER.debug("{}", strDump);
155         assertThat(service).isNotNull();
156         //
157         // Tell it to initialize based on the properties file
158         // we just built for it.
159         //
160         service.initialize(propertiesFile.toPath().getParent(), clientParams);
161     }
162
163     /**
164      * Simply test some of the simple methods for the application.
165      */
166     @Test
167     public void test01Basics() {
168         //
169         // Make sure there's an application name
170         //
171         assertThat(service.applicationName()).isNotEmpty();
172         //
173         // Does it return the correct decisions
174         //
175         assertThat(service.actionDecisionsSupported().size()).isEqualTo(1);
176         assertThat(service.actionDecisionsSupported()).contains("optimize");
177         //
178         // Ensure it has the supported policy types and
179         // can support the correct policy types.
180         //
181         assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
182                 "onap.policies.optimization.resource.AffinityPolicy", "1.0.0"))).isTrue();
183         assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
184                 "onap.policies.optimization.service.SubscriberPolicy", "1.0.0"))).isTrue();
185         assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
186                 "onap.foobar", "1.0.0"))).isFalse();
187     }
188
189     /**
190      * With no policies loaded, there should be 0 policies returned.
191      *
192      * @throws CoderException CoderException
193      */
194     @Test
195     public void test02NoPolicies() throws CoderException {
196         //
197         // Ask for a decision when there are no policies loaded
198         //
199         LOGGER.info("Request {}", gson.encode(baseRequest));
200         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
201         LOGGER.info("Decision {}", decision.getKey());
202
203         assertThat(decision.getKey()).isNotNull();
204         assertThat(decision.getKey().getPolicies().size()).isEqualTo(0);
205     }
206
207     /**
208      * Should return ONLY default policies.
209      *
210      * @throws XacmlApplicationException could not load policies
211      */
212     @Test
213     public void test03OptimizationDefault() throws XacmlApplicationException {
214         //
215         // Now load all the optimization policies
216         //
217         TestUtils.loadPolicies("src/test/resources/vCPE.policies.optimization.input.tosca.yaml", service);
218         //
219         // Ask for a decision for available default policies
220         //
221         DecisionResponse response = makeDecision();
222
223         assertThat(response).isNotNull();
224         assertThat(response.getPolicies().size()).isEqualTo(2);
225         //
226         // Validate it
227         //
228         validateDecision(response, baseRequest);
229     }
230
231     /**
232      * Should only return default HPA policy type.
233      */
234     @SuppressWarnings("unchecked")
235     @Test
236     public void test04OptimizationDefaultHpa() {
237         //
238         // Add in policy type
239         //
240         List<String> policyTypes = Lists.newArrayList("onap.policies.optimization.resource.HpaPolicy");
241         baseRequest.getResource().put("policy-type", policyTypes);
242         //
243         // Ask for a decision for default HPA policy
244         //
245         DecisionResponse response = makeDecision();
246
247         assertThat(response).isNotNull();
248         assertThat(response.getPolicies().size()).isEqualTo(1);
249         response.getPolicies().forEach((key, value) -> {
250             assertThat(((Map<String, Object>) value).get("type"))
251                 .isEqualTo(("onap.policies.optimization.resource.HpaPolicy"));
252         });
253         //
254         // Validate it
255         //
256         validateDecision(response, baseRequest);
257     }
258
259     /**
260      * Refine for US only policies.
261      */
262     @SuppressWarnings("unchecked")
263     @Test
264     public void test05OptimizationDefaultGeography() throws CoderException {
265         //
266         // Remove all the policy-type resources from the request
267         //
268         cleanOutResources();
269         //
270         // Add US to the geography list
271         //
272         ((List<String>)baseRequest.getResource().get("geography")).add("US");
273         //
274         // Ask for a decision for default US Policy
275         //
276         DecisionResponse response = makeDecision();
277         assertThat(response).isNotNull();
278         assertThat(response.getPolicies().size()).isEqualTo(2);
279         //
280         // Validate it
281         //
282         validateDecision(response, baseRequest);
283     }
284
285     /**
286      * Add more refinement for service.
287      */
288     @SuppressWarnings("unchecked")
289     @Test
290     public void test06OptimizationDefaultGeographyAndService() {
291         //
292         // Add vCPE to the service list
293         //
294         ((List<String>)baseRequest.getResource().get("services")).add("vCPE");
295         //
296         // Ask for a decision for default US policy for vCPE service
297         //
298         DecisionResponse response = makeDecision();
299
300         assertThat(response).isNotNull();
301         assertThat(response.getPolicies().size()).isEqualTo(3);
302         //
303         // Validate it
304         //
305         validateDecision(response, baseRequest);
306     }
307
308     /**
309      * Add more refinement for specific resource.
310      */
311     @SuppressWarnings("unchecked")
312     @Test
313     public void test07OptimizationDefaultGeographyAndServiceAndResource() {
314         //
315         // Add vG to the resource list
316         //
317         ((List<String>)baseRequest.getResource().get("resources")).add("vG");
318         //
319         // Ask for a decision for default US service vCPE resource vG policy
320         //
321         DecisionResponse response = makeDecision();
322
323         assertThat(response).isNotNull();
324         assertThat(response.getPolicies().size()).isEqualTo(6);
325         //
326         // Validate it
327         //
328         validateDecision(response, baseRequest);
329     }
330
331     /**
332      * Now we need to add in subscriberName in order to get scope for gold.
333      */
334     @SuppressWarnings("unchecked")
335     @Test
336     public void test08OptimizationGeographyAndServiceAndResourceAndScopeIsGoldSubscriber() {
337         //
338         // Add gold as a scope
339         //
340         //((List<String>)baseRequest.getResource().get("scope")).add("gold");
341         ((List<String>)baseRequest.getContext().get("subscriberName")).add("subscriber_a");
342         //
343         // Ask for a decision for specific US vCPE vG gold
344         //
345         DecisionResponse response = makeDecision();
346
347         assertThat(response).isNotNull();
348         assertThat(response.getPolicies().size()).isEqualTo(6);
349         //
350         // Validate it
351         //
352         validateDecision(response, baseRequest);
353     }
354
355     /**
356      * Add a subscriber that should be platinum.
357      */
358     @SuppressWarnings("unchecked")
359     @Test
360     public void test09OptimizationGeographyAndServiceAndResourceAndScopeGoldOrPlatinumSubscriber() {
361         //
362         // Add platinum to the scope list: this is now gold OR platinum
363         //
364         ((List<String>)baseRequest.getResource().get("scope")).remove("gold");
365         ((List<String>)baseRequest.getContext().get("subscriberName")).add("subscriber_x");
366         //
367         // Ask for a decision for specific US vCPE vG (gold or platinum)
368         //
369         DecisionResponse response = makeDecision();
370
371         assertThat(response).isNotNull();
372         assertThat(response.getPolicies().size()).isEqualTo(8);
373         //
374         // Validate it
375         //
376         validateDecision(response, baseRequest);
377     }
378
379     /**
380      * Remove gold subscriber, keep the platinum one.
381      */
382     @SuppressWarnings("unchecked")
383     @Test
384     public void test10OptimizationGeographyAndServiceAndResourceAndScopeNotGoldStillPlatinum() {
385         //
386         // Add gold as a scope
387         //
388         ((List<String>)baseRequest.getResource().get("scope")).remove("gold");
389         ((List<String>)baseRequest.getResource().get("scope")).remove("platinum");
390         ((List<String>)baseRequest.getContext().get("subscriberName")).remove("subscriber_a");
391         //
392         // Ask for a decision for specific US vCPE vG gold
393         //
394         DecisionResponse response = makeDecision();
395
396         assertThat(response).isNotNull();
397         assertThat(response.getPolicies().size()).isEqualTo(7);
398         //
399         // Validate it
400         //
401         validateDecision(response, baseRequest);
402     }
403
404     /**
405      * Filter by Affinity policy.
406      */
407     @Test
408     public void test11OptimizationPolicyTypeDefault() {
409         //
410         // Add in policy type
411         //
412         List<String> policyTypes = Lists.newArrayList("onap.policies.optimization.resource.AffinityPolicy");
413         baseRequest.getResource().put("policy-type", policyTypes);
414         //
415         // Ask for a decision for default
416         //
417         DecisionResponse response = makeDecision();
418
419         assertThat(response).isNotNull();
420         assertThat(response.getPolicies().size()).isEqualTo(1);
421         //
422         // Validate it
423         //
424         validateDecision(response, baseRequest);
425     }
426
427     /**
428      * Now filter by HPA policy type.
429      */
430     @SuppressWarnings("unchecked")
431     @Test
432     public void test12OptimizationPolicyTypeDefault() {
433         //
434         // Add in another policy type
435         //
436         ((List<String>) baseRequest.getResource().get("policy-type"))
437             .add("onap.policies.optimization.resource.HpaPolicy");
438         //
439         // Ask for a decision for default
440         //
441         DecisionResponse response = makeDecision();
442
443         assertThat(response).isNotNull();
444         assertThat(response.getPolicies().size()).isEqualTo(2);
445         //
446         // Validate it
447         //
448         validateDecision(response, baseRequest);
449     }
450
451     private DecisionResponse makeDecision() {
452         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
453         LOGGER.info("Request Resources {}", baseRequest.getResource());
454         LOGGER.info("Decision {}", decision.getKey());
455         for (Entry<String, Object> entrySet : decision.getKey().getPolicies().entrySet()) {
456             LOGGER.info("Policy {}", entrySet.getKey());
457         }
458         return decision.getKey();
459     }
460
461     @SuppressWarnings("unchecked")
462     private void validateDecision(DecisionResponse decision, DecisionRequest request) {
463         for (Entry<String, Object> entrySet : decision.getPolicies().entrySet()) {
464             LOGGER.info("Decision Returned Policy {}", entrySet.getKey());
465             assertThat(entrySet.getValue()).isInstanceOf(Map.class);
466             Map<String, Object> policyContents = (Map<String, Object>) entrySet.getValue();
467             assertThat(policyContents.containsKey("properties")).isTrue();
468             assertThat(policyContents.get("properties")).isInstanceOf(Map.class);
469             Map<String, Object> policyProperties = (Map<String, Object>) policyContents.get("properties");
470
471             validateMatchable((Collection<String>) request.getResource().get("scope"),
472                     (Collection<String>) policyProperties.get("scope"));
473
474             validateMatchable((Collection<String>) request.getResource().get("services"),
475                     (Collection<String>) policyProperties.get("services"));
476
477             validateMatchable((Collection<String>) request.getResource().get("resources"),
478                     (Collection<String>) policyProperties.get("resources"));
479
480             validateMatchable((Collection<String>) request.getResource().get("geography"),
481                     (Collection<String>) policyProperties.get("geography"));
482         }
483     }
484
485     private void validateMatchable(Collection<String> requestList, Collection<String> policyProperties) {
486         LOGGER.info("Validating matchable: {} with {}", policyProperties, requestList);
487         //
488         // Null or empty implies '*' - that is any value is acceptable
489         // for this policy.
490         //
491         if (policyProperties == null || policyProperties.isEmpty()) {
492             return;
493         }
494         Condition<String> condition = new Condition<>(
495                 requestList::contains,
496                 "Request list is contained");
497         assertThat(policyProperties).haveAtLeast(1, condition);
498
499     }
500
501     @SuppressWarnings("unchecked")
502     private void cleanOutResources() {
503         ((List<String>)baseRequest.getResource().get("scope")).clear();
504         ((List<String>)baseRequest.getResource().get("services")).clear();
505         ((List<String>)baseRequest.getResource().get("resources")).clear();
506         ((List<String>)baseRequest.getResource().get("geography")).clear();
507         if (((List<String>)baseRequest.getResource().get("policy-type")) != null) {
508             baseRequest.getResource().remove("policy-type");
509         }
510     }
511 }