a9f0a04e47eb3c531efd171e378c4dd696b0379b
[policy/drools-applications.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * demo
4  * ================================================================================
5  * Copyright (C) 2018-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  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.template.demo.clc;
22
23 import static org.junit.Assert.fail;
24
25 import java.io.BufferedReader;
26 import java.io.File;
27 import java.io.FileInputStream;
28 import java.io.FileReader;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.PrintWriter;
32 import java.nio.charset.StandardCharsets;
33 import java.nio.file.Files;
34 import java.nio.file.Path;
35 import java.nio.file.Paths;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.UUID;
39 import java.util.regex.Matcher;
40 import java.util.regex.Pattern;
41 import java.util.stream.Stream;
42 import javax.persistence.EntityManager;
43 import javax.persistence.EntityManagerFactory;
44 import javax.persistence.Persistence;
45 import javax.persistence.Query;
46 import org.apache.commons.io.IOUtils;
47 import org.kie.api.KieServices;
48 import org.kie.api.builder.KieBuilder;
49 import org.kie.api.builder.KieFileSystem;
50 import org.kie.api.builder.Message;
51 import org.kie.api.builder.ReleaseId;
52 import org.kie.api.builder.Results;
53 import org.kie.api.runtime.KieContainer;
54 import org.kie.api.runtime.KieSession;
55 import org.onap.policy.common.endpoints.http.server.HttpServletServer;
56 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
57 import org.onap.policy.controlloop.policy.guard.ControlLoopGuard;
58 import org.onap.policy.controlloop.policy.guard.ControlLoopGuard;
59 import org.onap.policy.coordination.CoordinationDirective;
60 import org.onap.policy.drools.system.PolicyEngine;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63 import org.yaml.snakeyaml.Yaml;
64 import org.yaml.snakeyaml.constructor.Constructor;
65
66
67 public final class SupportUtil {
68
69     private static final String OPSHISTPUPROP = "OperationsHistoryPU";
70     private static final Logger logger = LoggerFactory.getLogger(SupportUtil.class);
71
72     // values from the last call to buildContainer()
73
74     private static KieServices kieServices;
75     private static KieContainer keyContainer;
76
77     public static class Pair<A, B> {
78         public final A first;
79         public final B second;
80
81         public Pair(A first, B second) {
82             this.first = first;
83             this.second = second;
84         }
85     }
86
87     /**
88      * Load YAML.
89      *
90      * @param testFile test file to load
91      * @return the Pair of a policy and the yaml contents
92      */
93     public static Pair<ControlLoopPolicy, String> loadYaml(String testFile) {
94         try (InputStream is = new FileInputStream(new File(testFile))) {
95             String contents = IOUtils.toString(is, StandardCharsets.UTF_8);
96             //
97             // Read the yaml into our Java Object
98             //
99             Yaml yaml = new Yaml(new Constructor(ControlLoopPolicy.class));
100             Object obj = yaml.load(contents);
101
102             logger.debug(contents);
103
104             return new Pair<ControlLoopPolicy, String>((ControlLoopPolicy) obj, contents);
105         } catch (IOException e) {
106             logger.error("Error while loading YAML", e);
107             fail(e.getLocalizedMessage());
108         }
109         return null;
110     }
111
112     /**
113      * Load the YAML guard policy.
114      *
115      * @param testFile the test file to load
116      * @return return the guard object
117      */
118     public static ControlLoopGuard loadYamlGuard(String testFile) {
119         try (InputStream is = new FileInputStream(new File(testFile))) {
120             String contents = IOUtils.toString(is, StandardCharsets.UTF_8);
121             //
122             // Read the yaml into our Java Object
123             //
124             Yaml yaml = new Yaml(new Constructor(ControlLoopGuard.class));
125             Object obj = yaml.load(contents);
126             return (ControlLoopGuard) obj;
127         } catch (IOException e) {
128             logger.error("Error while loading YAML guard", e);
129             fail(e.getLocalizedMessage());
130         }
131         return null;
132     }
133
134     /**
135      * Insert the Xacml policy into the PDP.
136      * Achieved by configuring the properties file to load the Xacml policy and required PIP(s).
137      *
138      * @param xacmlFile the Xacml policy file's path
139      * @param propProtoDir the directory containing Xacml implementation prototypes
140      * @param propDir the directory to which the Xacml rule should be output
141      */
142     public static void insertXacmlPolicy(String xacmlFile,
143                                          String propProtoDir,
144                                          String propDir) {
145         String propName = "xacml_guard_clc";
146         String propProtoFile = propProtoDir + File.separator + propName + ".properties";
147         String propFilename = propDir + File.separator + propName + ".properties";
148
149         String addXacmlFileToRoot = "# Policies to load\n"
150             + "xacml.rootPolicies=p1\n"
151             + "p1.file=" + xacmlFile + "\n";
152
153         File propFile = new File(propFilename);
154         try (Stream<String> stream = Files.lines(Paths.get(propProtoFile));
155              PrintWriter output = new PrintWriter(propFile)) {
156             /*
157              * Remove file after test
158              */
159             propFile.deleteOnExit();
160             /*
161              * Copy the property prototype
162              */
163             stream.forEach(output::println);
164             /*
165              * Add the Xacml policy to the set of root policies
166              */
167             output.println(addXacmlFileToRoot);
168             /*
169              * Obtain PIP Engine definitions from Xacml policy
170              * and insert into property file.
171              */
172             try (BufferedReader br = new BufferedReader(new FileReader(xacmlFile))) {
173                 boolean select = false;
174                 for (String line; (line = br.readLine()) != null; ) {
175                     if (line.contains("PIP Engine Definition")) {
176                         select = true;
177                     }
178                     if (line.contains("-->")) {
179                         select = false;
180                     }
181                     if (select) {
182                         output.println(line);
183                     }
184                 }
185             }
186         } catch (Exception e) {
187             logger.error("Error when trying to create test propery file", e);
188             fail(e.getMessage());
189         }
190     }
191
192     public static HttpServletServer buildAaiSim() throws InterruptedException, IOException {
193         return org.onap.policy.simulators.Util.buildAaiSim();
194     }
195
196     /**
197      * Build a container containing a single set of rules.
198      *
199      * @param droolsTemplate template
200      * @param closedLoopControlName control loop id
201      * @param policyScope policy scope
202      * @param policyName policy name
203      * @param policyVersion policy version
204      * @param yamlSpecification incoming yaml specification
205      * @return the Kie session
206      * @throws IOException if the container cannot be built
207      */
208     public static KieSession buildContainer(String droolsTemplate, String closedLoopControlName, String policyScope,
209                     String policyName, String policyVersion, String yamlSpecification) throws IOException {
210
211         RuleSpec spec = new RuleSpec(droolsTemplate, closedLoopControlName, policyScope, policyName, policyVersion,
212                         yamlSpecification);
213
214         return buildContainer(policyVersion, new RuleSpec[] {spec});
215     }
216
217     /**
218      * Build a container containing all of the specified rules.
219      *
220      * @param policyVersion policy version
221      * @param specifications rule specifications
222      * @return the Kie session
223      * @throws IOException if the container cannot be built
224      */
225     public static KieSession buildContainer(String policyVersion, RuleSpec[] specifications) throws IOException {
226         //
227         // Get our Drools Kie factory
228         //
229         kieServices = KieServices.Factory.get();
230
231         ReleaseId releaseId = buildPolicy(policyVersion, specifications);
232         logger.debug(releaseId.toString());
233
234         //
235         // Create our kie Session and container
236         //
237         keyContainer = kieServices.newKieContainer(releaseId);
238
239         return keyContainer.newKieSession();
240     }
241
242     /**
243      * Update the container with new rules.
244      *
245      * @param policyVersion new policy version
246      * @param specifications new rule specifications
247      * @throws IOException if the container cannot be built
248      */
249     public static void updateContainer(String policyVersion, RuleSpec[] specifications) throws IOException {
250         ReleaseId releaseId = buildPolicy(policyVersion, specifications);
251         logger.debug(releaseId.toString());
252
253         keyContainer.updateToVersion(releaseId);
254     }
255
256     /**
257      * Build the Policy so it can be loaded into a KIE container.
258      *
259      * @param policyVersion policy version
260      * @param specifications rule specifications
261      * @return the release
262      * @throws IOException if the container cannot be built
263      */
264     private static ReleaseId buildPolicy(String policyVersion, RuleSpec[] specifications) throws IOException {
265         //
266         // Generate our drools rule from our template
267         //
268         KieFileSystem kfs = kieServices.newKieFileSystem();
269         ReleaseId releaseId = kieServices.getRepository().getDefaultReleaseId();
270         releaseId = kieServices.newReleaseId(releaseId.getGroupId(), releaseId.getArtifactId(), policyVersion);
271
272         kfs.generateAndWritePomXML(releaseId);
273
274         for (RuleSpec spec : specifications) {
275             String drlContents = spec.generateRules();
276             kfs.write("src/main/resources/" + spec.policyName + ".drl",
277                             kieServices.getResources().newByteArrayResource(drlContents.getBytes()));
278         }
279
280         //
281         // Compile the rule
282         //
283         KieBuilder builder = kieServices.newKieBuilder(kfs).buildAll();
284         Results results = builder.getResults();
285         if (results.hasMessages(Message.Level.ERROR)) {
286             for (Message msg : results.getMessages()) {
287                 logger.error(msg.toString());
288             }
289             throw new RuntimeException("Drools Rule has Errors");
290         }
291         for (Message msg : results.getMessages()) {
292             logger.debug(msg.toString());
293         }
294
295         return releaseId;
296     }
297
298     /**
299      *  Set the A&AI properties.
300      */
301     public static void setAaiProps() {
302         PolicyEngine.manager.setEnvironmentProperty("aai.url", "http://localhost:6666");
303         PolicyEngine.manager.setEnvironmentProperty("aai.username", "AAI");
304         PolicyEngine.manager.setEnvironmentProperty("aai.password", "AAI");
305     }
306
307     /**
308      *  Set the Guard properties to use embedded XACML PDPEngine.
309      */
310     public static void setGuardPropsEmbedded() {
311         /*
312          * Guard PDP-x connection Properties. No URL specified -> use embedded PDPEngine.
313          */
314         PolicyEngine.manager.setEnvironmentProperty("prop.guard.propfile",
315                                                     "src/test/resources/properties/xacml_guard_clc.properties");
316         PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_USER,        "python");
317         PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_PASS,        "test");
318         PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_CLIENT_USER, "python");
319         PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_CLIENT_PASS, "test");
320         PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_ENV,         "TEST");
321         PolicyEngine.manager.setEnvironmentProperty(org.onap.policy.guard.Util.PROP_GUARD_DISABLED,    "false");
322     }
323
324     /**
325      *  Set the operation history properties.
326      */
327     public static void setPuProp() {
328         System.setProperty(OPSHISTPUPROP, "TestOperationsHistoryPU");
329     }
330
331     /**
332      * Dump the contents of the History database.
333      *
334      * @return a list of the database entries
335      */
336     public static List<?> dumpDb() {
337         //
338         // Connect to in-mem db
339         //
340         EntityManagerFactory emf = Persistence.createEntityManagerFactory("TestOperationsHistoryPU");
341         EntityManager em = emf.createEntityManager();
342         //
343         // Create query
344         //
345         String sql = "select * from operationshistory10";
346         Query nq = em.createNativeQuery(sql);
347         List<?> results = null;
348         //
349         // Execute query
350         //
351         try {
352             results = nq.getResultList();
353         } catch (Exception ex) {
354             logger.error("getStatusFromDB threw: ", ex);
355             //
356             // Clean up and return null
357             //
358             em.close();
359             emf.close();
360             return null;
361         }
362         //
363         // Clean up and return results
364         //
365         em.close();
366         emf.close();
367         return results;
368     }
369
370     /**
371      * Rule specification.
372      */
373     public static class RuleSpec {
374         private String droolsTemplate;
375         private String closedLoopControlName;
376         private String policyScope;
377         private String policyName;
378         private String policyVersion;
379         private String yamlSpecification;
380
381         /**
382          * Constructs the object.
383          *
384          * @param droolsTemplate template
385          * @param closedLoopControlName control loop id
386          * @param policyScope policy scope
387          * @param policyName policy name
388          * @param policyVersion policy version
389          * @param yamlSpecification incoming yaml specification
390          */
391         public RuleSpec(String droolsTemplate, String closedLoopControlName, String policyScope, String policyName,
392                         String policyVersion, String yamlSpecification) {
393
394             this.droolsTemplate = droolsTemplate;
395             this.closedLoopControlName = closedLoopControlName;
396             this.policyScope = policyScope;
397             this.policyName = policyName;
398             this.policyVersion = policyVersion;
399             this.yamlSpecification = yamlSpecification;
400         }
401
402         /**
403          * Generates the rules by reading the template and making variable substitutions.
404          *
405          * @return the rules
406          * @throws IOException if an error occurs
407          */
408         private String generateRules() throws IOException {
409             Path rule = Paths.get(droolsTemplate);
410             String ruleTemplate = new String(Files.readAllBytes(rule));
411
412             Pattern pattern = Pattern.compile("\\$\\{closedLoopControlName\\}");
413             Matcher matcher = pattern.matcher(ruleTemplate);
414             ruleTemplate = matcher.replaceAll(closedLoopControlName);
415
416             pattern = Pattern.compile("\\$\\{policyScope\\}");
417             matcher = pattern.matcher(ruleTemplate);
418             ruleTemplate = matcher.replaceAll(policyScope);
419
420             pattern = Pattern.compile("\\$\\{policyName\\}");
421             matcher = pattern.matcher(ruleTemplate);
422             ruleTemplate = matcher.replaceAll(policyName);
423
424             pattern = Pattern.compile("\\$\\{policyVersion\\}");
425             matcher = pattern.matcher(ruleTemplate);
426             ruleTemplate = matcher.replaceAll(policyVersion);
427
428             pattern = Pattern.compile("\\$\\{controlLoopYaml\\}");
429             matcher = pattern.matcher(ruleTemplate);
430             ruleTemplate = matcher.replaceAll(yamlSpecification);
431
432             return ruleTemplate;
433         }
434     }
435 }