1cb8f32a024169aa7eac4adeda0a8102d74288a0
[policy/xacml-pdp.git] /
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.Resource",
80         "onap.policies.optimization.Service",
81         "onap.policies.optimization.resource.AffinityPolicy",
82         "onap.policies.optimization.resource.DistancePolicy",
83         "onap.policies.optimization.resource.HpaPolicy",
84         "onap.policies.optimization.resource.OptimizationPolicy",
85         "onap.policies.optimization.resource.PciPolicy",
86         "onap.policies.optimization.service.QueryPolicy",
87         "onap.policies.optimization.service.SubscriberPolicy",
88         "onap.policies.optimization.resource.Vim_fit",
89         "onap.policies.optimization.resource.VnfPolicy"};
90
91     @ClassRule
92     public static final TemporaryFolder policyFolder = new TemporaryFolder();
93
94     /**
95      * Copies the xacml.properties and policies files into
96      * temporary folder and loads the service provider saving
97      * instance of provider off for other tests to use.
98      */
99     @BeforeClass
100     public static void setUp() throws Exception {
101         clientParams = mock(RestServerParameters.class);
102         when(clientParams.getHost()).thenReturn("localhost");
103         when(clientParams.getPort()).thenReturn(6969);
104         //
105         // Load Single Decision Request
106         //
107         baseRequest = gson.decode(
108                 TextFileUtils
109                     .getTextFileAsString(
110                             "src/test/resources/decision.optimization.input.json"),
111                     DecisionRequest.class);
112         //
113         // Setup our temporary folder
114         //
115         XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename);
116         propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties",
117                 properties, myCreator);
118         //
119         // Copy the test policy types into data area
120         //
121         for (String policy : listPolicyTypeFiles) {
122             String policyType = ResourceUtils.getResourceAsString("policytypes/" + policy + ".yaml");
123             LOGGER.info("Copying {}", policyType);
124             Files.write(Paths.get(policyFolder.getRoot().getAbsolutePath(), policy + "-1.0.0.yaml"),
125                     policyType.getBytes());
126         }
127         //
128         // Load service
129         //
130         ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
131                 ServiceLoader.load(XacmlApplicationServiceProvider.class);
132         //
133         // Iterate through Xacml application services and find
134         // the optimization service. Save it for use throughout
135         // all the Junit tests.
136         //
137         StringBuilder strDump = new StringBuilder("Loaded applications:" + XacmlPolicyUtils.LINE_SEPARATOR);
138         Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
139         while (iterator.hasNext()) {
140             XacmlApplicationServiceProvider application = iterator.next();
141             //
142             // Is it our service?
143             //
144             if (application instanceof OptimizationPdpApplication) {
145                 //
146                 // Should be the first and only one
147                 //
148                 assertThat(service).isNull();
149                 service = application;
150             }
151             strDump.append(application.applicationName());
152             strDump.append(" supports ");
153             strDump.append(application.supportedPolicyTypes());
154             strDump.append(XacmlPolicyUtils.LINE_SEPARATOR);
155         }
156         LOGGER.debug("{}", strDump);
157         assertThat(service).isNotNull();
158         //
159         // Tell it to initialize based on the properties file
160         // we just built for it.
161         //
162         service.initialize(propertiesFile.toPath().getParent(), clientParams);
163     }
164
165     @Test
166     public void test01Basics() {
167         //
168         // Make sure there's an application name
169         //
170         assertThat(service.applicationName()).isNotEmpty();
171         //
172         // Decisions
173         //
174         assertThat(service.actionDecisionsSupported().size()).isEqualTo(1);
175         assertThat(service.actionDecisionsSupported()).contains("optimize");
176         //
177         // Ensure it has the supported policy types and
178         // can support the correct policy types.
179         //
180         assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
181                 "onap.policies.optimization.resource.AffinityPolicy", "1.0.0"))).isTrue();
182         assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
183                 "onap.policies.optimization.service.SubscriberPolicy", "1.0.0"))).isTrue();
184         assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
185                 "onap.foobar", "1.0.0"))).isFalse();
186     }
187
188     @Test
189     public void test02NoPolicies() throws CoderException {
190         //
191         // Ask for a decision when there are no policies loaded
192         //
193         LOGGER.info("Request {}", gson.encode(baseRequest));
194         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
195         LOGGER.info("Decision {}", decision.getKey());
196
197         assertThat(decision.getKey()).isNotNull();
198         assertThat(decision.getKey().getPolicies().size()).isEqualTo(0);
199     }
200
201     @Test
202     public void test03OptimizationDefault() throws CoderException, FileNotFoundException, IOException,
203         XacmlApplicationException {
204         //
205         // Now load all the optimization policies
206         //
207         TestUtils.loadPolicies("src/test/resources/vCPE.policies.optimization.input.tosca.yaml", service);
208         //
209         // Ask for a decision for available default policies
210         //
211         DecisionResponse response = makeDecision();
212
213         assertThat(response).isNotNull();
214         assertThat(response.getPolicies().size()).isEqualTo(2);
215         //
216         // Validate it
217         //
218         validateDecision(response, baseRequest);
219     }
220
221     @SuppressWarnings("unchecked")
222     @Test
223     public void test04OptimizationDefaultHpa() throws CoderException, FileNotFoundException, IOException,
224         XacmlApplicationException {
225         //
226         // Add in policy type
227         //
228         List<String> policyTypes = Lists.newArrayList("onap.policies.optimization.resource.HpaPolicy");
229         baseRequest.getResource().put("policy-type", policyTypes);
230         //
231         // Ask for a decision for default HPA policy
232         //
233         DecisionResponse response = makeDecision();
234
235         assertThat(response).isNotNull();
236         assertThat(response.getPolicies().size()).isEqualTo(1);
237         response.getPolicies().forEach((key, value) -> {
238             assertThat(((Map<String, Object>) value).get("type"))
239                 .isEqualTo(("onap.policies.optimization.resource.HpaPolicy"));
240         });
241         //
242         // Validate it
243         //
244         validateDecision(response, baseRequest);
245     }
246
247     @SuppressWarnings("unchecked")
248     @Test
249     public void test05OptimizationDefaultGeography() throws CoderException {
250         //
251         // Remove all the policy-type resources from the request
252         //
253         cleanOutResources();
254         //
255         // Add US to the geography list
256         //
257         ((List<String>)baseRequest.getResource().get("geography")).add("US");
258         //
259         // Ask for a decision for default US Policy
260         //
261         DecisionResponse response = makeDecision();
262         assertThat(response).isNotNull();
263         assertThat(response.getPolicies().size()).isEqualTo(2);
264         //
265         // Validate it
266         //
267         validateDecision(response, baseRequest);
268     }
269
270     @SuppressWarnings("unchecked")
271     @Test
272     public void test06OptimizationDefaultGeographyAndService() throws CoderException {
273         //
274         // Add vCPE to the service list
275         //
276         ((List<String>)baseRequest.getResource().get("services")).add("vCPE");
277         //
278         // Ask for a decision for default US policy for vCPE service
279         //
280         DecisionResponse response = makeDecision();
281
282         assertThat(response).isNotNull();
283         assertThat(response.getPolicies().size()).isEqualTo(5);
284         //
285         // Validate it
286         //
287         validateDecision(response, baseRequest);
288     }
289
290     @SuppressWarnings("unchecked")
291     @Test
292     public void test07OptimizationDefaultGeographyAndServiceAndResource() throws CoderException {
293         //
294         // Add vG to the resource list
295         //
296         ((List<String>)baseRequest.getResource().get("resources")).add("vG");
297         //
298         // Ask for a decision for default US service vCPE resource vG policy
299         //
300         DecisionResponse response = makeDecision();
301
302         assertThat(response).isNotNull();
303         assertThat(response.getPolicies().size()).isEqualTo(8);
304         //
305         // Validate it
306         //
307         validateDecision(response, baseRequest);
308     }
309
310     @SuppressWarnings("unchecked")
311     @Test
312     public void test08OptimizationGeographyAndServiceAndResourceAndScope() throws CoderException {
313         //
314         // Add gold as a scope
315         //
316         ((List<String>)baseRequest.getResource().get("scope")).add("gold");
317         //
318         // Ask for a decision for specific US vCPE vG gold
319         //
320         DecisionResponse response = makeDecision();
321
322         assertThat(response).isNotNull();
323         assertThat(response.getPolicies().size()).isEqualTo(8);
324         //
325         // Validate it
326         //
327         validateDecision(response, baseRequest);
328     }
329
330     @SuppressWarnings("unchecked")
331     @Test
332     public void test09OptimizationGeographyAndServiceAndResourceAndScopeIsGoldOrPlatinum() throws CoderException {
333         //
334         // Add platinum to the scope list: this is now gold OR platinum
335         //
336         ((List<String>)baseRequest.getResource().get("scope")).add("platinum");
337         //
338         // Ask for a decision for specific US vCPE vG (gold or platinum)
339         //
340         DecisionResponse response = makeDecision();
341
342         assertThat(response).isNotNull();
343         assertThat(response.getPolicies().size()).isEqualTo(10);
344         //
345         // Validate it
346         //
347         validateDecision(response, baseRequest);
348     }
349
350     @SuppressWarnings("unchecked")
351     @Test
352     public void test10OptimizationGeographyAndServiceAndResourceAndScopeNotGold() throws CoderException {
353         //
354         // Add gold as a scope
355         //
356         ((List<String>)baseRequest.getResource().get("scope")).remove("gold");
357         //
358         // Ask for a decision for specific US vCPE vG gold
359         //
360         DecisionResponse response = makeDecision();
361
362         assertThat(response).isNotNull();
363         assertThat(response.getPolicies().size()).isEqualTo(9);
364         //
365         // Validate it
366         //
367         validateDecision(response, baseRequest);
368     }
369
370     @Test
371     public void test11OptimizationPolicyTypeDefault() throws CoderException {
372         //
373         // Add in policy type
374         //
375         List<String> policyTypes = Lists.newArrayList("onap.policies.optimization.resource.AffinityPolicy");
376         baseRequest.getResource().put("policy-type", policyTypes);
377         //
378         // Ask for a decision for default
379         //
380         DecisionResponse response = makeDecision();
381
382         assertThat(response).isNotNull();
383         assertThat(response.getPolicies().size()).isEqualTo(1);
384         //
385         // Validate it
386         //
387         validateDecision(response, baseRequest);
388     }
389
390     @SuppressWarnings("unchecked")
391     @Test
392     public void test12OptimizationPolicyTypeDefault() throws CoderException {
393         //
394         // Add in another policy type
395         //
396         ((List<String>) baseRequest.getResource().get("policy-type"))
397             .add("onap.policies.optimization.resource.HpaPolicy");
398         //
399         // Ask for a decision for default
400         //
401         DecisionResponse response = makeDecision();
402
403         assertThat(response).isNotNull();
404         assertThat(response.getPolicies().size()).isEqualTo(2);
405         //
406         // Validate it
407         //
408         validateDecision(response, baseRequest);
409     }
410
411     private DecisionResponse makeDecision() {
412         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
413         LOGGER.info("Request Resources {}", baseRequest.getResource());
414         LOGGER.info("Decision {}", decision.getKey());
415         for (Entry<String, Object> entrySet : decision.getKey().getPolicies().entrySet()) {
416             LOGGER.info("Policy {}", entrySet.getKey());
417         }
418         return decision.getKey();
419     }
420
421     @SuppressWarnings("unchecked")
422     private void validateDecision(DecisionResponse decision, DecisionRequest request) {
423         for (Entry<String, Object> entrySet : decision.getPolicies().entrySet()) {
424             LOGGER.info("Decision Returned Policy {}", entrySet.getKey());
425             assertThat(entrySet.getValue()).isInstanceOf(Map.class);
426             Map<String, Object> policyContents = (Map<String, Object>) entrySet.getValue();
427             assertThat(policyContents.containsKey("properties")).isTrue();
428             assertThat(policyContents.get("properties")).isInstanceOf(Map.class);
429             Map<String, Object> policyProperties = (Map<String, Object>) policyContents.get("properties");
430
431             validateMatchable((Collection<String>) request.getResource().get("scope"),
432                     (Collection<String>) policyProperties.get("scope"));
433
434             validateMatchable((Collection<String>) request.getResource().get("services"),
435                     (Collection<String>) policyProperties.get("services"));
436
437             validateMatchable((Collection<String>) request.getResource().get("resources"),
438                     (Collection<String>) policyProperties.get("resources"));
439
440             validateMatchable((Collection<String>) request.getResource().get("geography"),
441                     (Collection<String>) policyProperties.get("geography"));
442         }
443     }
444
445     private void validateMatchable(Collection<String> requestList, Collection<String> policyProperties) {
446         LOGGER.info("Validating matchable: {} with {}", policyProperties, requestList);
447         //
448         // Null or empty implies '*' - that is any value is acceptable
449         // for this policy.
450         //
451         if (policyProperties == null || policyProperties.isEmpty()) {
452             return;
453         }
454         Condition<String> condition = new Condition<>(
455                 requestList::contains,
456                 "Request list is contained");
457         assertThat(policyProperties).haveAtLeast(1, condition);
458
459     }
460
461     @SuppressWarnings("unchecked")
462     private void cleanOutResources() {
463         ((List<String>)baseRequest.getResource().get("scope")).clear();
464         ((List<String>)baseRequest.getResource().get("services")).clear();
465         ((List<String>)baseRequest.getResource().get("resources")).clear();
466         ((List<String>)baseRequest.getResource().get("geography")).clear();
467         if (((List<String>)baseRequest.getResource().get("policy-type")) != null) {
468             baseRequest.getResource().remove("policy-type");
469         }
470     }
471 }