More examples of optimization policies and cleanup
[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.io.FileNotFoundException;
34 import java.io.IOException;
35 import java.nio.file.Files;
36 import java.nio.file.Paths;
37 import java.util.Collection;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Map.Entry;
42 import java.util.Properties;
43 import java.util.ServiceLoader;
44 import org.apache.commons.lang3.tuple.Pair;
45 import org.assertj.core.api.Condition;
46 import org.junit.BeforeClass;
47 import org.junit.ClassRule;
48 import org.junit.FixMethodOrder;
49 import org.junit.Test;
50 import org.junit.rules.TemporaryFolder;
51 import org.junit.runners.MethodSorters;
52 import org.onap.policy.common.endpoints.parameters.RestServerParameters;
53 import org.onap.policy.common.utils.coder.CoderException;
54 import org.onap.policy.common.utils.coder.StandardCoder;
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.ToscaPolicyTypeIdentifier;
60 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
61 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
62 import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
63 import org.onap.policy.pdp.xacml.xacmltest.TestUtils;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66
67 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
68 public class OptimizationPdpApplicationTest {
69
70     private static final Logger LOGGER = LoggerFactory.getLogger(OptimizationPdpApplicationTest.class);
71     private static Properties properties = new Properties();
72     private static File propertiesFile;
73     private static XacmlApplicationServiceProvider service;
74     private static StandardCoder gson = new StandardCoder();
75     private static DecisionRequest baseRequest;
76     private static RestServerParameters clientParams;
77     private static String[] listPolicyTypeFiles = {
78         "onap.policies.Optimization",
79         "onap.policies.optimization.AffinityPolicy",
80         "onap.policies.optimization.DistancePolicy",
81         "onap.policies.optimization.HpaPolicy",
82         "onap.policies.optimization.OptimizationPolicy",
83         "onap.policies.optimization.PciPolicy",
84         "onap.policies.optimization.QueryPolicy",
85         "onap.policies.optimization.SubscriberPolicy",
86         "onap.policies.optimization.Vim_fit",
87         "onap.policies.optimization.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     @Test
164     public void test01Basics() {
165         //
166         // Make sure there's an application name
167         //
168         assertThat(service.applicationName()).isNotEmpty();
169         //
170         // Decisions
171         //
172         assertThat(service.actionDecisionsSupported().size()).isEqualTo(1);
173         assertThat(service.actionDecisionsSupported()).contains("optimize");
174         //
175         // Ensure it has the supported policy types and
176         // can support the correct policy types.
177         //
178         assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
179                 "onap.policies.optimization.AffinityPolicy", "1.0.0"))).isTrue();
180         assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
181                 "onap.foobar", "1.0.0"))).isFalse();
182     }
183
184     @Test
185     public void test02NoPolicies() throws CoderException {
186         //
187         // Ask for a decision when there are no policies loaded
188         //
189         LOGGER.info("Request {}", gson.encode(baseRequest));
190         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
191         LOGGER.info("Decision {}", decision.getKey());
192
193         assertThat(decision.getKey()).isNotNull();
194         assertThat(decision.getKey().getPolicies().size()).isEqualTo(0);
195     }
196
197     @Test
198     public void test03OptimizationDefault() throws CoderException, FileNotFoundException, IOException,
199         XacmlApplicationException {
200         //
201         // Now load all the optimization policies
202         //
203         TestUtils.loadPolicies("src/test/resources/vCPE.policies.optimization.input.tosca.yaml", service);
204         //
205         // Ask for a decision for available default policies
206         //
207         DecisionResponse response = makeDecision();
208
209         assertThat(response).isNotNull();
210         assertThat(response.getPolicies().size()).isEqualTo(2);
211         //
212         // Validate it
213         //
214         validateDecision(response, baseRequest);
215     }
216
217     @SuppressWarnings("unchecked")
218     @Test
219     public void test04OptimizationDefaultHpa() throws CoderException, FileNotFoundException, IOException,
220         XacmlApplicationException {
221         //
222         // Add in policy type
223         //
224         List<String> policyTypes = Lists.newArrayList("onap.policies.optimization.HpaPolicy");
225         baseRequest.getResource().put("policy-type", policyTypes);
226         //
227         // Ask for a decision for default HPA policy
228         //
229         DecisionResponse response = makeDecision();
230
231         assertThat(response).isNotNull();
232         assertThat(response.getPolicies().size()).isEqualTo(1);
233         response.getPolicies().forEach((key, value) -> {
234             assertThat(((Map<String, Object>) value).get("type")).isEqualTo(("onap.policies.optimization.HpaPolicy"));
235         });
236         //
237         // Validate it
238         //
239         validateDecision(response, baseRequest);
240     }
241
242     @SuppressWarnings("unchecked")
243     @Test
244     public void test05OptimizationDefaultGeography() throws CoderException {
245         //
246         // Remove all the policy-type resources from the request
247         //
248         cleanOutResources();
249         //
250         // Add US to the geography list
251         //
252         ((List<String>)baseRequest.getResource().get("geography")).add("US");
253         //
254         // Ask for a decision for default US Policy
255         //
256         DecisionResponse response = makeDecision();
257         assertThat(response).isNotNull();
258         assertThat(response.getPolicies().size()).isEqualTo(3); // Should be 1
259         //
260         // Validate it
261         //
262         validateDecision(response, baseRequest);
263     }
264
265     @SuppressWarnings("unchecked")
266     @Test
267     public void test06OptimizationDefaultGeographyAndService() throws CoderException {
268         //
269         // Add vCPE to the service list
270         //
271         ((List<String>)baseRequest.getResource().get("services")).add("vCPE");
272         //
273         // Ask for a decision for default US policy for vCPE service
274         //
275         DecisionResponse response = makeDecision();
276
277         assertThat(response).isNotNull();
278         assertThat(response.getPolicies().size()).isEqualTo(6); // should be 1
279         //
280         // Validate it
281         //
282         validateDecision(response, baseRequest);
283     }
284
285     @SuppressWarnings("unchecked")
286     @Test
287     public void test07OptimizationDefaultGeographyAndServiceAndResource() throws CoderException {
288         //
289         // Add vCPE to the service list
290         //
291         ((List<String>)baseRequest.getResource().get("resources")).add("vG");
292         //
293         // Ask for a decision for default US service vCPE resource vG policy
294         //
295         DecisionResponse response = makeDecision();
296
297         assertThat(response).isNotNull();
298         assertThat(response.getPolicies().size()).isEqualTo(11); // should be 4
299         //
300         // Validate it
301         //
302         validateDecision(response, baseRequest);
303     }
304
305     @SuppressWarnings("unchecked")
306     @Test
307     public void test08OptimizationGeographyAndServiceAndResourceAndScope() throws CoderException {
308         //
309         // Add gold as a scope
310         //
311         ((List<String>)baseRequest.getResource().get("scope")).add("gold");
312         //
313         // Ask for a decision for specific US vCPE vG gold
314         //
315         DecisionResponse response = makeDecision();
316
317         assertThat(response).isNotNull();
318         assertThat(response.getPolicies().size()).isEqualTo(12); // should be 1
319         //
320         // Validate it
321         //
322         validateDecision(response, baseRequest);
323     }
324
325     @SuppressWarnings("unchecked")
326     @Test
327     public void test09OptimizationGeographyAndServiceAndResourceAndScopeIsGoldOrPlatinum() throws CoderException {
328         //
329         // Add platinum to the scope list: this is now gold OR platinum
330         //
331         ((List<String>)baseRequest.getResource().get("scope")).add("platinum");
332         //
333         // Ask for a decision for specific US vCPE vG (gold or platinum)
334         //
335         DecisionResponse response = makeDecision();
336
337         assertThat(response).isNotNull();
338         assertThat(response.getPolicies().size()).isEqualTo(14); // should be 3
339         //
340         // Validate it
341         //
342         validateDecision(response, baseRequest);
343     }
344
345     @SuppressWarnings("unchecked")
346     @Test
347     public void test10OptimizationGeographyAndServiceAndResourceAndScopeNotGold() throws CoderException {
348         //
349         // Add gold as a scope
350         //
351         ((List<String>)baseRequest.getResource().get("scope")).remove("gold");
352         //
353         // Ask for a decision for specific US vCPE vG gold
354         //
355         DecisionResponse response = makeDecision();
356
357         assertThat(response).isNotNull();
358         assertThat(response.getPolicies().size()).isEqualTo(13); // should be 2
359         //
360         // Validate it
361         //
362         validateDecision(response, baseRequest);
363     }
364
365     @Test
366     public void test11OptimizationPolicyTypeDefault() throws CoderException {
367         //
368         // Add in policy type
369         //
370         List<String> policyTypes = Lists.newArrayList("onap.policies.optimization.AffinityPolicy");
371         baseRequest.getResource().put("policy-type", policyTypes);
372         //
373         // Ask for a decision for default
374         //
375         DecisionResponse response = makeDecision();
376
377         assertThat(response).isNotNull();
378         assertThat(response.getPolicies().size()).isEqualTo(4); // should be 1
379         //
380         // Validate it
381         //
382         validateDecision(response, baseRequest);
383     }
384
385     @SuppressWarnings("unchecked")
386     @Test
387     public void test12OptimizationPolicyTypeDefault() throws CoderException {
388         //
389         // Add in another policy type
390         //
391         ((List<String>) baseRequest.getResource().get("policy-type")).add("onap.policies.optimization.HpaPolicy");
392         //
393         // Ask for a decision for default
394         //
395         DecisionResponse response = makeDecision();
396
397         assertThat(response).isNotNull();
398         assertThat(response.getPolicies().size()).isEqualTo(6); // should be 2
399         //
400         // Validate it
401         //
402         validateDecision(response, baseRequest);
403     }
404
405     private DecisionResponse makeDecision() {
406         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
407         LOGGER.info("Request Resources {}", baseRequest.getResource());
408         LOGGER.info("Decision {}", decision.getKey());
409         for (Entry<String, Object> entrySet : decision.getKey().getPolicies().entrySet()) {
410             LOGGER.info("Policy {}", entrySet.getKey());
411         }
412         return decision.getKey();
413     }
414
415     @SuppressWarnings("unchecked")
416     private void validateDecision(DecisionResponse decision, DecisionRequest request) {
417         for (Entry<String, Object> entrySet : decision.getPolicies().entrySet()) {
418             LOGGER.info("Decision Returned Policy {}", entrySet.getKey());
419             assertThat(entrySet.getValue()).isInstanceOf(Map.class);
420             Map<String, Object> policyContents = (Map<String, Object>) entrySet.getValue();
421             assertThat(policyContents.containsKey("properties")).isTrue();
422             assertThat(policyContents.get("properties")).isInstanceOf(Map.class);
423             Map<String, Object> policyProperties = (Map<String, Object>) policyContents.get("properties");
424
425             validateMatchable((Collection<String>) request.getResource().get("scope"),
426                     (Collection<String>) policyProperties.get("scope"));
427
428             validateMatchable((Collection<String>) request.getResource().get("services"),
429                     (Collection<String>) policyProperties.get("services"));
430
431             validateMatchable((Collection<String>) request.getResource().get("resources"),
432                     (Collection<String>) policyProperties.get("resources"));
433
434             validateMatchable((Collection<String>) request.getResource().get("geography"),
435                     (Collection<String>) policyProperties.get("geography"));
436         }
437     }
438
439     private void validateMatchable(Collection<String> requestList, Collection<String> policyProperties) {
440         LOGGER.info("Validating matchable: {} with {}", policyProperties, requestList);
441         //
442         // Null or empty implies '*' - that is any value is acceptable
443         // for this policy.
444         //
445         if (policyProperties == null || policyProperties.isEmpty()) {
446             return;
447         }
448         Condition<String> condition = new Condition<>(
449                 requestList::contains,
450                 "Request list is contained");
451         assertThat(policyProperties).haveAtLeast(1, condition);
452
453     }
454
455     @SuppressWarnings("unchecked")
456     private void cleanOutResources() {
457         ((List<String>)baseRequest.getResource().get("scope")).clear();
458         ((List<String>)baseRequest.getResource().get("services")).clear();
459         ((List<String>)baseRequest.getResource().get("resources")).clear();
460         ((List<String>)baseRequest.getResource().get("geography")).clear();
461         if (((List<String>)baseRequest.getResource().get("policy-type")) != null) {
462             baseRequest.getResource().remove("policy-type");
463         }
464     }
465 }