2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.onap.policy.template.demo.clc;
23 import static org.junit.Assert.fail;
25 import java.io.BufferedReader;
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;
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;
67 public final class SupportUtil {
69 private static final String OPSHISTPUPROP = "OperationsHistoryPU";
70 private static final Logger logger = LoggerFactory.getLogger(SupportUtil.class);
72 // values from the last call to buildContainer()
74 private static KieServices kieServices;
75 private static KieContainer keyContainer;
77 public static class Pair<A, B> {
79 public final B second;
81 public Pair(A first, B second) {
90 * @param testFile test file to load
91 * @return the Pair of a policy and the yaml contents
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);
97 // Read the yaml into our Java Object
99 Yaml yaml = new Yaml(new Constructor(ControlLoopPolicy.class));
100 Object obj = yaml.load(contents);
102 logger.debug(contents);
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());
113 * Load the YAML guard policy.
115 * @param testFile the test file to load
116 * @return return the guard object
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);
122 // Read the yaml into our Java Object
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());
135 * Insert the Xacml policy into the PDP.
136 * Achieved by configuring the properties file to load the Xacml policy and required PIP(s).
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
142 public static void insertXacmlPolicy(String xacmlFile,
145 String propName = "xacml_guard_clc";
146 String propProtoFile = propProtoDir + File.separator + propName + ".properties";
147 String propFilename = propDir + File.separator + propName + ".properties";
149 String addXacmlFileToRoot = "# Policies to load\n"
150 + "xacml.rootPolicies=p1\n"
151 + "p1.file=" + xacmlFile + "\n";
153 File propFile = new File(propFilename);
154 try (Stream<String> stream = Files.lines(Paths.get(propProtoFile));
155 PrintWriter output = new PrintWriter(propFile)) {
157 * Remove file after test
159 propFile.deleteOnExit();
161 * Copy the property prototype
163 stream.forEach(output::println);
165 * Add the Xacml policy to the set of root policies
167 output.println(addXacmlFileToRoot);
169 * Obtain PIP Engine definitions from Xacml policy
170 * and insert into property file.
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")) {
178 if (line.contains("-->")) {
182 output.println(line);
186 } catch (Exception e) {
187 logger.error("Error when trying to create test propery file", e);
188 fail(e.getMessage());
192 public static HttpServletServer buildAaiSim() throws InterruptedException, IOException {
193 return org.onap.policy.simulators.Util.buildAaiSim();
197 * Build a container containing a single set of rules.
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
208 public static KieSession buildContainer(String droolsTemplate, String closedLoopControlName, String policyScope,
209 String policyName, String policyVersion, String yamlSpecification) throws IOException {
211 RuleSpec spec = new RuleSpec(droolsTemplate, closedLoopControlName, policyScope, policyName, policyVersion,
214 return buildContainer(policyVersion, new RuleSpec[] {spec});
218 * Build a container containing all of the specified rules.
220 * @param policyVersion policy version
221 * @param specifications rule specifications
222 * @return the Kie session
223 * @throws IOException if the container cannot be built
225 public static KieSession buildContainer(String policyVersion, RuleSpec[] specifications) throws IOException {
227 // Get our Drools Kie factory
229 kieServices = KieServices.Factory.get();
231 ReleaseId releaseId = buildPolicy(policyVersion, specifications);
232 logger.debug(releaseId.toString());
235 // Create our kie Session and container
237 keyContainer = kieServices.newKieContainer(releaseId);
239 return keyContainer.newKieSession();
243 * Update the container with new rules.
245 * @param policyVersion new policy version
246 * @param specifications new rule specifications
247 * @throws IOException if the container cannot be built
249 public static void updateContainer(String policyVersion, RuleSpec[] specifications) throws IOException {
250 ReleaseId releaseId = buildPolicy(policyVersion, specifications);
251 logger.debug(releaseId.toString());
253 keyContainer.updateToVersion(releaseId);
257 * Build the Policy so it can be loaded into a KIE container.
259 * @param policyVersion policy version
260 * @param specifications rule specifications
261 * @return the release
262 * @throws IOException if the container cannot be built
264 private static ReleaseId buildPolicy(String policyVersion, RuleSpec[] specifications) throws IOException {
266 // Generate our drools rule from our template
268 KieFileSystem kfs = kieServices.newKieFileSystem();
269 ReleaseId releaseId = kieServices.getRepository().getDefaultReleaseId();
270 releaseId = kieServices.newReleaseId(releaseId.getGroupId(), releaseId.getArtifactId(), policyVersion);
272 kfs.generateAndWritePomXML(releaseId);
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()));
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());
289 throw new RuntimeException("Drools Rule has Errors");
291 for (Message msg : results.getMessages()) {
292 logger.debug(msg.toString());
299 * Set the A&AI properties.
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");
308 * Set the Guard properties to use embedded XACML PDPEngine.
310 public static void setGuardPropsEmbedded() {
312 * Guard PDP-x connection Properties. No URL specified -> use embedded PDPEngine.
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");
325 * Set the operation history properties.
327 public static void setPuProp() {
328 System.setProperty(OPSHISTPUPROP, "TestOperationsHistoryPU");
332 * Dump the contents of the History database.
334 * @return a list of the database entries
336 public static List<?> dumpDb() {
338 // Connect to in-mem db
340 EntityManagerFactory emf = Persistence.createEntityManagerFactory("TestOperationsHistoryPU");
341 EntityManager em = emf.createEntityManager();
345 String sql = "select * from operationshistory10";
346 Query nq = em.createNativeQuery(sql);
347 List<?> results = null;
352 results = nq.getResultList();
353 } catch (Exception ex) {
354 logger.error("getStatusFromDB threw: ", ex);
356 // Clean up and return null
363 // Clean up and return results
371 * Rule specification.
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;
382 * Constructs the object.
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
391 public RuleSpec(String droolsTemplate, String closedLoopControlName, String policyScope, String policyName,
392 String policyVersion, String yamlSpecification) {
394 this.droolsTemplate = droolsTemplate;
395 this.closedLoopControlName = closedLoopControlName;
396 this.policyScope = policyScope;
397 this.policyName = policyName;
398 this.policyVersion = policyVersion;
399 this.yamlSpecification = yamlSpecification;
403 * Generates the rules by reading the template and making variable substitutions.
406 * @throws IOException if an error occurs
408 private String generateRules() throws IOException {
409 Path rule = Paths.get(droolsTemplate);
410 String ruleTemplate = new String(Files.readAllBytes(rule));
412 Pattern pattern = Pattern.compile("\\$\\{closedLoopControlName\\}");
413 Matcher matcher = pattern.matcher(ruleTemplate);
414 ruleTemplate = matcher.replaceAll(closedLoopControlName);
416 pattern = Pattern.compile("\\$\\{policyScope\\}");
417 matcher = pattern.matcher(ruleTemplate);
418 ruleTemplate = matcher.replaceAll(policyScope);
420 pattern = Pattern.compile("\\$\\{policyName\\}");
421 matcher = pattern.matcher(ruleTemplate);
422 ruleTemplate = matcher.replaceAll(policyName);
424 pattern = Pattern.compile("\\$\\{policyVersion\\}");
425 matcher = pattern.matcher(ruleTemplate);
426 ruleTemplate = matcher.replaceAll(policyVersion);
428 pattern = Pattern.compile("\\$\\{controlLoopYaml\\}");
429 matcher = pattern.matcher(ruleTemplate);
430 ruleTemplate = matcher.replaceAll(yamlSpecification);