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. --- engine | 11 +++++ j2/dba/cluster.j2 | 19 --------- j2/platform-ansible.j2 | 6 --- j2/terraform-machine-outputs.j2 | 7 ---- j2/terraform-machine.j2 | 19 --------- j2/terraform-main-scaleway-machine.j2 | 19 --------- j2/terraform-record-set.j2 | 8 ---- j2/wireguard/ansible-host.j2 | 8 ---- j2/wireguard/ansible.j2 | 6 --- j2/wireguard/inventory.j2 | 7 ---- .../acme/src/main/resources/META-INF/kmodule.xml | 2 +- .../rules/machine/MachineSpecification.java | 6 ++- .../io/trygvis/rules/terraform/terraform.drl | 6 +-- .../src/main/resources/templates/dba/cluster.j2 | 19 +++++++++ .../main/resources/templates/platform-ansible.j2 | 6 +++ .../templates/terraform/machine-outputs.j2 | 7 ++++ .../main/resources/templates/terraform/machine.j2 | 19 +++++++++ .../templates/terraform/main-scaleway-machine.j2 | 19 +++++++++ .../resources/templates/terraform/record-set.j2 | 8 ++++ .../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 --------- .../resources/templates/wireguard/ansible-host.j2 | 8 ++++ .../main/resources/templates/wireguard/ansible.j2 | 6 +++ .../resources/templates/wireguard/inventory.j2 | 7 ++++ out/acme/apps.yaml | 44 ++++++++++++++++++-- 31 files changed, 327 insertions(+), 155 deletions(-) create mode 100755 engine delete mode 100644 j2/dba/cluster.j2 delete mode 100644 j2/platform-ansible.j2 delete mode 100644 j2/terraform-machine-outputs.j2 delete mode 100644 j2/terraform-machine.j2 delete mode 100644 j2/terraform-main-scaleway-machine.j2 delete mode 100644 j2/terraform-record-set.j2 delete mode 100644 j2/wireguard/ansible-host.j2 delete mode 100644 j2/wireguard/ansible.j2 delete mode 100644 j2/wireguard/inventory.j2 create mode 100644 module/ri-base/src/main/resources/templates/dba/cluster.j2 create mode 100644 module/ri-base/src/main/resources/templates/platform-ansible.j2 create mode 100644 module/ri-base/src/main/resources/templates/terraform/machine-outputs.j2 create mode 100644 module/ri-base/src/main/resources/templates/terraform/machine.j2 create mode 100644 module/ri-base/src/main/resources/templates/terraform/main-scaleway-machine.j2 create mode 100644 module/ri-base/src/main/resources/templates/terraform/record-set.j2 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 create mode 100644 module/ri-wireguard/src/main/resources/templates/wireguard/ansible-host.j2 create mode 100644 module/ri-wireguard/src/main/resources/templates/wireguard/ansible.j2 create mode 100644 module/ri-wireguard/src/main/resources/templates/wireguard/inventory.j2 diff --git a/engine b/engine new file mode 100755 index 0000000..4444143 --- /dev/null +++ b/engine @@ -0,0 +1,11 @@ +#!/bin/bash + +set -euo pipefail + +basedir="$(dirname $0)" +jar="$(echo $basedir/module/ri-engine/target/ri-engine-*-fat.jar)" + +exec java \ + --enable-preview \ + -jar "$jar" \ + "${@}" diff --git a/j2/dba/cluster.j2 b/j2/dba/cluster.j2 deleted file mode 100644 index 045fbcd..0000000 --- a/j2/dba/cluster.j2 +++ /dev/null @@ -1,19 +0,0 @@ -# Generated - -# cluster: {{ cluster.name }} -{%- for m, containers in containersByMachine.entrySet() %} ---- -- host: - - {{ m.name }} - tasks: - import_role: - name: docker-service - vars: - template: | - version: "3" - services: -{%- for c in containers %} - {{ c.name }}: - image: {{ c.image }}:{{ c.tag }} -{%- endfor %} -{% endfor %} diff --git a/j2/platform-ansible.j2 b/j2/platform-ansible.j2 deleted file mode 100644 index 72e3247..0000000 --- a/j2/platform-ansible.j2 +++ /dev/null @@ -1,6 +0,0 @@ -# Ansible -- hosts: - - {{ m.key }} - tasks: - - import_role: - name: acme-platform diff --git a/j2/terraform-machine-outputs.j2 b/j2/terraform-machine-outputs.j2 deleted file mode 100644 index 438fac6..0000000 --- a/j2/terraform-machine-outputs.j2 +++ /dev/null @@ -1,7 +0,0 @@ -output "addresses" { - value = { -{%- for m in machines %} - {{ m.key }}: scaleway_instance_ip.{{ m.key }}.address, -{%- endfor %} - } -} diff --git a/j2/terraform-machine.j2 b/j2/terraform-machine.j2 deleted file mode 100644 index 0ac8b90..0000000 --- a/j2/terraform-machine.j2 +++ /dev/null @@ -1,19 +0,0 @@ -resource "scaleway_instance_server" "{{ scw.key }}" { - name = "acme-1" - type = "DEV1-S" - image = "b3042271-d2b1-4f87-b407-aedd3bbd1663" - ip_id = scaleway_instance_ip.{{ scw.key }}.id - enable_dynamic_ip = false - enable_ipv6 = true -} - -resource "scaleway_instance_ip" "{{ scw.key }}" {} - -resource "scaleway_instance_ip_reverse_dns" "{{ scw.key }}" { - ip_id = scaleway_instance_ip.{{ scw.key }}.id - reverse = "{{ m.fqdn }}." -} - -output "{{scw.key}}_public_ip" { - value = scaleway_instance_server.{{ scw.key }}.public_ip -} diff --git a/j2/terraform-main-scaleway-machine.j2 b/j2/terraform-main-scaleway-machine.j2 deleted file mode 100644 index eab9fac..0000000 --- a/j2/terraform-main-scaleway-machine.j2 +++ /dev/null @@ -1,19 +0,0 @@ -# Generated - -terraform { - required_providers { - scaleway = { - source = "scaleway/scaleway" - version = "1.17.2" - } - } -} - -provider "scaleway" { -} - -{% -for z in managedZones %} -variable "{{z.name}}" { - type = string -} -{% endfor -%} diff --git a/j2/terraform-record-set.j2 b/j2/terraform-record-set.j2 deleted file mode 100644 index b89ee00..0000000 --- a/j2/terraform-record-set.j2 +++ /dev/null @@ -1,8 +0,0 @@ -resource "google_dns_record_set" "{{ tf.key }}" { - name = "{{ entry.fqdn }}" - managed_zone = var.{{ managedZone.name }} - type = "{{ entry.type }}" - ttl = 300 - - rrdatas = [{{ tf.expression }}] -} diff --git a/j2/wireguard/ansible-host.j2 b/j2/wireguard/ansible-host.j2 deleted file mode 100644 index a3c8c40..0000000 --- a/j2/wireguard/ansible-host.j2 +++ /dev/null @@ -1,8 +0,0 @@ -# Generated -link_address: {{ host.ip }} -network_cidr: {{ host.networkCidr }} -wireguard_peers: - {{ host.machine.name }}: -{%- for peer in peers %} - - {{ peer.fqdn }} -{%- endfor %} diff --git a/j2/wireguard/ansible.j2 b/j2/wireguard/ansible.j2 deleted file mode 100644 index 82c0ca0..0000000 --- a/j2/wireguard/ansible.j2 +++ /dev/null @@ -1,6 +0,0 @@ -- hosts: {{ net.name }} - roles: - - name: wireguard - wireguard_if: {{ net.name }} - wireguard_listen_port: 45364 - wireguard_address4: "{{ '{{' }} link_addresses[ansible_hostname] }}" diff --git a/j2/wireguard/inventory.j2 b/j2/wireguard/inventory.j2 deleted file mode 100644 index 0924bb2..0000000 --- a/j2/wireguard/inventory.j2 +++ /dev/null @@ -1,7 +0,0 @@ -# Generated -all: - hosts: - {%- for host in hosts %} - {{ host.getName() }}: - ansible_host: {{ host.getFqdn() }} - {%- endfor %} diff --git a/module/acme/src/main/resources/META-INF/kmodule.xml b/module/acme/src/main/resources/META-INF/kmodule.xml index 6bcd1db..da435d6 100644 --- a/module/acme/src/main/resources/META-INF/kmodule.xml +++ b/module/acme/src/main/resources/META-INF/kmodule.xml @@ -11,7 +11,7 @@ - + diff --git a/module/ri-base/src/main/java/io/trygvis/rules/machine/MachineSpecification.java b/module/ri-base/src/main/java/io/trygvis/rules/machine/MachineSpecification.java index 2e17ae5..9d38b2d 100644 --- a/module/ri-base/src/main/java/io/trygvis/rules/machine/MachineSpecification.java +++ b/module/ri-base/src/main/java/io/trygvis/rules/machine/MachineSpecification.java @@ -1,8 +1,10 @@ package io.trygvis.rules.machine; public class MachineSpecification { - public final int cpu; - public final int memory; + public int cpu; + public int memory; + + protected MachineSpecification() {} public MachineSpecification(int cpu, int memory) { this.cpu = cpu; diff --git a/module/ri-base/src/main/resources/io/trygvis/rules/terraform/terraform.drl b/module/ri-base/src/main/resources/io/trygvis/rules/terraform/terraform.drl index 5ebd082..7313998 100644 --- a/module/ri-base/src/main/resources/io/trygvis/rules/terraform/terraform.drl +++ b/module/ri-base/src/main/resources/io/trygvis/rules/terraform/terraform.drl @@ -50,7 +50,7 @@ when $managedZones : ArrayList() from collect(GoogleManagedZoneTerraformExpression()) then String path = "terraform/main-scaleway-machine.tf"; - te.template("terraform-main-scaleway-machine", path, Map.of( + te.template("terraform/main-scaleway-machine", path, Map.of( "managedZones", $managedZones )); end @@ -62,7 +62,7 @@ when $scw: ScalewayMachine(machine == $m) then String path = "terraform/scaleway-machine-%s.tf".formatted($scw.getKey()); - te.template("terraform-machine", path, Map.of("m", $m, "scw", $scw)); + te.template("terraform/machine", path, Map.of("m", $m, "scw", $scw)); end rule "Terraform for DNS" @@ -73,7 +73,7 @@ when $managedZone : GoogleManagedZoneTerraformExpression() then String path = "terraform/dns-%s.tf".formatted($tf.key); - te.template("terraform-record-set", path, Map.of( + te.template("terraform/record-set", path, Map.of( "entry", $entry, "managedZone", $managedZone, "tf", $tf) diff --git a/module/ri-base/src/main/resources/templates/dba/cluster.j2 b/module/ri-base/src/main/resources/templates/dba/cluster.j2 new file mode 100644 index 0000000..045fbcd --- /dev/null +++ b/module/ri-base/src/main/resources/templates/dba/cluster.j2 @@ -0,0 +1,19 @@ +# Generated + +# cluster: {{ cluster.name }} +{%- for m, containers in containersByMachine.entrySet() %} +--- +- host: + - {{ m.name }} + tasks: + import_role: + name: docker-service + vars: + template: | + version: "3" + services: +{%- for c in containers %} + {{ c.name }}: + image: {{ c.image }}:{{ c.tag }} +{%- endfor %} +{% endfor %} diff --git a/module/ri-base/src/main/resources/templates/platform-ansible.j2 b/module/ri-base/src/main/resources/templates/platform-ansible.j2 new file mode 100644 index 0000000..72e3247 --- /dev/null +++ b/module/ri-base/src/main/resources/templates/platform-ansible.j2 @@ -0,0 +1,6 @@ +# Ansible +- hosts: + - {{ m.key }} + tasks: + - import_role: + name: acme-platform diff --git a/module/ri-base/src/main/resources/templates/terraform/machine-outputs.j2 b/module/ri-base/src/main/resources/templates/terraform/machine-outputs.j2 new file mode 100644 index 0000000..438fac6 --- /dev/null +++ b/module/ri-base/src/main/resources/templates/terraform/machine-outputs.j2 @@ -0,0 +1,7 @@ +output "addresses" { + value = { +{%- for m in machines %} + {{ m.key }}: scaleway_instance_ip.{{ m.key }}.address, +{%- endfor %} + } +} diff --git a/module/ri-base/src/main/resources/templates/terraform/machine.j2 b/module/ri-base/src/main/resources/templates/terraform/machine.j2 new file mode 100644 index 0000000..0ac8b90 --- /dev/null +++ b/module/ri-base/src/main/resources/templates/terraform/machine.j2 @@ -0,0 +1,19 @@ +resource "scaleway_instance_server" "{{ scw.key }}" { + name = "acme-1" + type = "DEV1-S" + image = "b3042271-d2b1-4f87-b407-aedd3bbd1663" + ip_id = scaleway_instance_ip.{{ scw.key }}.id + enable_dynamic_ip = false + enable_ipv6 = true +} + +resource "scaleway_instance_ip" "{{ scw.key }}" {} + +resource "scaleway_instance_ip_reverse_dns" "{{ scw.key }}" { + ip_id = scaleway_instance_ip.{{ scw.key }}.id + reverse = "{{ m.fqdn }}." +} + +output "{{scw.key}}_public_ip" { + value = scaleway_instance_server.{{ scw.key }}.public_ip +} diff --git a/module/ri-base/src/main/resources/templates/terraform/main-scaleway-machine.j2 b/module/ri-base/src/main/resources/templates/terraform/main-scaleway-machine.j2 new file mode 100644 index 0000000..eab9fac --- /dev/null +++ b/module/ri-base/src/main/resources/templates/terraform/main-scaleway-machine.j2 @@ -0,0 +1,19 @@ +# Generated + +terraform { + required_providers { + scaleway = { + source = "scaleway/scaleway" + version = "1.17.2" + } + } +} + +provider "scaleway" { +} + +{% -for z in managedZones %} +variable "{{z.name}}" { + type = string +} +{% endfor -%} diff --git a/module/ri-base/src/main/resources/templates/terraform/record-set.j2 b/module/ri-base/src/main/resources/templates/terraform/record-set.j2 new file mode 100644 index 0000000..b89ee00 --- /dev/null +++ b/module/ri-base/src/main/resources/templates/terraform/record-set.j2 @@ -0,0 +1,8 @@ +resource "google_dns_record_set" "{{ tf.key }}" { + name = "{{ entry.fqdn }}" + managed_zone = var.{{ managedZone.name }} + type = "{{ entry.type }}" + ttl = 300 + + rrdatas = [{{ tf.expression }}] +} 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()); - } -} diff --git a/module/ri-wireguard/src/main/resources/templates/wireguard/ansible-host.j2 b/module/ri-wireguard/src/main/resources/templates/wireguard/ansible-host.j2 new file mode 100644 index 0000000..a3c8c40 --- /dev/null +++ b/module/ri-wireguard/src/main/resources/templates/wireguard/ansible-host.j2 @@ -0,0 +1,8 @@ +# Generated +link_address: {{ host.ip }} +network_cidr: {{ host.networkCidr }} +wireguard_peers: + {{ host.machine.name }}: +{%- for peer in peers %} + - {{ peer.fqdn }} +{%- endfor %} diff --git a/module/ri-wireguard/src/main/resources/templates/wireguard/ansible.j2 b/module/ri-wireguard/src/main/resources/templates/wireguard/ansible.j2 new file mode 100644 index 0000000..82c0ca0 --- /dev/null +++ b/module/ri-wireguard/src/main/resources/templates/wireguard/ansible.j2 @@ -0,0 +1,6 @@ +- hosts: {{ net.name }} + roles: + - name: wireguard + wireguard_if: {{ net.name }} + wireguard_listen_port: 45364 + wireguard_address4: "{{ '{{' }} link_addresses[ansible_hostname] }}" diff --git a/module/ri-wireguard/src/main/resources/templates/wireguard/inventory.j2 b/module/ri-wireguard/src/main/resources/templates/wireguard/inventory.j2 new file mode 100644 index 0000000..0924bb2 --- /dev/null +++ b/module/ri-wireguard/src/main/resources/templates/wireguard/inventory.j2 @@ -0,0 +1,7 @@ +# Generated +all: + hosts: + {%- for host in hosts %} + {{ host.getName() }}: + ansible_host: {{ host.getFqdn() }} + {%- endfor %} diff --git a/out/acme/apps.yaml b/out/acme/apps.yaml index 0c69b8e..e0e9e88 100644 --- a/out/acme/apps.yaml +++ b/out/acme/apps.yaml @@ -76,6 +76,9 @@ image: "4tune-api" tag: "development" machine: *acme-1 + machineSpecification: + cpu: 200 + memory: 200 - type: "io.trygvis.rules.dba.Container" data: id: "acme-myapp-production-4tune-api" @@ -85,6 +88,9 @@ image: "4tune-api" tag: "master" machine: *acme-3 + machineSpecification: + cpu: 200 + memory: 200 - type: "io.trygvis.rules.dba.Container" data: id: "acme-myapp-ci-4tune-web" @@ -94,6 +100,9 @@ image: "4tune-web" tag: "development" machine: *acme-1 + machineSpecification: + cpu: 100 + memory: 50 - type: "io.trygvis.rules.dba.Container" data: id: "acme-myapp-production-4tune-web" @@ -103,6 +112,9 @@ image: "4tune-web" tag: "master" machine: *acme-3 + machineSpecification: + cpu: 100 + memory: 50 - type: "io.trygvis.rules.dba.Container" data: id: "acme-myapp-ci-mdb" @@ -112,6 +124,9 @@ image: "mongodb" tag: "3.2" machine: *acme-2 + machineSpecification: + cpu: 500 + memory: 200 - type: "io.trygvis.rules.dba.Container" data: id: "acme-myapp-production-mdb" @@ -121,6 +136,9 @@ image: "mongodb" tag: "3.2" machine: *acme-3 + machineSpecification: + cpu: 500 + memory: 200 - type: "io.trygvis.rules.dba.Container" data: id: "acme-ops-n8n" @@ -130,6 +148,7 @@ image: "n8n" tag: "0.84.1" machine: *acme-2 + machineSpecification: null - type: "io.trygvis.rules.dba.Container" data: id: "acme-myapp-ci-pdb" @@ -139,6 +158,9 @@ image: "postgresql" tag: "13" machine: *acme-2 + machineSpecification: + cpu: 500 + memory: 500 - type: "io.trygvis.rules.dba.Container" data: id: "acme-myapp-production-pdb" @@ -148,6 +170,9 @@ image: "postgresql" tag: "13" machine: *acme-3 + machineSpecification: + cpu: 500 + memory: 500 - type: "io.trygvis.rules.dba.Container" data: id: "acme-ops-pdb" @@ -157,6 +182,7 @@ image: "postgresql" tag: "11" machine: *acme-2 + machineSpecification: null - type: "io.trygvis.rules.dba.Container" data: id: "acme-myapp-ci-statera" @@ -166,6 +192,9 @@ image: "statera" tag: "development" machine: *acme-1 + machineSpecification: + cpu: 200 + memory: 1000 - type: "io.trygvis.rules.dba.Container" data: id: "acme-myapp-production-statera" @@ -175,6 +204,9 @@ image: "statera" tag: "master" machine: *acme-3 + machineSpecification: + cpu: 200 + memory: 1000 - type: "io.trygvis.rules.dba.Container" data: id: "acme-myapp-ci-statera-console" @@ -184,6 +216,9 @@ image: "statera-console" tag: "development" machine: *acme-1 + machineSpecification: + cpu: 100 + memory: 50 - type: "io.trygvis.rules.dba.Container" data: id: "acme-myapp-production-statera-console" @@ -193,20 +228,23 @@ image: "statera-console" tag: "master" machine: *acme-3 + machineSpecification: + cpu: 100 + memory: 50 - type: "io.trygvis.rules.dba.DbaMachineRole" data: - machine: "acme-1" + &1 machine: "acme-1" roles: - "ci-app" - type: "io.trygvis.rules.dba.DbaMachineRole" data: - machine: "acme-2" + &2 machine: "acme-2" roles: - "ops" - "ci-db" - type: "io.trygvis.rules.dba.DbaMachineRole" data: - machine: "acme-3" + &3 machine: "acme-3" roles: - "production-app" - "production-db" -- cgit v1.2.3