From 250cb0fb4fa9787c78b73b44425676cfec3a7944 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Tue, 12 Jan 2021 20:57:56 +0100 Subject: Starting on generating ansible files for docker-compose setups. --- acme-apps/ansible/dba/acme-myapp-ci.yml | 37 +++++ acme-apps/ansible/dba/acme-myapp-production.yml | 26 ++++ acme-apps/ansible/dba/acme-ops.yml | 18 +++ acme.yaml | 22 +++ j2/dba/cluster.j2 | 19 +++ .../main/resources/io/trygvis/acme/apps/apps.drl | 25 +-- .../main/java/io/trygvis/rules/core/Problem.java | 11 ++ .../main/java/io/trygvis/rules/dba/Container.java | 42 ++++- .../main/java/io/trygvis/rules/dns/DnsZone.java | 9 ++ .../main/resources/io/trygvis/rules/dba/dba.drl | 69 +++++++++ out/acme/apps.yaml | 170 +++++++++++++++------ 11 files changed, 384 insertions(+), 64 deletions(-) create mode 100644 acme-apps/ansible/dba/acme-myapp-ci.yml create mode 100644 acme-apps/ansible/dba/acme-myapp-production.yml create mode 100644 acme-apps/ansible/dba/acme-ops.yml create mode 100644 j2/dba/cluster.j2 create mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/core/Problem.java create mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/dns/DnsZone.java create mode 100644 module/ri-engine/src/main/resources/io/trygvis/rules/dba/dba.drl diff --git a/acme-apps/ansible/dba/acme-myapp-ci.yml b/acme-apps/ansible/dba/acme-myapp-ci.yml new file mode 100644 index 0000000..e44b73e --- /dev/null +++ b/acme-apps/ansible/dba/acme-myapp-ci.yml @@ -0,0 +1,37 @@ +# Generated + +# cluster: +--- +- host: + - io.trygvis.rules.machine.Machine@b112b13 + tasks: + import_role: + name: docker-service + vars: + template: | + version: "3" + services: + mdb: + image: mongodb:3.2 + pdb: + image: postgresql:13 + +--- +- host: + - io.trygvis.rules.machine.Machine@d5556bf + tasks: + import_role: + name: docker-service + vars: + template: | + version: "3" + services: + 4tune-api: + image: 4tune-api:development + 4tune-web: + image: 4tune-web:development + statera-console: + image: statera-console:development + statera: + image: statera:development + diff --git a/acme-apps/ansible/dba/acme-myapp-production.yml b/acme-apps/ansible/dba/acme-myapp-production.yml new file mode 100644 index 0000000..3cd0798 --- /dev/null +++ b/acme-apps/ansible/dba/acme-myapp-production.yml @@ -0,0 +1,26 @@ +# Generated + +# cluster: +--- +- host: + - io.trygvis.rules.machine.Machine@3ac3f6f + tasks: + import_role: + name: docker-service + vars: + template: | + version: "3" + services: + mdb: + image: mongodb:3.2 + pdb: + image: postgresql:13 + 4tune-api: + image: 4tune-api:master + 4tune-web: + image: 4tune-web:master + statera-console: + image: statera-console:master + statera: + image: statera:master + diff --git a/acme-apps/ansible/dba/acme-ops.yml b/acme-apps/ansible/dba/acme-ops.yml new file mode 100644 index 0000000..62264b0 --- /dev/null +++ b/acme-apps/ansible/dba/acme-ops.yml @@ -0,0 +1,18 @@ +# Generated + +# cluster: +--- +- host: + - io.trygvis.rules.machine.Machine@b112b13 + tasks: + import_role: + name: docker-service + vars: + template: | + version: "3" + services: + n8n: + image: n8n:0.84.1 + pdb: + image: postgresql:11 + diff --git a/acme.yaml b/acme.yaml index 09bdd0d..e82200a 100644 --- a/acme.yaml +++ b/acme.yaml @@ -21,13 +21,35 @@ type: io.trygvis.rules.machine.Machine data: name: acme-1 --- +type: io.trygvis.rules.dba.DbaMachineRole +data: + machine: acme-1 + roles: + - ci-app + +--- type: io.trygvis.rules.machine.Machine data: name: acme-2 --- +type: io.trygvis.rules.dba.DbaMachineRole +data: + machine: acme-2 + roles: + - ops + - ci-db # This also runs the DB for the non-production environments to keep the other machines stateless + +--- type: io.trygvis.rules.machine.Machine data: name: acme-3 +--- +type: io.trygvis.rules.dba.DbaMachineRole +data: + machine: acme-3 + roles: + - production-app + - production-db # Workstations --- diff --git a/j2/dba/cluster.j2 b/j2/dba/cluster.j2 new file mode 100644 index 0000000..87973ff --- /dev/null +++ b/j2/dba/cluster.j2 @@ -0,0 +1,19 @@ +# Generated + +# cluster: {{ cluster.name }} +{%- for m, containers in containersByMachine.entrySet() %} +--- +- host: + - {{ m }} + 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/acme/src/main/resources/io/trygvis/acme/apps/apps.drl b/module/acme/src/main/resources/io/trygvis/acme/apps/apps.drl index 95f09c8..e7bdfe3 100644 --- a/module/acme/src/main/resources/io/trygvis/acme/apps/apps.drl +++ b/module/acme/src/main/resources/io/trygvis/acme/apps/apps.drl @@ -2,7 +2,8 @@ package io.trygvis.acme.apps; import io.trygvis.rules.machine.Machine; import io.trygvis.rules.dba.Cluster; -import io.trygvis.rules.dba.Container; +import io.trygvis.rules.dba.Container +import io.trygvis.rules.dns.DnsZone; dialect "mvel" @@ -12,22 +13,28 @@ when then var cluster = new Cluster("acme-ops"); insert(cluster); - insert(new Container(cluster, "app", "pdb", "postgresql", "11")); - insert(new Container(cluster, "app", "n8n", "n8n", "0.84.1")); + insert(new Container(cluster, "pdb", "ops", "postgresql", "11")); + insert(new Container(cluster, "n8n", "ops", "n8n", "0.84.1")); end rule "MyApp" when $app: AcmeMyApp() then + var zone = new DnsZone($app.environment + ".acme.com"); + insert(zone) + var cluster = new Cluster("acme-myapp-" + $app.environment); insert(cluster); + var app = $app.environment + "-app"; + var db = $app.environment + "-db"; + var tag = $app.dockerTag; - insert(new Container(cluster, "app", "statera", "statera", tag)); - insert(new Container(cluster, "app", "statera-console", "statera-console", tag)); - insert(new Container(cluster, "app", "4tune-web", "4tune-web", tag)); - insert(new Container(cluster, "app", "4tune-api", "4tune-api", tag)); - insert(new Container(cluster, "db", "pdb", "postgresql", "13")); - insert(new Container(cluster, "db", "mdb", "mongodb", "3.2")); + insert(new Container(cluster, "statera", app, "statera", tag)); + insert(new Container(cluster, "statera-console", app, "statera-console", tag)); + insert(new Container(cluster, "4tune-web", app, "4tune-web", tag)); + insert(new Container(cluster, "4tune-api", app, "4tune-api", tag)); + insert(new Container(cluster, "pdb", db, "postgresql", "13")); + insert(new Container(cluster, "mdb", db, "mongodb", "3.2")); end diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/core/Problem.java b/module/ri-engine/src/main/java/io/trygvis/rules/core/Problem.java new file mode 100644 index 0000000..04d1af3 --- /dev/null +++ b/module/ri-engine/src/main/java/io/trygvis/rules/core/Problem.java @@ -0,0 +1,11 @@ +package io.trygvis.rules.core; + +public class Problem { + public final String message; + public final Object object; + + public Problem(String message, Object object) { + this.message = message; + this.object = object; + } +} diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/dba/Container.java b/module/ri-engine/src/main/java/io/trygvis/rules/dba/Container.java index 6df939d..d852115 100644 --- a/module/ri-engine/src/main/java/io/trygvis/rules/dba/Container.java +++ b/module/ri-engine/src/main/java/io/trygvis/rules/dba/Container.java @@ -1,11 +1,15 @@ package io.trygvis.rules.dba; +import io.trygvis.rules.machine.Machine; + public class Container { - public Cluster cluster; - public String name; - public String machineRole; - public String image; - public String tag; + public final Cluster cluster; + public final String name; + public final String machineRole; + public final String image; + public final String tag; + + private Machine machine; public Container(Cluster cluster, String name, String machineRole, String image, String tag) { this.cluster = cluster; @@ -14,4 +18,32 @@ public class Container { this.image = image; this.tag = tag; } + + public Cluster getCluster() { + return cluster; + } + + public String getName() { + return name; + } + + public String getMachineRole() { + return machineRole; + } + + public String getImage() { + return image; + } + + public String getTag() { + return tag; + } + + public Machine getMachine() { + return machine; + } + + public void setMachine(Machine machine) { + this.machine = machine; + } } diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/dns/DnsZone.java b/module/ri-engine/src/main/java/io/trygvis/rules/dns/DnsZone.java new file mode 100644 index 0000000..1af5c8f --- /dev/null +++ b/module/ri-engine/src/main/java/io/trygvis/rules/dns/DnsZone.java @@ -0,0 +1,9 @@ +package io.trygvis.rules.dns; + +public class DnsZone { + public final String name; + + public DnsZone(String name) { + this.name = name; + } +} diff --git a/module/ri-engine/src/main/resources/io/trygvis/rules/dba/dba.drl b/module/ri-engine/src/main/resources/io/trygvis/rules/dba/dba.drl new file mode 100644 index 0000000..9bdc0a5 --- /dev/null +++ b/module/ri-engine/src/main/resources/io/trygvis/rules/dba/dba.drl @@ -0,0 +1,69 @@ +package io.trygvis.rules.dba + +import io.trygvis.rules.core.Problem +import io.trygvis.rules.machine.Machine +import java.util.ArrayList +import java.util.Map +import java.util.HashMap +import java.util.List +import java.util.stream.Collectors +import java.util.Collections + +global io.trygvis.rules.engine.TemplateEngine te; + +dialect "mvel" + +declare DbaMachineRole + machine : String + roles : String[] +end + +rule "Assign containers to hosts" +when + $machine : Machine() + $machineRole : DbaMachineRole(machine == $machine.name) + $container : Container(machine == null, $machineRole.roles contains machineRole) +then + System.out.println("Assigning container to machine: " + $machine.name); + modify($container) { + machine = $machine + } +end + +rule "Containers without hosts" + agenda-group "generate" +when + $container : Container(machine == null) +then + insert(new Problem("No machine for container", $container)) +end + +rule "Generate docker-compose.yaml" + agenda-group "generate" +when + $cluster : Cluster() + $containers : ArrayList(size > 0) from collect(Container(cluster == $cluster)) +then + System.out.println("Docker compose for cluster: " + $cluster.name + " with " + $containers.size() + " containers"); + + Map containersByMachine = new HashMap(); + for (Object o : $containers) { + Container c = (Container) o; + + var list = (List) containersByMachine.get(c.getMachine()); + if (list == null) { + list = new ArrayList(); + containersByMachine.put(c.getMachine(), list); + } + list.add(c); + } + + System.out.println("containersByMachine = " + containersByMachine); + + var path = "ansible/dba/" + $cluster.name + ".yml"; + te.template("dba/cluster", path, Map.of( + "cluster", $cluster, + "containers", $containers, + "containersByMachine", containersByMachine + )); +end diff --git a/out/acme/apps.yaml b/out/acme/apps.yaml index 95aed6b..d6fbe6d 100644 --- a/out/acme/apps.yaml +++ b/out/acme/apps.yaml @@ -49,127 +49,189 @@ type: "io.trygvis.rules.dba.Container" data: cluster: name: "acme-myapp-ci" - name: "app" - machineRole: "4tune-api" + name: "4tune-api" + machineRole: "ci-app" image: "4tune-api" tag: "development" + machine: + name: "acme-1" + fqdn: "acme-1.machine.acme.com" --- type: "io.trygvis.rules.dba.Container" data: cluster: name: "acme-myapp-production" - name: "app" - machineRole: "4tune-api" + name: "4tune-api" + machineRole: "production-app" image: "4tune-api" tag: "master" + machine: + name: "acme-3" + fqdn: "acme-3.machine.acme.com" --- type: "io.trygvis.rules.dba.Container" data: cluster: name: "acme-myapp-ci" - name: "app" - machineRole: "4tune-web" + name: "4tune-web" + machineRole: "ci-app" image: "4tune-web" tag: "development" + machine: + name: "acme-1" + fqdn: "acme-1.machine.acme.com" --- type: "io.trygvis.rules.dba.Container" data: cluster: name: "acme-myapp-production" - name: "app" - machineRole: "4tune-web" + name: "4tune-web" + machineRole: "production-app" image: "4tune-web" tag: "master" + machine: + name: "acme-3" + fqdn: "acme-3.machine.acme.com" +--- +type: "io.trygvis.rules.dba.Container" +data: + cluster: + name: "acme-myapp-ci" + name: "mdb" + machineRole: "ci-db" + image: "mongodb" + tag: "3.2" + machine: + name: "acme-2" + fqdn: "acme-2.machine.acme.com" +--- +type: "io.trygvis.rules.dba.Container" +data: + cluster: + name: "acme-myapp-production" + name: "mdb" + machineRole: "production-db" + image: "mongodb" + tag: "3.2" + machine: + name: "acme-3" + fqdn: "acme-3.machine.acme.com" --- type: "io.trygvis.rules.dba.Container" data: cluster: name: "acme-ops" - name: "app" - machineRole: "n8n" + name: "n8n" + machineRole: "ops" image: "n8n" tag: "0.84.1" + machine: + name: "acme-2" + fqdn: "acme-2.machine.acme.com" +--- +type: "io.trygvis.rules.dba.Container" +data: + cluster: + name: "acme-myapp-ci" + name: "pdb" + machineRole: "ci-db" + image: "postgresql" + tag: "13" + machine: + name: "acme-2" + fqdn: "acme-2.machine.acme.com" --- type: "io.trygvis.rules.dba.Container" data: cluster: name: "acme-ops" - name: "app" - machineRole: "pdb" + name: "pdb" + machineRole: "ops" image: "postgresql" tag: "11" + machine: + name: "acme-2" + fqdn: "acme-2.machine.acme.com" +--- +type: "io.trygvis.rules.dba.Container" +data: + cluster: + name: "acme-myapp-production" + name: "pdb" + machineRole: "production-db" + image: "postgresql" + tag: "13" + machine: + name: "acme-3" + fqdn: "acme-3.machine.acme.com" --- type: "io.trygvis.rules.dba.Container" data: cluster: name: "acme-myapp-ci" - name: "app" - machineRole: "statera" + name: "statera" + machineRole: "ci-app" image: "statera" tag: "development" + machine: + name: "acme-1" + fqdn: "acme-1.machine.acme.com" --- type: "io.trygvis.rules.dba.Container" data: cluster: name: "acme-myapp-production" - name: "app" - machineRole: "statera" + name: "statera" + machineRole: "production-app" image: "statera" tag: "master" + machine: + name: "acme-3" + fqdn: "acme-3.machine.acme.com" --- type: "io.trygvis.rules.dba.Container" data: cluster: name: "acme-myapp-ci" - name: "app" - machineRole: "statera-console" + name: "statera-console" + machineRole: "ci-app" image: "statera-console" tag: "development" + machine: + name: "acme-1" + fqdn: "acme-1.machine.acme.com" --- type: "io.trygvis.rules.dba.Container" data: cluster: name: "acme-myapp-production" - name: "app" - machineRole: "statera-console" + name: "statera-console" + machineRole: "production-app" image: "statera-console" tag: "master" + machine: + name: "acme-3" + fqdn: "acme-3.machine.acme.com" --- -type: "io.trygvis.rules.dba.Container" -data: - cluster: - name: "acme-myapp-production" - name: "db" - machineRole: "mdb" - image: "mongodb" - tag: "3.2" ---- -type: "io.trygvis.rules.dba.Container" +type: "io.trygvis.rules.dba.DbaMachineRole" data: - cluster: - name: "acme-myapp-ci" - name: "db" - machineRole: "mdb" - image: "mongodb" - tag: "3.2" + machine: "acme-1" + roles: + - "ci-app" --- -type: "io.trygvis.rules.dba.Container" +type: "io.trygvis.rules.dba.DbaMachineRole" data: - cluster: - name: "acme-myapp-production" - name: "db" - machineRole: "pdb" - image: "postgresql" - tag: "13" + machine: "acme-2" + roles: + - "ops" + - "ci-db" --- -type: "io.trygvis.rules.dba.Container" +type: "io.trygvis.rules.dba.DbaMachineRole" data: - cluster: - name: "acme-myapp-ci" - name: "db" - machineRole: "pdb" - image: "postgresql" - tag: "13" + machine: "acme-3" + roles: + - "production-app" + - "production-db" --- type: "io.trygvis.rules.dns.DnsEntry" data: @@ -210,6 +272,14 @@ data: key: "acme-3" expression: "scaleway_instance_ip.acme-3.address" --- +type: "io.trygvis.rules.dns.DnsZone" +data: + name: "ci.acme.com" +--- +type: "io.trygvis.rules.dns.DnsZone" +data: + name: "production.acme.com" +--- type: "io.trygvis.rules.engine.KeyValue" data: key: "rm-gen" -- cgit v1.2.3