From 0ae7ecd47fd76921e8e1137739497578fe703354 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Tue, 26 Jan 2021 21:06:24 +0100 Subject: Better main(). * Moving templates into their respective modules. * Supporting export type-based filtering. Probably not perfect. --- .../main/java/io/trygvis/rules/engine/DbIo.java | 41 +++++++++++------- .../main/java/io/trygvis/rules/engine/Engine.java | 48 +++++++++++++++++++++- .../rules/engine/JinjavaTemplateEngine.java | 10 +++-- .../io/trygvis/rules/engine/TemplateEngine.java | 5 +++ .../io/trygvis/rules/engine/cli/RunCommand.java | 46 +++++++++++++++++---- .../io/trygvis/rules/engine/AcmeAppsTestMain.java | 19 +++++++++ .../rules/engine/AcmeWireguardTestMain.java | 27 ++++++++++++ .../io/trygvis/rules/engine/WireguardTestMain.java | 19 --------- 8 files changed, 168 insertions(+), 47 deletions(-) create mode 100644 module/ri-engine/src/test/java/io/trygvis/rules/engine/AcmeAppsTestMain.java create mode 100644 module/ri-engine/src/test/java/io/trygvis/rules/engine/AcmeWireguardTestMain.java delete mode 100644 module/ri-engine/src/test/java/io/trygvis/rules/engine/WireguardTestMain.java (limited to 'module/ri-engine/src') diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/DbIo.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/DbIo.java index d3d309a..e2abd5a 100644 --- a/module/ri-engine/src/main/java/io/trygvis/rules/engine/DbIo.java +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/DbIo.java @@ -14,9 +14,10 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; import org.drools.core.common.DefaultFactHandle; import org.drools.core.factmodel.GeneratedFact; import org.kie.api.KieBase; -import org.kie.api.definition.type.FactType; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.rule.FactHandle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileWriter; @@ -27,6 +28,8 @@ import java.util.function.Function; @SuppressWarnings("unchecked") public class DbIo { + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final ObjectMapper mapper; private static final List prioritizedKeys = List.of("key", "name", "fqdn"); @@ -268,9 +271,9 @@ public class DbIo { } } - private static class DbClassLoader extends ClassLoader { - private final KieBase kieBase; + private class DbClassLoader extends ClassLoader { private final KieContainer container; + private final KieBase kieBase; public DbClassLoader(KieContainer container, KieBase kieBase) { this.container = container; @@ -279,35 +282,43 @@ public class DbIo { @Override public Class loadClass(String name) throws ClassNotFoundException { + logger.info("Loading class {}", name); try { - return super.loadClass(name); + var klass = super.loadClass(name); + logger.info("Found class in super classloader"); + return klass; } catch (ClassNotFoundException e) { var i = name.lastIndexOf('.'); - String pkg, klass; + String pkg, simpleName; if (i == -1) { pkg = null; - klass = name; + simpleName = name; } else { pkg = name.substring(0, i); - klass = name.substring(i + 1); + simpleName = name.substring(i + 1); } try { - return container.getClassLoader().loadClass(name); + var klass = container.getClassLoader().loadClass(name); + logger.info("Found class in container's classloader"); + return klass; } catch (ClassNotFoundException ignore) { } - FactType clazz = null; try { - clazz = kieBase.getFactType(pkg, klass); + logger.info("pkg = {}", pkg); + logger.info("simpleName = {}", simpleName); + var clazz = kieBase.getFactType(pkg, simpleName); + if (clazz != null) { + logger.info("Found class as a FactType"); + return clazz.getFactClass(); + } } catch (UnsupportedOperationException ignore) { - System.out.println("AcmeClassLoader.loadClass: " + name); - } - if (clazz == null) { - throw e; } - return clazz.getFactClass(); + logger.warn("Class not found: {}", name); + + throw e; } } } diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/Engine.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/Engine.java index f73419a..4a49ca2 100644 --- a/module/ri-engine/src/main/java/io/trygvis/rules/engine/Engine.java +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/Engine.java @@ -1,6 +1,7 @@ package io.trygvis.rules.engine; import org.drools.core.audit.WorkingMemoryConsoleLogger; +import org.drools.reflective.classloader.ProjectClassLoader; import org.kie.api.KieServices; import org.kie.api.event.rule.AgendaEventListener; import org.kie.api.event.rule.RuleRuntimeEventListener; @@ -12,10 +13,16 @@ import org.slf4j.LoggerFactory; import java.io.Closeable; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import static io.trygvis.rules.engine.TemplateEngine.TemplateLoader; + public class Engine implements Closeable { private final Logger logger = LoggerFactory.getLogger(getClass()); @@ -33,8 +40,10 @@ public class Engine implements Closeable { logger.info("kieRepository.getDefaultReleaseId() = {}", kieRepository.getDefaultReleaseId()); KieContainer container; + TemplateLoader templateLoader; if (modules != null && modules.length > 0) { List resources = new ArrayList<>(); + List files = new ArrayList<>(); for (File path : modules) { if (!path.exists()) { logger.warn("Module path does not exist: {}", path.getAbsolutePath()); @@ -43,6 +52,10 @@ public class Engine implements Closeable { logger.info("New KieBuilder: {}, file={}, directory={}", path, path.isFile(), path.isDirectory()); + if (path.isFile()) { + files.add(path.toURI().toURL()); + } + var resource = services.getResources().newFileSystemResource(path); logger.info("resource.getResourceType() = {}", resource.getResourceType()); resources.add(resource); @@ -54,8 +67,12 @@ public class Engine implements Closeable { logger.info("Creating classpath container, releaseId=" + rId); container = services.newKieContainer(rId); + + templateLoader = new ClasspathTemplateLoader(new URLClassLoader(files.toArray(new URL[0]))); } else { - container = services.getKieClasspathContainer(); + var classLoader = ProjectClassLoader.findParentClassLoader(); + container = services.getKieClasspathContainer(classLoader); + templateLoader = new ClasspathTemplateLoader(classLoader); } logger.info("Creating KieBase \"{}\"", name); @@ -68,11 +85,17 @@ public class Engine implements Closeable { session.addEventListener((AgendaEventListener) l); session.addEventListener((RuleRuntimeEventListener) l); - session.setGlobal("te", new JinjavaTemplateEngine(output)); + session.setGlobal("te", new JinjavaTemplateEngine(templateLoader, output)); logger.info("Loading data"); io = new DbIo(container, kieBase); var objects = io.load(database); + + if (objects.isEmpty()) { + logger.warn("Did not load any objects, something is wrong"); + return; + } + logger.info("Loaded {} objects", objects.size()); for (var object : objects) { @@ -91,4 +114,25 @@ public class Engine implements Closeable { public void close() { session.dispose(); } + + private static class ClasspathTemplateLoader implements TemplateLoader { + private final ClassLoader classLoader; + + private ClasspathTemplateLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + @Override + public String load(String name) throws IOException { + var resource = "templates/" + name + ".j2"; + + try (var inputStream = classLoader.getResourceAsStream(resource)) { + if (inputStream == null) { + throw new FileNotFoundException("Classpath resource: " + resource); + } + + return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + } + } + } } diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/JinjavaTemplateEngine.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/JinjavaTemplateEngine.java index 42b2127..286029e 100644 --- a/module/ri-engine/src/main/java/io/trygvis/rules/engine/JinjavaTemplateEngine.java +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/JinjavaTemplateEngine.java @@ -7,15 +7,19 @@ import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.nio.file.Files; -import java.nio.file.Path; import java.util.Map; +/** + * TODO: cache templates. + */ public class JinjavaTemplateEngine implements TemplateEngine { private final Jinjava jinjava = new Jinjava(); + private final TemplateLoader loader; private final File basedir; - public JinjavaTemplateEngine(File basedir) { + public JinjavaTemplateEngine(TemplateLoader templateLoader, File basedir) { + this.loader = templateLoader; this.basedir = basedir; } @@ -31,7 +35,7 @@ public class JinjavaTemplateEngine implements TemplateEngine { @Override public void template(String name, String output, Map params) throws IOException { - var template = Files.readString(Path.of("j2", name + ".j2")); + var template = loader.load(name); String renderedTemplate = jinjava.render(template, params); var f = new File(basedir, output); FileUtil.createMissingParentDirectories(f); diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/TemplateEngine.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/TemplateEngine.java index eafa6e4..a2ae0c2 100644 --- a/module/ri-engine/src/main/java/io/trygvis/rules/engine/TemplateEngine.java +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/TemplateEngine.java @@ -1,5 +1,6 @@ package io.trygvis.rules.engine; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.Map; @@ -7,4 +8,8 @@ public interface TemplateEngine { void clean(); void template(String name, String output, Map params) throws IOException; + + interface TemplateLoader { + String load(String name) throws IOException; + } } diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/RunCommand.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/RunCommand.java index 2b016f2..203a9b0 100644 --- a/module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/RunCommand.java +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/RunCommand.java @@ -20,14 +20,18 @@ public class RunCommand implements Callable { @Option(names = {"--output-state"}) public File outputState; + @Option(names = {"--include"}, split = ",", arity = "1..*") + public String[] includes; + @Option(names = {"--generated-output"}) public File generatedOutput; @Option(names = {"--agenda-groups"}) public String[] agendaGroups; - @Option(names = {"--modules"}, split = ",", arity = "1..*") - public File[] modules; + // TODO: Remove --modules + @Option(names = {"--modules", "--module"}, split = ",", arity = "1..*") + public File[] module; @Override public Integer call() throws Exception { @@ -36,13 +40,39 @@ public class RunCommand implements Callable { agendaGroups = new String[]{"init", "generate"}; } - try (var engine = new Engine(name, input, generatedOutput, agendaGroups, modules)) { + try (var engine = new Engine(name, input, generatedOutput, agendaGroups, module)) { engine.io.dump(outputState, engine.session.getFactHandles(), (Object o) -> - o.getClass().getName().contains("Wg") || - o.getClass().getSimpleName().contains("Machine") || - o.getClass().getSimpleName().contains("DnsEntry") || - o.getClass().getSimpleName().contains("Ipv4Cidr") || - o.getClass().getSimpleName().contains("Ipv4Address") + { + if (includes == null || includes.length == 0) { + return true; + } + + var name = o.getClass().getName(); + var simpleName = o.getClass().getSimpleName(); + + for (var i : includes) { + var ok = false; + if (i.startsWith("*")) { + i = i.substring(1); + + if (i.endsWith("*")) { + i = i.substring(1, i.length() - 2); + ok = name.contains(i); + } else { + ok = name.startsWith(i) || simpleName.startsWith(i); + } + } else if (i.endsWith("*")) { + i = i.substring(0, i.length() - 2); + ok = name.startsWith(i) || simpleName.startsWith(i); + } + + if (ok) { + return true; + } + } + + return false; + } ); } diff --git a/module/ri-engine/src/test/java/io/trygvis/rules/engine/AcmeAppsTestMain.java b/module/ri-engine/src/test/java/io/trygvis/rules/engine/AcmeAppsTestMain.java new file mode 100644 index 0000000..17b7950 --- /dev/null +++ b/module/ri-engine/src/test/java/io/trygvis/rules/engine/AcmeAppsTestMain.java @@ -0,0 +1,19 @@ +package io.trygvis.rules.engine; + +import io.trygvis.rules.engine.cli.RunCommand; + +import java.io.File; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class AcmeAppsTestMain { + public static void main(String[] args) throws Exception { + var c = new RunCommand(); + c.name = "acme-apps"; + c.input = new File("acme.yaml"); + c.outputState = new File("out/acme/apps.yaml"); + c.agendaGroups = new String[]{"init", "generate"}; + c.generatedOutput = new File("acme-apps"); + assertEquals(0, c.call()); + } +} diff --git a/module/ri-engine/src/test/java/io/trygvis/rules/engine/AcmeWireguardTestMain.java b/module/ri-engine/src/test/java/io/trygvis/rules/engine/AcmeWireguardTestMain.java new file mode 100644 index 0000000..2bb5513 --- /dev/null +++ b/module/ri-engine/src/test/java/io/trygvis/rules/engine/AcmeWireguardTestMain.java @@ -0,0 +1,27 @@ +package io.trygvis.rules.engine; + +import io.trygvis.rules.engine.cli.RunCommand; + +import java.io.File; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class AcmeWireguardTestMain { + public static void main(String[] args) throws Exception { + var c = new RunCommand(); + c.name = "acme-wireguard"; + c.input = new File("acme.yaml"); + c.outputState = new File("out/acme/wireguard.yaml"); + c.agendaGroups = new String[]{"init", "generate"}; + c.generatedOutput = new File("acme-wireguard"); + c.includes = new String[]{ + "Wg*", + "Machine", + "DnsEntry", + "Ipv4Cidr", + "Ipv4Address", + }; + + assertEquals(0, c.call()); + } +} diff --git a/module/ri-engine/src/test/java/io/trygvis/rules/engine/WireguardTestMain.java b/module/ri-engine/src/test/java/io/trygvis/rules/engine/WireguardTestMain.java deleted file mode 100644 index 20aeffa..0000000 --- a/module/ri-engine/src/test/java/io/trygvis/rules/engine/WireguardTestMain.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.trygvis.rules.engine; - -import io.trygvis.rules.engine.cli.RunCommand; - -import java.io.File; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class WireguardTestMain { - public static void main(String[] args) throws Exception { - var c = new RunCommand(); - c.name = "acme"; - c.input = new File("acme.yaml"); - c.outputState = new File("out/acme/wireguard.yaml"); - c.agendaGroups = new String[]{"init", "generate"}; - c.generatedOutput = new File("acme-wireguard"); - assertEquals(0, c.call()); - } -} -- cgit v1.2.3