Merge "Create the operationshistory table from pdpx"
[policy/xacml-pdp.git] / applications / guard / src / test / java / org / onap / policy / xacml / pdp / application / guard / CoordinationTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * SPDX-License-Identifier: Apache-2.0
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.xacml.pdp.application.guard;
24
25 import static org.assertj.core.api.Assertions.assertThat;
26
27 import com.att.research.xacml.api.Response;
28
29 import java.io.File;
30 import java.io.IOException;
31 import java.sql.Date;
32 import java.time.Instant;
33 import java.util.Iterator;
34 import java.util.Map;
35 import java.util.Properties;
36 import java.util.ServiceLoader;
37 import java.util.UUID;
38
39 import javax.persistence.EntityManager;
40 import javax.persistence.Persistence;
41
42 import org.apache.commons.lang3.tuple.Pair;
43 import org.junit.AfterClass;
44 import org.junit.Before;
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.utils.coder.CoderException;
52 import org.onap.policy.common.utils.coder.StandardCoder;
53 import org.onap.policy.common.utils.resources.TextFileUtils;
54 import org.onap.policy.models.decisions.concepts.DecisionRequest;
55 import org.onap.policy.models.decisions.concepts.DecisionResponse;
56 import org.onap.policy.pdp.xacml.application.common.TestUtils;
57 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
58 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
59 import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
60 import org.onap.policy.pdp.xacml.application.common.operationshistory.CountRecentOperationsPip;
61 import org.onap.policy.pdp.xacml.application.common.operationshistory.Dbao;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
66 public class CoordinationTest {
67
68     private static final Logger LOGGER = LoggerFactory.getLogger(CoordinationTest.class);
69     private static Properties properties = new Properties();
70     private static File propertiesFile;
71     private static XacmlApplicationServiceProvider service;
72     private static DecisionRequest requestCl1Node1;
73     private static DecisionRequest requestCl1Node2;
74     private static DecisionRequest requestCl2Node1;
75     private static DecisionRequest requestCl2Node2;
76     private static StandardCoder gson = new StandardCoder();
77     private static EntityManager em;
78     private static final String DENY = "Deny";
79     private static final String PERMIT = "Permit";
80     private static final String OPEN = "Success";
81     private static final String CLOSE = "Closed";
82
83
84     @ClassRule
85     public static final TemporaryFolder policyFolder = new TemporaryFolder();
86
87     /**
88      * Copies the xacml.properties and policies files into
89      * temporary folder and loads the service provider saving
90      * instance of provider off for other tests to use.
91      */
92     @BeforeClass
93     public static void setup() throws Exception {
94         LOGGER.info("Setting up class");
95         //
96         // Setup our temporary folder
97         //
98         XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename);
99         propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties",
100                 properties, myCreator);
101         //
102         // Load service
103         //
104         ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
105                 ServiceLoader.load(XacmlApplicationServiceProvider.class);
106         //
107         // Find the guard service application and save for use in all the tests
108         //
109         StringBuilder strDump = new StringBuilder("Loaded applications:" + System.lineSeparator());
110         Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
111         while (iterator.hasNext()) {
112             XacmlApplicationServiceProvider application = iterator.next();
113             //
114             // Is it our service?
115             //
116             if (application instanceof GuardPdpApplication) {
117                 //
118                 // Should be the first and only one
119                 //
120                 assertThat(service).isNull();
121                 service = application;
122             }
123             strDump.append(application.applicationName());
124             strDump.append(" supports ");
125             strDump.append(application.supportedPolicyTypes());
126             strDump.append(System.lineSeparator());
127         }
128         LOGGER.info("{}", strDump);
129         //
130         // Tell it to initialize based on the properties file
131         // we just built for it.
132         //
133         service.initialize(propertiesFile.toPath().getParent());
134         //
135         // Load Decision Requests
136         //
137         requestCl1Node1 = gson.decode(
138                 TextFileUtils.getTextFileAsString(
139                     "src/test/resources/requests/coordination.cl.1.node.1.json"),
140                     DecisionRequest.class);
141         requestCl2Node1 = gson.decode(
142                 TextFileUtils.getTextFileAsString(
143                     "src/test/resources/requests/coordination.cl.2.node.1.json"),
144                     DecisionRequest.class);
145         requestCl1Node2 = gson.decode(
146                 TextFileUtils.getTextFileAsString(
147                     "src/test/resources/requests/coordination.cl.1.node.2.json"),
148                     DecisionRequest.class);
149         requestCl2Node2 = gson.decode(
150                 TextFileUtils.getTextFileAsString(
151                     "src/test/resources/requests/coordination.cl.2.node.2.json"),
152                     DecisionRequest.class);
153         //
154         // Create EntityManager for manipulating DB
155         //
156         String persistenceUnit = CountRecentOperationsPip.ISSUER_NAME + ".persistenceunit";
157         em = Persistence.createEntityManagerFactory(
158                 CoordinationTest.properties.getProperty(persistenceUnit), properties)
159                 .createEntityManager();
160     }
161
162     /**
163      * Clears the database before each test.
164      *
165      */
166     @Before
167     public void startClean() throws Exception {
168         em.getTransaction().begin();
169         em.createQuery("DELETE FROM Dbao").executeUpdate();
170         em.getTransaction().commit();
171     }
172
173     /**
174      * Check that decision matches expectation.
175      *
176      * @param expected from the response
177      * @param response received
178      *
179      **/
180     public void checkDecision(String expected, DecisionResponse response) throws CoderException {
181         LOGGER.info("Looking for {} Decision", expected);
182         assertThat(response).isNotNull();
183         assertThat(response.getStatus()).isNotNull();
184         assertThat(response.getStatus()).isEqualTo(expected);
185         //
186         // Dump it out as Json
187         //
188         LOGGER.info(gson.encode(response));
189     }
190
191     /**
192      * Request a decision and check that it matches expectation.
193      *
194      * @param request to send to Xacml PDP
195      * @param expected from the response
196      *
197      **/
198     public void requestAndCheckDecision(DecisionRequest request, String expected) throws CoderException {
199         //
200         // Ask for a decision
201         //
202         Pair<DecisionResponse, Response> decision = service.makeDecision(request);
203         //
204         // Check decision
205         //
206         checkDecision(expected, decision.getKey());
207     }
208
209     @Test
210     public void test1() throws CoderException, IOException, XacmlApplicationException {
211         LOGGER.info("**************** Running test1 ****************");
212         //
213         // Now load the test coordination policy - make sure
214         // the pdp can support it and have it load
215         // into the PDP.
216         //
217         TestUtils.loadPolicies("src/test/resources/test.policy.guard.coordination.firstBlocksSecond.tosca.yaml",
218                 service);
219         //
220         // cl1 doesn't have open action: cl2 should get permit
221         //
222         requestAndCheckDecision(requestCl2Node1, PERMIT);
223         //
224         // Open cl2 on node1
225         //
226         insertOperationEvent(requestCl2Node1, OPEN);
227         //
228         // Under current coordination policy cl1 always can go
229         //
230         requestAndCheckDecision(requestCl1Node1, PERMIT);
231         //
232         // Open cl1 on node1
233         //
234         insertOperationEvent(requestCl1Node1, OPEN);
235         //
236         // Close cl2 on node1
237         //
238         insertOperationEvent(requestCl2Node1, CLOSE);
239         //
240         // Try cl2 again, cl1 has open action on node1: should get deny
241         //
242         requestAndCheckDecision(requestCl2Node1, DENY);
243         //
244         // Close cl1 on node1
245         //
246         insertOperationEvent(requestCl1Node1, CLOSE);
247         //
248         // Under current coordination policy cl1 always can go
249         //
250         requestAndCheckDecision(requestCl1Node1, PERMIT);
251         //
252         // Open cl1 on node1
253         //
254         insertOperationEvent(requestCl1Node1, OPEN);
255         //
256         // Try cl2 on node2, cl1 only open on node1: should get permit
257         //
258         requestAndCheckDecision(requestCl2Node2, PERMIT);
259         //
260         // Open cl2 on node2
261         //
262         insertOperationEvent(requestCl2Node2, OPEN);
263         //
264         // Try cl2 on node1, cl1 open on node1: should get DENY
265         //
266         requestAndCheckDecision(requestCl2Node1, DENY);
267     }
268
269     @SuppressWarnings("unchecked")
270     private void insertOperationEvent(DecisionRequest request, String outcome) {
271         //
272         // Get the properties
273         //
274         Map<String, Object> properties = (Map<String, Object>) request.getResource().get("guard");
275         //
276         // Add an entry
277         //
278         Dbao newEntry = new Dbao();
279         newEntry.setActor(properties.get("actor").toString());
280         newEntry.setOperation(properties.get("recipe").toString());
281         newEntry.setClosedLoopName(properties.get("clname").toString());
282         newEntry.setOutcome(outcome);
283         newEntry.setStarttime(Date.from(Instant.now().minusMillis(20000)));
284         newEntry.setEndtime(Date.from(Instant.now()));
285         newEntry.setRequestId(UUID.randomUUID().toString());
286         newEntry.setTarget(properties.get("target").toString());
287         em.getTransaction().begin();
288         em.persist(newEntry);
289         em.getTransaction().commit();
290     }
291
292     /**
293      * Close the entity manager.
294      */
295     @AfterClass
296     public static void cleanup() throws Exception {
297         if (em != null) {
298             em.close();
299         }
300     }
301 }