summaryrefslogtreecommitdiff
path: root/example
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2021-02-03 16:35:48 +0100
committerTrygve Laugstøl <trygvis@inamo.no>2021-02-03 16:35:48 +0100
commitbafe762ac01d16904c18404283027e426e19bc73 (patch)
treec22688ad186f5ce635f525704c5035f91b983b68 /example
parent91abd0b04320a9c9d932df195aca38c1cacfcc5a (diff)
downloadrules-sandbox-bafe762ac01d16904c18404283027e426e19bc73.tar.gz
rules-sandbox-bafe762ac01d16904c18404283027e426e19bc73.tar.bz2
rules-sandbox-bafe762ac01d16904c18404283027e426e19bc73.tar.xz
rules-sandbox-bafe762ac01d16904c18404283027e426e19bc73.zip
Code reorganization.
Moving main code to src, keeping modules in modules/
Diffstat (limited to 'example')
-rw-r--r--example/.gitignore10
-rw-r--r--example/.settings.sh9
-rw-r--r--example/Makefile41
-rw-r--r--example/acme-apps/ansible/dba/acme-myapp-ci.yml37
-rw-r--r--example/acme-apps/ansible/dba/acme-myapp-production.yml26
-rw-r--r--example/acme-apps/ansible/dba/acme-ops.yml18
-rw-r--r--example/acme-apps/terraform/acme-1-instance.tf8
-rw-r--r--example/acme-apps/terraform/acme-1-ip.tf4
-rw-r--r--example/acme-apps/terraform/acme-2-instance.tf8
-rw-r--r--example/acme-apps/terraform/acme-2-ip.tf4
-rw-r--r--example/acme-apps/terraform/acme-3-instance.tf8
-rw-r--r--example/acme-apps/terraform/acme-3-ip.tf4
-rw-r--r--example/acme-apps/terraform/main.tf9
-rw-r--r--example/acme-apps/terraform/vars.tf1
-rw-r--r--example/acme-wireguard/host_vars/acme-1/wireguard.yml15
-rw-r--r--example/acme-wireguard/host_vars/acme-2/wireguard.yml15
-rw-r--r--example/acme-wireguard/host_vars/acme-3/wireguard.yml15
-rw-r--r--example/acme-wireguard/host_vars/ws-1/wireguard.yml20
-rw-r--r--example/acme-wireguard/host_vars/ws-2/wireguard.yml20
-rw-r--r--example/acme-wireguard/inventory.yml21
-rw-r--r--example/acme-wireguard/wireguard-vpn0.yml7
-rw-r--r--example/acme.yaml78
-rw-r--r--example/ansible.cfg8
-rw-r--r--example/build.ninja1
-rw-r--r--example/db/apps.yaml354
-rw-r--r--example/db/wireguard.yaml161
-rw-r--r--example/engine.ninja11
-rw-r--r--example/main.tf60
-rw-r--r--example/modules/acme/pom.xml29
-rw-r--r--example/modules/acme/src/main/java/io/trygvis/acme/AcmeAppsMain.java14
-rw-r--r--example/modules/acme/src/main/java/io/trygvis/acme/VpnMain.java21
-rw-r--r--example/modules/acme/src/main/java/io/trygvis/acme/apps/AcmeMyApp.java6
-rw-r--r--example/modules/acme/src/main/java/io/trygvis/acme/apps/AcmeOps.java4
-rw-r--r--example/modules/acme/src/main/resources/META-INF/kmodule.xml17
-rw-r--r--example/modules/acme/src/main/resources/io/trygvis/acme/acme.drl81
-rw-r--r--example/modules/acme/src/main/resources/io/trygvis/acme/apps/apps.drl44
36 files changed, 1182 insertions, 7 deletions
diff --git a/example/.gitignore b/example/.gitignore
new file mode 100644
index 0000000..c6f6ac8
--- /dev/null
+++ b/example/.gitignore
@@ -0,0 +1,10 @@
+../acme/.terraform
+terraform.d
+*.tfstate
+*.tfstate.backup
+plan
+
+.vault-password*
+*.dot
+*.png
+.ninja_log
diff --git a/example/.settings.sh b/example/.settings.sh
new file mode 100644
index 0000000..7bd49fb
--- /dev/null
+++ b/example/.settings.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+basedir=$(dirname "$_")
+basedir=$(cd "$basedir" && pwd)
+
+#echo "Adding tools/ to path"
+#PATH="$basedir/tools:$PATH"
+
+alias terraform="TF_VAR_ansible_vault_pass=\$($(pwd)/.vault-password) $(pwd)/.terraform/bin/terraform"
diff --git a/example/Makefile b/example/Makefile
new file mode 100644
index 0000000..39d54a6
--- /dev/null
+++ b/example/Makefile
@@ -0,0 +1,41 @@
+terraform_version=0.14.4
+terraform_url=https://releases.hashicorp.com/terraform/$(terraform_version)/terraform_$(terraform_version)_linux_amd64.zip
+terraform_unzip=.terraform/unzip/$(terraform_version)/
+terraform_zip=.terraform/zip/terraform_$(terraform_version)_linux_amd64.zip
+terraform_bin=.terraform/bin/terraform
+
+ansiblevault_version=2.0.1
+ansiblevault_url=https://github.com/MeilleursAgents/terraform-provider-ansiblevault/releases/download/v$(ansiblevault_version)/terraform-provider-ansiblevault_linux_amd64_v$(ansiblevault_version)
+ansiblevault_path=terraform.d/plugins/linux_amd64/terraform-provider-ansiblevault_v$(ansiblevault_version)_x4
+
+all: $(terraform_bin) $(ansiblevault_path) setup
+
+$(terraform_bin): $(terraform_zip)
+ rm -rf $(dir $(terraform_unzip))
+ mkdir -p $(terraform_unzip)
+ mkdir -p $(dir $(terraform_bin))
+ unzip $(terraform_zip) -d $(terraform_unzip)
+ ln -sf $(PWD)/$(terraform_unzip)/terraform $(terraform_bin)
+ touch $(PWD)/$(terraform_unzip)/terraform
+
+$(terraform_zip):
+ mkdir -p $(dir $@)
+ curl -L -o "$@" $(terraform_url)
+
+$(ansiblevault_path): terraform.d
+ mkdir -p $(dir $@)
+ curl -L -o "$@" $(ansiblevault_url)
+ chmod +x $(@)
+
+terraform.d:
+ mkdir $@
+
+MAIN=$(patsubst %/main.tf,%,$(wildcard */main.tf))
+setup: $(patsubst %,%/terraform.d,$(MAIN))
+.PHONY: setup
+
+%/terraform.d: terraform.d
+ ln -s ../terraform.d $@
+
+.terraform/plugins/linux_amd64:
+ mkdir -p $@
diff --git a/example/acme-apps/ansible/dba/acme-myapp-ci.yml b/example/acme-apps/ansible/dba/acme-myapp-ci.yml
new file mode 100644
index 0000000..e73360d
--- /dev/null
+++ b/example/acme-apps/ansible/dba/acme-myapp-ci.yml
@@ -0,0 +1,37 @@
+# Generated
+
+# cluster:
+---
+- host:
+ - acme-2
+ tasks:
+ import_role:
+ name: docker-service
+ vars:
+ template: |
+ version: "3"
+ services:
+ mdb:
+ image: mongodb:3.2
+ pdb:
+ image: postgresql:13
+
+---
+- host:
+ - acme-1
+ 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/example/acme-apps/ansible/dba/acme-myapp-production.yml b/example/acme-apps/ansible/dba/acme-myapp-production.yml
new file mode 100644
index 0000000..6b6bf6c
--- /dev/null
+++ b/example/acme-apps/ansible/dba/acme-myapp-production.yml
@@ -0,0 +1,26 @@
+# Generated
+
+# cluster:
+---
+- host:
+ - acme-3
+ 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/example/acme-apps/ansible/dba/acme-ops.yml b/example/acme-apps/ansible/dba/acme-ops.yml
new file mode 100644
index 0000000..077c554
--- /dev/null
+++ b/example/acme-apps/ansible/dba/acme-ops.yml
@@ -0,0 +1,18 @@
+# Generated
+
+# cluster:
+---
+- host:
+ - acme-2
+ tasks:
+ import_role:
+ name: docker-service
+ vars:
+ template: |
+ version: "3"
+ services:
+ n8n:
+ image: n8n:0.84.1
+ pdb:
+ image: postgresql:11
+
diff --git a/example/acme-apps/terraform/acme-1-instance.tf b/example/acme-apps/terraform/acme-1-instance.tf
new file mode 100644
index 0000000..e1aed14
--- /dev/null
+++ b/example/acme-apps/terraform/acme-1-instance.tf
@@ -0,0 +1,8 @@
+resource "scaleway_server_instance" "acme-1" {
+ name = "acme-1"
+ type = "DEV1-S"
+ image = "b3042271-d2b1-4f87-b407-aedd3bbd1663"
+ ip_id = scaleway_instance_ip.acme-1.ip
+ enable_dynamic_ip = false
+ enable_ipv6 = true
+}
diff --git a/example/acme-apps/terraform/acme-1-ip.tf b/example/acme-apps/terraform/acme-1-ip.tf
new file mode 100644
index 0000000..283eb55
--- /dev/null
+++ b/example/acme-apps/terraform/acme-1-ip.tf
@@ -0,0 +1,4 @@
+resource "scaleway_instance_reverse_dns" "acme-1" {
+ reverse = "acme-1.machine.acme.com."
+ ip_id = scaleway_instance_ip.acme-1.id
+}
diff --git a/example/acme-apps/terraform/acme-2-instance.tf b/example/acme-apps/terraform/acme-2-instance.tf
new file mode 100644
index 0000000..4ae0fe5
--- /dev/null
+++ b/example/acme-apps/terraform/acme-2-instance.tf
@@ -0,0 +1,8 @@
+resource "scaleway_server_instance" "acme-2" {
+ name = "acme-1"
+ type = "DEV1-S"
+ image = "b3042271-d2b1-4f87-b407-aedd3bbd1663"
+ ip_id = scaleway_instance_ip.acme-2.ip
+ enable_dynamic_ip = false
+ enable_ipv6 = true
+}
diff --git a/example/acme-apps/terraform/acme-2-ip.tf b/example/acme-apps/terraform/acme-2-ip.tf
new file mode 100644
index 0000000..f72fe88
--- /dev/null
+++ b/example/acme-apps/terraform/acme-2-ip.tf
@@ -0,0 +1,4 @@
+resource "scaleway_instance_reverse_dns" "acme-2" {
+ reverse = "acme-2.machine.acme.com."
+ ip_id = scaleway_instance_ip.acme-2.id
+}
diff --git a/example/acme-apps/terraform/acme-3-instance.tf b/example/acme-apps/terraform/acme-3-instance.tf
new file mode 100644
index 0000000..389b39b
--- /dev/null
+++ b/example/acme-apps/terraform/acme-3-instance.tf
@@ -0,0 +1,8 @@
+resource "scaleway_server_instance" "acme-3" {
+ name = "acme-1"
+ type = "DEV1-S"
+ image = "b3042271-d2b1-4f87-b407-aedd3bbd1663"
+ ip_id = scaleway_instance_ip.acme-3.ip
+ enable_dynamic_ip = false
+ enable_ipv6 = true
+}
diff --git a/example/acme-apps/terraform/acme-3-ip.tf b/example/acme-apps/terraform/acme-3-ip.tf
new file mode 100644
index 0000000..7d07eb9
--- /dev/null
+++ b/example/acme-apps/terraform/acme-3-ip.tf
@@ -0,0 +1,4 @@
+resource "scaleway_instance_reverse_dns" "acme-3" {
+ reverse = "acme-3.machine.acme.com."
+ ip_id = scaleway_instance_ip.acme-3.id
+}
diff --git a/example/acme-apps/terraform/main.tf b/example/acme-apps/terraform/main.tf
new file mode 100644
index 0000000..74efe05
--- /dev/null
+++ b/example/acme-apps/terraform/main.tf
@@ -0,0 +1,9 @@
+terraform {
+ required_providers {
+
+ scaleway = {
+ version = "2.0.0-rc1"
+ source = "scaleway"
+ }
+ }
+}
diff --git a/example/acme-apps/terraform/vars.tf b/example/acme-apps/terraform/vars.tf
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/example/acme-apps/terraform/vars.tf
@@ -0,0 +1 @@
+
diff --git a/example/acme-wireguard/host_vars/acme-1/wireguard.yml b/example/acme-wireguard/host_vars/acme-1/wireguard.yml
new file mode 100644
index 0000000..3c71e52
--- /dev/null
+++ b/example/acme-wireguard/host_vars/acme-1/wireguard.yml
@@ -0,0 +1,15 @@
+# Generated
+wireguard_port: 53476
+link_address: 192.168.10.3
+network_cidr: 10.55.255.0/24
+wireguard_peers:
+ acme-2:
+ public_address: acme-2.machine.acme.com
+ public_port: 53476
+ gateway: 192.168.10.4
+ network: 10.55.254.0/24
+ acme-3:
+ public_address: acme-3.machine.acme.com
+ public_port: 53476
+ gateway: 192.168.10.5
+ network: 10.55.253.0/24
diff --git a/example/acme-wireguard/host_vars/acme-2/wireguard.yml b/example/acme-wireguard/host_vars/acme-2/wireguard.yml
new file mode 100644
index 0000000..d7e4219
--- /dev/null
+++ b/example/acme-wireguard/host_vars/acme-2/wireguard.yml
@@ -0,0 +1,15 @@
+# Generated
+wireguard_port: 53476
+link_address: 192.168.10.4
+network_cidr: 10.55.254.0/24
+wireguard_peers:
+ acme-1:
+ public_address: acme-1.machine.acme.com
+ public_port: 53476
+ gateway: 192.168.10.3
+ network: 10.55.255.0/24
+ acme-3:
+ public_address: acme-3.machine.acme.com
+ public_port: 53476
+ gateway: 192.168.10.5
+ network: 10.55.253.0/24
diff --git a/example/acme-wireguard/host_vars/acme-3/wireguard.yml b/example/acme-wireguard/host_vars/acme-3/wireguard.yml
new file mode 100644
index 0000000..7d7fa76
--- /dev/null
+++ b/example/acme-wireguard/host_vars/acme-3/wireguard.yml
@@ -0,0 +1,15 @@
+# Generated
+wireguard_port: 53476
+link_address: 192.168.10.5
+network_cidr: 10.55.253.0/24
+wireguard_peers:
+ acme-1:
+ public_address: acme-1.machine.acme.com
+ public_port: 53476
+ gateway: 192.168.10.3
+ network: 10.55.255.0/24
+ acme-2:
+ public_address: acme-2.machine.acme.com
+ public_port: 53476
+ gateway: 192.168.10.4
+ network: 10.55.254.0/24
diff --git a/example/acme-wireguard/host_vars/ws-1/wireguard.yml b/example/acme-wireguard/host_vars/ws-1/wireguard.yml
new file mode 100644
index 0000000..0372db8
--- /dev/null
+++ b/example/acme-wireguard/host_vars/ws-1/wireguard.yml
@@ -0,0 +1,20 @@
+# Generated
+wireguard_port: 53476
+link_address: 192.168.10.6
+network_cidr: 10.55.252.0/24
+wireguard_peers:
+ acme-1:
+ public_address: acme-1.machine.acme.com
+ public_port: 53476
+ gateway: 192.168.10.3
+ network: 10.55.255.0/24
+ acme-2:
+ public_address: acme-2.machine.acme.com
+ public_port: 53476
+ gateway: 192.168.10.4
+ network: 10.55.254.0/24
+ acme-3:
+ public_address: acme-3.machine.acme.com
+ public_port: 53476
+ gateway: 192.168.10.5
+ network: 10.55.253.0/24
diff --git a/example/acme-wireguard/host_vars/ws-2/wireguard.yml b/example/acme-wireguard/host_vars/ws-2/wireguard.yml
new file mode 100644
index 0000000..133bd66
--- /dev/null
+++ b/example/acme-wireguard/host_vars/ws-2/wireguard.yml
@@ -0,0 +1,20 @@
+# Generated
+wireguard_port: 53476
+link_address: 192.168.10.7
+network_cidr: 10.55.251.0/24
+wireguard_peers:
+ acme-1:
+ public_address: acme-1.machine.acme.com
+ public_port: 53476
+ gateway: 192.168.10.3
+ network: 10.55.255.0/24
+ acme-2:
+ public_address: acme-2.machine.acme.com
+ public_port: 53476
+ gateway: 192.168.10.4
+ network: 10.55.254.0/24
+ acme-3:
+ public_address: acme-3.machine.acme.com
+ public_port: 53476
+ gateway: 192.168.10.5
+ network: 10.55.253.0/24
diff --git a/example/acme-wireguard/inventory.yml b/example/acme-wireguard/inventory.yml
new file mode 100644
index 0000000..de54c64
--- /dev/null
+++ b/example/acme-wireguard/inventory.yml
@@ -0,0 +1,21 @@
+# Generated
+all:
+ hosts:
+ acme-1:
+ ansible_host: acme-1.machine.acme.com
+ acme-2:
+ ansible_host: acme-2.machine.acme.com
+ acme-3:
+ ansible_host: acme-3.machine.acme.com
+ ws-1:
+ ansible_host:
+ ws-2:
+ ansible_host:
+ children:
+ wireguard_vpn0:
+ hosts:
+ acme-1:
+ acme-2:
+ acme-3:
+ ws-1:
+ ws-2:
diff --git a/example/acme-wireguard/wireguard-vpn0.yml b/example/acme-wireguard/wireguard-vpn0.yml
new file mode 100644
index 0000000..a1309e2
--- /dev/null
+++ b/example/acme-wireguard/wireguard-vpn0.yml
@@ -0,0 +1,7 @@
+- hosts: wireguard_vpn0
+ vars:
+ wireguard_if: vpn0
+ tasks:
+ - name: wireguard
+ import_role:
+ name: wireguard
diff --git a/example/acme.yaml b/example/acme.yaml
new file mode 100644
index 0000000..741e711
--- /dev/null
+++ b/example/acme.yaml
@@ -0,0 +1,78 @@
+- type: io.trygvis.acme.apps.AcmeMyApp
+ data:
+ environment: ci
+ dockerTag: development
+
+- type: io.trygvis.acme.apps.AcmeMyApp
+ data:
+ environment: production
+ dockerTag: master
+
+- type: io.trygvis.acme.apps.AcmeOps
+
+
+ # DNS configuration
+- type: io.trygvis.rules.terraform.GoogleManagedZoneTerraformExpression
+ data:
+ name: "acme_zone"
+
+
+- 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.MachineSpecificaiton
+ data:
+ mCpu: 2000
+ memory: 2000
+
+- 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
+
+- type: io.trygvis.rules.machine.Machine
+ data:
+ name: ws-1
+
+- type: io.trygvis.rules.machine.Machine
+ data:
+ name: ws-2
+
+ # Wireguard VPN network
+- type: io.trygvis.rules.wireguard.WgNet
+ data:
+ name: vpn0
+ domain: vpn.acme.com
+ port: 53476
+ linkCidr: 192.168.10.0/29
+ networkCidr: 10.55.0.0/16
+ networkBits: 24
+ \ No newline at end of file
diff --git a/example/ansible.cfg b/example/ansible.cfg
new file mode 100644
index 0000000..1790523
--- /dev/null
+++ b/example/ansible.cfg
@@ -0,0 +1,8 @@
+[defaults]
+become_method = sudo
+inventory = inventory.yml
+nocows = True
+stdout_callback = debug
+vault_password_file = .vault-password
+roles_path = roles
+retry_files_enabled = False
diff --git a/example/build.ninja b/example/build.ninja
new file mode 100644
index 0000000..7ccc450
--- /dev/null
+++ b/example/build.ninja
@@ -0,0 +1 @@
+subninja engine.ninja
diff --git a/example/db/apps.yaml b/example/db/apps.yaml
new file mode 100644
index 0000000..b27231a
--- /dev/null
+++ b/example/db/apps.yaml
@@ -0,0 +1,354 @@
+---
+- type: "io.trygvis.rules.machine.Machine"
+ data:
+ &acme-1 name: "acme-1"
+ fqdn: "acme-1.machine.acme.com"
+- type: "io.trygvis.rules.machine.Machine"
+ data:
+ &acme-2 name: "acme-2"
+ fqdn: "acme-2.machine.acme.com"
+- type: "io.trygvis.rules.machine.Machine"
+ data:
+ &acme-3 name: "acme-3"
+ fqdn: "acme-3.machine.acme.com"
+- type: "io.trygvis.rules.machine.Machine"
+ data:
+ &ws-1 name: "ws-1"
+ fqdn: null
+- type: "io.trygvis.rules.machine.Machine"
+ data:
+ &ws-2 name: "ws-2"
+ fqdn: null
+- 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.dba.Cluster"
+ data:
+ &acme-myapp-ci name: "acme-myapp-ci"
+- type: "io.trygvis.rules.dba.Cluster"
+ data:
+ &acme-myapp-production name: "acme-myapp-production"
+- type: "io.trygvis.rules.dba.Cluster"
+ data:
+ &acme-ops name: "acme-ops"
+- type: "io.trygvis.rules.dba.Container"
+ data:
+ id: "acme-myapp-ci-4tune-api"
+ cluster: *acme-myapp-ci
+ name: "4tune-api"
+ machineRole: "ci-app"
+ 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"
+ cluster: *acme-myapp-production
+ name: "4tune-api"
+ machineRole: "production-app"
+ 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"
+ cluster: *acme-myapp-ci
+ name: "4tune-web"
+ machineRole: "ci-app"
+ 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"
+ cluster: *acme-myapp-production
+ name: "4tune-web"
+ machineRole: "production-app"
+ 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"
+ cluster: *acme-myapp-ci
+ name: "mdb"
+ machineRole: "ci-db"
+ 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"
+ cluster: *acme-myapp-production
+ name: "mdb"
+ machineRole: "production-db"
+ image: "mongodb"
+ tag: "3.2"
+ machine: *acme-3
+ machineSpecification:
+ cpu: 500
+ memory: 200
+- type: "io.trygvis.rules.dba.Container"
+ data:
+ id: "acme-ops-n8n"
+ cluster: *acme-ops
+ name: "n8n"
+ machineRole: "ops"
+ image: "n8n"
+ tag: "0.84.1"
+ machine: *acme-2
+ machineSpecification: null
+- type: "io.trygvis.rules.dba.Container"
+ data:
+ id: "acme-myapp-ci-pdb"
+ cluster: *acme-myapp-ci
+ name: "pdb"
+ machineRole: "ci-db"
+ image: "postgresql"
+ tag: "13"
+ machine: *acme-2
+ machineSpecification:
+ cpu: 500
+ memory: 500
+- type: "io.trygvis.rules.dba.Container"
+ data:
+ id: "acme-myapp-production-pdb"
+ cluster: *acme-myapp-production
+ name: "pdb"
+ machineRole: "production-db"
+ image: "postgresql"
+ tag: "13"
+ machine: *acme-3
+ machineSpecification:
+ cpu: 500
+ memory: 500
+- type: "io.trygvis.rules.dba.Container"
+ data:
+ id: "acme-ops-pdb"
+ cluster: *acme-ops
+ name: "pdb"
+ machineRole: "ops"
+ image: "postgresql"
+ tag: "11"
+ machine: *acme-2
+ machineSpecification: null
+- type: "io.trygvis.rules.dba.Container"
+ data:
+ id: "acme-myapp-ci-statera"
+ cluster: *acme-myapp-ci
+ name: "statera"
+ machineRole: "ci-app"
+ image: "statera"
+ tag: "development"
+ machine: *acme-1
+ machineSpecification:
+ cpu: 200
+ memory: 1000
+- type: "io.trygvis.rules.dba.Container"
+ data:
+ id: "acme-myapp-production-statera"
+ cluster: *acme-myapp-production
+ name: "statera"
+ machineRole: "production-app"
+ 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"
+ cluster: *acme-myapp-ci
+ name: "statera-console"
+ machineRole: "ci-app"
+ 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"
+ cluster: *acme-myapp-production
+ name: "statera-console"
+ machineRole: "production-app"
+ image: "statera-console"
+ tag: "master"
+ machine: *acme-3
+ machineSpecification:
+ cpu: 100
+ memory: 50
+- type: "io.trygvis.rules.dba.DbaMachineRole"
+ data:
+ &1 machine: "acme-1"
+ roles:
+ - "ci-app"
+- type: "io.trygvis.rules.dba.DbaMachineRole"
+ data:
+ &2 machine: "acme-2"
+ roles:
+ - "ops"
+ - "ci-db"
+- type: "io.trygvis.rules.dba.DbaMachineRole"
+ data:
+ &3 machine: "acme-3"
+ roles:
+ - "production-app"
+ - "production-db"
+- type: "io.trygvis.rules.wireguard.WgNet"
+ data:
+ &vpn0 name: "vpn0"
+ domain: "vpn.acme.com"
+ port: 53476
+ linkCidr: "192.168.10.0/29"
+ networkCidr: "10.55.0.0/16"
+ networkBits: 24
+- type: "io.trygvis.rules.terraform.TerraformResource$ArrayTerraformValue"
+ data:
+ - "scaleway_instance_ip.acme-1.id"
+- type: "io.trygvis.rules.terraform.TerraformResource$ArrayTerraformValue"
+ data:
+ - "scaleway_instance_ip.acme-3.id"
+- type: "io.trygvis.rules.terraform.TerraformResource$ArrayTerraformValue"
+ data:
+ - "scaleway_instance_ip.acme-2.id"
+- type: "io.trygvis.rules.terraform.TerraformResource"
+ data:
+ output: "terraform/acme-1-instance.tf"
+ kind: "scaleway_server_instance"
+ instance: "acme-1"
+ values:
+ name: "acme-1"
+ type: "DEV1-S"
+ image: "b3042271-d2b1-4f87-b407-aedd3bbd1663"
+ ip_id: "scaleway_instance_ip.acme-1.ip"
+ enable_dynamic_ip: false
+ enable_ipv6: true
+ name: "scaleway_server_instance.acme-1"
+- type: "io.trygvis.rules.terraform.TerraformResource"
+ data:
+ output: "terraform/acme-1-ip.tf"
+ kind: "scaleway_instance_ip"
+ instance: "acme-1"
+ values: {}
+ name: "scaleway_instance_ip.acme-1"
+- type: "io.trygvis.rules.terraform.TerraformResource"
+ data:
+ output: "terraform/acme-1-ip.tf"
+ kind: "scaleway_instance_reverse_dns"
+ instance: "acme-1"
+ values:
+ reverse: "acme-1.machine.acme.com."
+ ip_id: "scaleway_instance_ip.acme-1.id"
+ name: "scaleway_instance_reverse_dns.acme-1"
+- type: "io.trygvis.rules.terraform.TerraformResource"
+ data:
+ output: "terraform/acme-2-instance.tf"
+ kind: "scaleway_server_instance"
+ instance: "acme-2"
+ values:
+ name: "acme-1"
+ type: "DEV1-S"
+ image: "b3042271-d2b1-4f87-b407-aedd3bbd1663"
+ ip_id: "scaleway_instance_ip.acme-2.ip"
+ enable_dynamic_ip: false
+ enable_ipv6: true
+ name: "scaleway_server_instance.acme-2"
+- type: "io.trygvis.rules.terraform.TerraformResource"
+ data:
+ output: "terraform/acme-2-ip.tf"
+ kind: "scaleway_instance_ip"
+ instance: "acme-2"
+ values: {}
+ name: "scaleway_instance_ip.acme-2"
+- type: "io.trygvis.rules.terraform.TerraformResource"
+ data:
+ output: "terraform/acme-2-ip.tf"
+ kind: "scaleway_instance_reverse_dns"
+ instance: "acme-2"
+ values:
+ reverse: "acme-2.machine.acme.com."
+ ip_id: "scaleway_instance_ip.acme-2.id"
+ name: "scaleway_instance_reverse_dns.acme-2"
+- type: "io.trygvis.rules.terraform.TerraformResource"
+ data:
+ output: "terraform/acme-3-instance.tf"
+ kind: "scaleway_server_instance"
+ instance: "acme-3"
+ values:
+ name: "acme-1"
+ type: "DEV1-S"
+ image: "b3042271-d2b1-4f87-b407-aedd3bbd1663"
+ ip_id: "scaleway_instance_ip.acme-3.ip"
+ enable_dynamic_ip: false
+ enable_ipv6: true
+ name: "scaleway_server_instance.acme-3"
+- type: "io.trygvis.rules.terraform.TerraformResource"
+ data:
+ output: "terraform/acme-3-ip.tf"
+ kind: "scaleway_instance_ip"
+ instance: "acme-3"
+ values: {}
+ name: "scaleway_instance_ip.acme-3"
+- type: "io.trygvis.rules.terraform.TerraformResource"
+ data:
+ output: "terraform/acme-3-ip.tf"
+ kind: "scaleway_instance_reverse_dns"
+ instance: "acme-3"
+ values:
+ reverse: "acme-3.machine.acme.com."
+ ip_id: "scaleway_instance_ip.acme-3.id"
+ name: "scaleway_instance_reverse_dns.acme-3"
+- type: "io.trygvis.rules.terraform.TerraformMain"
+ data:
+ module: "terraform"
+ providers:
+ scaleway:
+ source: "scaleway"
+ version: "2.0.0-rc1"
+- type: "io.trygvis.rules.engine.KeyValue"
+ data:
+ key: "rm-gen"
+ value: null
+- type: "io.trygvis.acme.AcmeServer"
+ data:
+ &acme-1 name: "acme-1"
+ machine: *acme-1
+- type: "io.trygvis.acme.AcmeServer"
+ data:
+ &acme-2 name: "acme-2"
+ machine: *acme-2
+- type: "io.trygvis.acme.AcmeServer"
+ data:
+ &acme-3 name: "acme-3"
+ machine: *acme-3
+- type: "io.trygvis.acme.apps.AcmeOps"
+ data: {}
+- type: "io.trygvis.acme.apps.AcmeMyApp"
+ data:
+ environment: "ci"
+ dockerTag: "development"
+- type: "io.trygvis.acme.apps.AcmeMyApp"
+ data:
+ environment: "production"
+ dockerTag: "master"
diff --git a/example/db/wireguard.yaml b/example/db/wireguard.yaml
new file mode 100644
index 0000000..a374351
--- /dev/null
+++ b/example/db/wireguard.yaml
@@ -0,0 +1,161 @@
+---
+- type: "io.trygvis.rules.machine.Machine"
+ data:
+ &acme-1 name: "acme-1"
+ fqdn: "acme-1.machine.acme.com"
+- type: "io.trygvis.rules.machine.Machine"
+ data:
+ &acme-2 name: "acme-2"
+ fqdn: "acme-2.machine.acme.com"
+- type: "io.trygvis.rules.machine.Machine"
+ data:
+ &acme-3 name: "acme-3"
+ fqdn: "acme-3.machine.acme.com"
+- type: "io.trygvis.rules.machine.Machine"
+ data:
+ &ws-1 name: "ws-1"
+ fqdn: null
+- type: "io.trygvis.rules.machine.Machine"
+ data:
+ &ws-2 name: "ws-2"
+ fqdn: null
+- type: "io.trygvis.rules.dns.DnsEntry"
+ data:
+ fqdn: "acme-1.vpn.acme.com"
+ type: "A"
+- type: "io.trygvis.rules.dns.DnsEntry"
+ data:
+ fqdn: "acme-2.vpn.acme.com"
+ type: "A"
+- type: "io.trygvis.rules.dns.DnsEntry"
+ data:
+ fqdn: "acme-3.vpn.acme.com"
+ type: "A"
+- type: "io.trygvis.rules.dns.DnsEntry"
+ data:
+ fqdn: "ws-1.vpn.acme.com"
+ type: "A"
+- type: "io.trygvis.rules.dns.DnsEntry"
+ data:
+ fqdn: "ws-2.vpn.acme.com"
+ type: "A"
+- type: "io.trygvis.rules.wireguard.WgNet"
+ data:
+ &vpn0 name: "vpn0"
+ domain: "vpn.acme.com"
+ port: 53476
+ linkCidr: "192.168.10.0/29"
+ networkCidr: "10.55.0.0/16"
+ networkBits: 24
+- type: "io.trygvis.rules.wireguard.WgIpPool"
+ data:
+ &1 net: *vpn0
+ role: "link"
+ cidr:
+ value: "192.168.10.0/29"
+- type: "io.trygvis.rules.wireguard.WgIpPool"
+ data:
+ &2 net: *vpn0
+ role: "networks"
+ cidr:
+ value: "10.55.0.0/16"
+- type: "io.trygvis.rules.wireguard.WgHost"
+ data:
+ &3 machine: *ws-1
+ net: *vpn0
+ publicName: null
+ publicPort: 53476
+ ip: "192.168.10.6"
+ networkCidr: "10.55.252.0/24"
+- type: "io.trygvis.rules.wireguard.WgHost"
+ data:
+ &4 machine: *ws-2
+ net: *vpn0
+ publicName: null
+ publicPort: 53476
+ ip: "192.168.10.7"
+ networkCidr: "10.55.251.0/24"
+- type: "io.trygvis.rules.wireguard.WgHost"
+ data:
+ &5 machine: *acme-1
+ net: *vpn0
+ publicName: "acme-1.machine.acme.com"
+ publicPort: 53476
+ ip: "192.168.10.3"
+ networkCidr: "10.55.255.0/24"
+- type: "io.trygvis.rules.wireguard.WgHost"
+ data:
+ &6 machine: *acme-2
+ net: *vpn0
+ publicName: "acme-2.machine.acme.com"
+ publicPort: 53476
+ ip: "192.168.10.4"
+ networkCidr: "10.55.254.0/24"
+- type: "io.trygvis.rules.wireguard.WgHost"
+ data:
+ &7 machine: *acme-3
+ net: *vpn0
+ publicName: "acme-3.machine.acme.com"
+ publicPort: 53476
+ ip: "192.168.10.5"
+ networkCidr: "10.55.253.0/24"
+- type: "io.trygvis.rules.wireguard.WgConnection"
+ data:
+ &acme-1_x_acme-2 name: "acme-1_x_acme-2"
+ host: *5
+ to: *6
+- type: "io.trygvis.rules.wireguard.WgConnection"
+ data:
+ &acme-1_x_acme-3 name: "acme-1_x_acme-3"
+ host: *5
+ to: *7
+- type: "io.trygvis.rules.wireguard.WgConnection"
+ data:
+ &acme-2_x_acme-1 name: "acme-2_x_acme-1"
+ host: *6
+ to: *5
+- type: "io.trygvis.rules.wireguard.WgConnection"
+ data:
+ &acme-2_x_acme-3 name: "acme-2_x_acme-3"
+ host: *6
+ to: *7
+- type: "io.trygvis.rules.wireguard.WgConnection"
+ data:
+ &acme-3_x_acme-1 name: "acme-3_x_acme-1"
+ host: *7
+ to: *5
+- type: "io.trygvis.rules.wireguard.WgConnection"
+ data:
+ &acme-3_x_acme-2 name: "acme-3_x_acme-2"
+ host: *7
+ to: *6
+- type: "io.trygvis.rules.wireguard.WgConnection"
+ data:
+ &ws-1_x_acme-1 name: "ws-1_x_acme-1"
+ host: *3
+ to: *5
+- type: "io.trygvis.rules.wireguard.WgConnection"
+ data:
+ &ws-1_x_acme-2 name: "ws-1_x_acme-2"
+ host: *3
+ to: *6
+- type: "io.trygvis.rules.wireguard.WgConnection"
+ data:
+ &ws-1_x_acme-3 name: "ws-1_x_acme-3"
+ host: *3
+ to: *7
+- type: "io.trygvis.rules.wireguard.WgConnection"
+ data:
+ &ws-2_x_acme-1 name: "ws-2_x_acme-1"
+ host: *4
+ to: *5
+- type: "io.trygvis.rules.wireguard.WgConnection"
+ data:
+ &ws-2_x_acme-2 name: "ws-2_x_acme-2"
+ host: *4
+ to: *6
+- type: "io.trygvis.rules.wireguard.WgConnection"
+ data:
+ &ws-2_x_acme-3 name: "ws-2_x_acme-3"
+ host: *4
+ to: *7
diff --git a/example/engine.ninja b/example/engine.ninja
index 3e6c6f3..3c53218 100644
--- a/example/engine.ninja
+++ b/example/engine.ninja
@@ -5,7 +5,7 @@
rule engine-yaml-to-ninja
command = engine ninja
-build engine.ninja: engine.yaml
+build engine.ninja: engine-yaml-to-ninja engine.yaml
### engine.png
@@ -22,35 +22,32 @@ build engine.png: dot-to-png engine.dot
# Jobs
rule acme
- command=engine run $name $inputs $output_state $agenda_group $modules
+ command=engine run $name $inputs $output_state $output_includes $generated_output $agenda_groups $modules
build db/acme.yaml: acme
name=--name acme
output_state=--output-state db/acme.yaml
- agenda_group=
modules=$
--module=foo $
--module=bar
rule acme-apps
- command=engine run $name $inputs $output_state $agenda_group $modules
+ command=engine run $name $inputs $output_state $output_includes $generated_output $agenda_groups $modules
build db/acme-apps.yaml: acme-apps db/acme.yaml
name=--name acme-apps
inputs=$
--input=db/acme.yaml
output_state=--output-state db/acme-apps.yaml
- agenda_group=
rule acme-wireguard
- command=engine run $name $inputs $output_state $agenda_group $modules
+ command=engine run $name $inputs $output_state $output_includes $generated_output $agenda_groups $modules
build db/acme-wireguard.yaml: acme-wireguard db/acme.yaml
name=--name acme-wireguard
inputs=$
--input=db/acme.yaml
output_state=--output-state db/acme-wireguard.yaml
- agenda_group=
modules=$
--module=foo $
--module=$$MODULE_HOME/bar
diff --git a/example/main.tf b/example/main.tf
new file mode 100644
index 0000000..c7b91b2
--- /dev/null
+++ b/example/main.tf
@@ -0,0 +1,60 @@
+terraform {
+ required_providers {
+ scaleway = {
+ source = "scaleway/scaleway"
+ version = "1.17.2"
+ }
+
+ ansiblevault = {
+ source = "MeilleursAgents/ansiblevault"
+ version = "2.2.0"
+ }
+ }
+}
+
+variable "ansible_vault_pass" {
+ type = string
+}
+
+provider "ansiblevault" {
+ # vault_path = ".vault-password"
+ vault_pass = var.ansible_vault_pass
+ root_folder = "."
+}
+
+data "ansiblevault_path" "scaleway_access_key" {
+ path = "vault/scaleway.yml"
+ key = "scaleway_access_key"
+}
+data "ansiblevault_path" "scaleway_secret_key" {
+ path = "vault/scaleway.yml"
+ key = "scaleway_secret_key"
+}
+data "ansiblevault_path" "scaleway_organization" {
+ path = "vault/scaleway.yml"
+ key = "scaleway_organization"
+}
+
+provider "scaleway" {
+ region = "fr-par"
+ zone = "fr-par-1"
+ access_key = data.ansiblevault_path.scaleway_access_key.value
+ secret_key = data.ansiblevault_path.scaleway_secret_key.value
+ organization_id = data.ansiblevault_path.scaleway_organization.value
+}
+
+# This can also be generated from input objects, but it might be reused between different modules so some control
+# over if/when it is generated is required.
+resource "google_dns_managed_zone" "acme" {
+ name = "acme"
+ dns_name = "machine.acme.com."
+}
+
+module "acme-apps" {
+ source = "../acme-apps/terraform"
+ providers = {
+ scaleway = scaleway
+ }
+
+ acme_zone = google_dns_managed_zone.acme.name
+}
diff --git a/example/modules/acme/pom.xml b/example/modules/acme/pom.xml
new file mode 100644
index 0000000..01b9ab0
--- /dev/null
+++ b/example/modules/acme/pom.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>io.trygvis.rules-sandbox.module</groupId>
+ <artifactId>ri-module-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <relativePath>../../../modules/ri-module-parent/pom.xml</relativePath>
+ </parent>
+
+ <artifactId>acme</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ri-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ri-wireguard</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/example/modules/acme/src/main/java/io/trygvis/acme/AcmeAppsMain.java b/example/modules/acme/src/main/java/io/trygvis/acme/AcmeAppsMain.java
new file mode 100644
index 0000000..c65a3b2
--- /dev/null
+++ b/example/modules/acme/src/main/java/io/trygvis/acme/AcmeAppsMain.java
@@ -0,0 +1,14 @@
+package io.trygvis.acme;
+
+public class AcmeAppsMain {
+// public static void main(String[] args) throws IOException {
+// try (var engine = new Engine(
+// "acme-apps",
+// new File("acme.yaml"),
+// new File("acme-apps"),
+// new String[]{"init", "generate"},
+// new File[0])) {
+// engine.io.dump(new File("out", "acme/apps.yaml"), engine.session.getFactHandles());
+// }
+// }
+}
diff --git a/example/modules/acme/src/main/java/io/trygvis/acme/VpnMain.java b/example/modules/acme/src/main/java/io/trygvis/acme/VpnMain.java
new file mode 100644
index 0000000..cbf962c
--- /dev/null
+++ b/example/modules/acme/src/main/java/io/trygvis/acme/VpnMain.java
@@ -0,0 +1,21 @@
+package io.trygvis.acme;
+
+public class VpnMain {
+// public static void main(String[] args) throws IOException {
+// try (var engine = new Engine(
+// "acme-wireguard",
+// new File("acme.yaml"),
+// new File("acme-wireguard"),
+// new String[]{"init", "generate"},
+// new File[0])) {
+// var outputFile = new File("out", "acme/wireguard.yaml");
+// engine.io.dump(outputFile, engine.session.getFactHandles(), (Object o) ->
+// o.getClass().getName().contains("Wg")
+// || o instanceof Machine
+// || o instanceof DnsEntry
+// || o instanceof Ipv4Cidr
+// || o instanceof Ipv4Address
+// );
+// }
+// }
+}
diff --git a/example/modules/acme/src/main/java/io/trygvis/acme/apps/AcmeMyApp.java b/example/modules/acme/src/main/java/io/trygvis/acme/apps/AcmeMyApp.java
new file mode 100644
index 0000000..9371af2
--- /dev/null
+++ b/example/modules/acme/src/main/java/io/trygvis/acme/apps/AcmeMyApp.java
@@ -0,0 +1,6 @@
+package io.trygvis.acme.apps;
+
+public class AcmeMyApp {
+ public String environment;
+ public String dockerTag;
+}
diff --git a/example/modules/acme/src/main/java/io/trygvis/acme/apps/AcmeOps.java b/example/modules/acme/src/main/java/io/trygvis/acme/apps/AcmeOps.java
new file mode 100644
index 0000000..be9d82b
--- /dev/null
+++ b/example/modules/acme/src/main/java/io/trygvis/acme/apps/AcmeOps.java
@@ -0,0 +1,4 @@
+package io.trygvis.acme.apps;
+
+public class AcmeOps {
+}
diff --git a/example/modules/acme/src/main/resources/META-INF/kmodule.xml b/example/modules/acme/src/main/resources/META-INF/kmodule.xml
new file mode 100644
index 0000000..da435d6
--- /dev/null
+++ b/example/modules/acme/src/main/resources/META-INF/kmodule.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://www.drools.org/xsd/kmodule"
+ xsi:schemaLocation="http://www.drools.org/xsd/kmodule https://www.drools.org/xsd/kmodule_7_1.xsd">
+
+ <kbase name="acme-apps" packages="io.trygvis.acme.apps" includes="dba,engine,machine,terraform, acme-shared">
+ <ksession name="acme-apps" default="true"/>
+ </kbase>
+
+ <kbase name="acme-wireguard" packages="io.trygvis.acme.wireguard" includes="engine,wireguard, acme-shared">
+ <ksession name="acme-wireguard" default="true"/>
+ </kbase>
+
+ <kbase name="acme-shared" packages="io.trygvis.acme">
+ <ksession name="acme-shared" default="true"/>
+ </kbase>
+</kmodule>
diff --git a/example/modules/acme/src/main/resources/io/trygvis/acme/acme.drl b/example/modules/acme/src/main/resources/io/trygvis/acme/acme.drl
new file mode 100644
index 0000000..6a2f33b
--- /dev/null
+++ b/example/modules/acme/src/main/resources/io/trygvis/acme/acme.drl
@@ -0,0 +1,81 @@
+package io.trygvis.acme;
+
+import io.trygvis.rules.machine.Machine;
+import io.trygvis.rules.dba.Cluster;
+import io.trygvis.rules.dba.Container
+import io.trygvis.rules.terraform.TerraformResource;
+import io.trygvis.rules.terraform.TerraformMain
+import io.trygvis.rules.terraform.TerraformProvider;
+
+dialect "mvel"
+
+declare AcmeServer
+ name : String
+ machine : Machine
+end
+
+rule "Create Acme servers"
+when
+ $m : Machine(name.startsWith("acme-"))
+ not(AcmeServer(name == $m.name))
+then
+ var s = new AcmeServer();
+ s.name = $m.name;
+ s.machine = $m;
+ insert(s);
+end
+
+rule "Set public domain for ACME servers"
+when
+ $m : Machine(fqdn == null)
+ $s : AcmeServer(machine == $m)
+then
+ var fqdn = "%s.machine.acme.com".formatted($m.name);
+ modify ($m) {
+ fqdn = fqdn
+ }
+end
+
+rule "Make Terraform module for machines"
+when
+ not TerraformMain(module == "terraform")
+then
+ var module = new TerraformMain("terraform");
+
+ var scaleway = new TerraformProvider("scaleway", "2.0.0-rc1");
+ module.getProviders().put("scaleway", scaleway);
+
+ insert(module)
+end
+
+rule "Make Scaleway Terraform resources for Machine"
+when
+ $m : Machine()
+ $s : AcmeServer(machine == $m)
+then
+ var ip = new TerraformResource("terraform/" + $m.name + "-ip.tf", "scaleway_instance_ip", $m.name);
+ var instance = new TerraformResource("terraform/" + $m.name + "-instance.tf", "scaleway_server_instance", $m.name)
+ .set("name", "acme-1")
+ .set("type", "DEV1-S")
+ .set("image", "b3042271-d2b1-4f87-b407-aedd3bbd1663")
+ .setExpression("ip_id", ip.name + ".ip")
+ .set("enable_dynamic_ip", false)
+ .set("enable_ipv6", true);
+
+
+ var rev = new TerraformResource("terraform/" + $m.name + "-ip.tf", "scaleway_instance_reverse_dns", $m.name)
+ .set("reverse", $m.fqdn + ".")
+ .setExpression("ip_id", ip.name + ".id");
+ var dns = new TerraformResource("terraform/" + $m.name + "-dns.tf", "google_dns_record_set", $m.name)
+ .set("name", $m.fqdn)
+ .setExpression("managed_zone", "var.dns_zone")
+ .set("type", "A")
+ .set("ttl", 300)
+ .array("rrdatas")
+ .addExpression(ip.name + ".id");
+
+ insert(instance)
+ insert(ip)
+ insert(rev)
+ insert(dns)
+end
diff --git a/example/modules/acme/src/main/resources/io/trygvis/acme/apps/apps.drl b/example/modules/acme/src/main/resources/io/trygvis/acme/apps/apps.drl
new file mode 100644
index 0000000..670079f
--- /dev/null
+++ b/example/modules/acme/src/main/resources/io/trygvis/acme/apps/apps.drl
@@ -0,0 +1,44 @@
+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.dns.DnsZone;
+import io.trygvis.rules.machine.Machine
+import io.trygvis.rules.machine.MachineSpecification
+import io.trygvis.rules.dba.Cluster
+import io.trygvis.rules.dba.Container
+
+dialect "mvel"
+
+rule "Ops"
+when
+ $ops: AcmeOps()
+then
+ var cluster = new Cluster("acme-ops");
+ insert(cluster);
+ insert(new Container(cluster, "pdb", "ops", "postgresql", "11", null));
+ insert(new Container(cluster, "n8n", "ops", "n8n", "0.84.1", null));
+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, "statera", app, "statera", tag, new MachineSpecification(200, 1000)));
+ insert(new Container(cluster, "statera-console", app, "statera-console", tag, new MachineSpecification(100, 50)));
+ insert(new Container(cluster, "4tune-web", app, "4tune-web", tag, new MachineSpecification(100, 50)));
+ insert(new Container(cluster, "4tune-api", app, "4tune-api", tag, new MachineSpecification(200, 200)));
+ insert(new Container(cluster, "pdb", db, "postgresql", "13", new MachineSpecification(500, 500)));
+ insert(new Container(cluster, "mdb", db, "mongodb", "3.2", new MachineSpecification(500, 200)));
+end