summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--acme-apps/ansible/dba/acme-myapp-ci.yml37
-rw-r--r--acme-apps/ansible/dba/acme-myapp-production.yml26
-rw-r--r--acme-apps/ansible/dba/acme-ops.yml18
-rw-r--r--acme.yaml22
-rw-r--r--j2/dba/cluster.j219
-rw-r--r--module/acme/src/main/resources/io/trygvis/acme/apps/apps.drl25
-rw-r--r--module/ri-engine/src/main/java/io/trygvis/rules/core/Problem.java11
-rw-r--r--module/ri-engine/src/main/java/io/trygvis/rules/dba/Container.java42
-rw-r--r--module/ri-engine/src/main/java/io/trygvis/rules/dns/DnsZone.java9
-rw-r--r--module/ri-engine/src/main/resources/io/trygvis/rules/dba/dba.drl69
-rw-r--r--out/acme/apps.yaml170
11 files changed, 384 insertions, 64 deletions
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"