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);