From 191799ab976bd7dad7162d62bf86f2d3cc5d0dbd Mon Sep 17 00:00:00 2001
From: Trygve Laugstøl <trygvis@inamo.no>
Date: Sat, 30 Jan 2021 14:04:37 +0100
Subject: Better Terraform resources.

---
 .../trygvis/rules/terraform/TerraformResource.java | 117 ++++++++++++++++++++-
 .../src/main/resources/META-INF/kmodule.xml        |   1 +
 .../io/trygvis/rules/scaleway/terraform.drl        |  81 ++++++++++++++
 .../rules/terraform/terraform-resources.drl        |  14 +++
 .../io/trygvis/rules/terraform/terraform.drl       |  81 --------------
 .../main/resources/templates/terraform/resource.j2 |   1 +
 6 files changed, 210 insertions(+), 85 deletions(-)
 create mode 100644 module/ri-base/src/main/resources/io/trygvis/rules/scaleway/terraform.drl
 create mode 100644 module/ri-base/src/main/resources/io/trygvis/rules/terraform/terraform-resources.drl
 delete mode 100644 module/ri-base/src/main/resources/io/trygvis/rules/terraform/terraform.drl
 create mode 100644 module/ri-base/src/main/resources/templates/terraform/resource.j2

(limited to 'module/ri-base')

diff --git a/module/ri-base/src/main/java/io/trygvis/rules/terraform/TerraformResource.java b/module/ri-base/src/main/java/io/trygvis/rules/terraform/TerraformResource.java
index 41bd6ae..8ca6ae2 100644
--- a/module/ri-base/src/main/java/io/trygvis/rules/terraform/TerraformResource.java
+++ b/module/ri-base/src/main/java/io/trygvis/rules/terraform/TerraformResource.java
@@ -1,14 +1,16 @@
 package io.trygvis.rules.terraform;
 
-import java.util.HashMap;
-import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonValue;
 
+import java.util.*;
+
+@SuppressWarnings("unused")
 public class TerraformResource {
     private static final String EOL = System.getProperty("line.separator");
     private final String output;
     private final String kind;
     private final String instance;
-    private final Map<String, TerraformValue> values = new HashMap<>();
+    private final Map<String, TerraformValue> values = new LinkedHashMap<>();
 
     public TerraformResource(String output, String kind, String instance) {
         this.output = output;
@@ -20,10 +22,40 @@ public class TerraformResource {
         return output;
     }
 
-    public void putString(String key, String value) {
+    public String getKind() {
+        return kind;
+    }
+
+    public String getInstance() {
+        return instance;
+    }
+
+    public Map<String, TerraformValue> getValues() {
+        return values;
+    }
+
+    public void set(String key, String value) {
         values.put(key, new StringTerraformValue(value));
     }
 
+    public void set(String key, boolean value) {
+        values.put(key, new BooleanTerraformValue(value));
+    }
+
+    public void set(String key, int value) {
+        values.put(key, new IntegerTerraformValue(value));
+    }
+
+    public void setExpression(String key, String value) {
+        values.put(key, new ExpressionTerraformValue(value));
+    }
+
+    public ArrayTerraformValue array(String key) {
+        var array = new ArrayTerraformValue();
+        values.put(key, array);
+        return array;
+    }
+
     public String asString() {
         var buf = new StringBuilder();
 
@@ -58,6 +90,11 @@ public class TerraformResource {
             this.value = value;
         }
 
+        @JsonValue
+        public String getValue() {
+            return value;
+        }
+
         @Override
         public String asString() {
             return quote(value);
@@ -71,6 +108,29 @@ public class TerraformResource {
             this.value = value;
         }
 
+        @JsonValue
+        public boolean getValue() {
+            return value;
+        }
+
+        @Override
+        public String asString() {
+            return String.valueOf(value);
+        }
+    }
+
+    public static class IntegerTerraformValue implements TerraformValue {
+        private final int value;
+
+        public IntegerTerraformValue(int value) {
+            this.value = value;
+        }
+
+        @JsonValue
+        public int getValue() {
+            return value;
+        }
+
         @Override
         public String asString() {
             return String.valueOf(value);
@@ -84,12 +144,61 @@ public class TerraformResource {
             this.value = value;
         }
 
+        @JsonValue
+        public String getValue() {
+            return value;
+        }
+
         @Override
         public String asString() {
             return value;
         }
     }
 
+    public static class ArrayTerraformValue implements TerraformValue {
+        private final List<TerraformValue> values = new ArrayList<>();
+
+        @JsonValue
+        public List<TerraformValue> getValues() {
+            return values;
+        }
+
+        public ArrayTerraformValue add(String value) {
+            values.add(new StringTerraformValue(value));
+            return this;
+        }
+
+        public ArrayTerraformValue add(int value) {
+            values.add(new IntegerTerraformValue(value));
+            return this;
+        }
+
+        public ArrayTerraformValue add(boolean value) {
+            values.add(new BooleanTerraformValue(value));
+            return this;
+        }
+
+        public ArrayTerraformValue addExpression(String value) {
+            values.add(new ExpressionTerraformValue(value));
+            return this;
+        }
+
+        @Override
+        public String asString() {
+            if (values.isEmpty()) {
+                return "[]";
+            }
+
+            if (values.size() == 1) {
+                return "[" + values.get(0).asString() + "]";
+            }
+
+            var j = new StringJoiner(",\n  ", "[\n", "\n  ]");
+            values.forEach(value -> j.add(value.asString()));
+            return j.toString();
+        }
+    }
+
     private static String quote(String value) {
         return "\"%s\"".formatted(value);
     }
diff --git a/module/ri-base/src/main/resources/META-INF/kmodule.xml b/module/ri-base/src/main/resources/META-INF/kmodule.xml
index 79c5e79..4650977 100644
--- a/module/ri-base/src/main/resources/META-INF/kmodule.xml
+++ b/module/ri-base/src/main/resources/META-INF/kmodule.xml
@@ -8,4 +8,5 @@
   <kbase name="dba" packages="io.trygvis.rules.dba"/>
   <kbase name="machine" packages="io.trygvis.rules.machine"/>
   <kbase name="terraform" packages="io.trygvis.rules.terraform"/>
+  <kbase name="scaleway" packages="io.trygvis.rules.scaleway"/>
 </kmodule>
diff --git a/module/ri-base/src/main/resources/io/trygvis/rules/scaleway/terraform.drl b/module/ri-base/src/main/resources/io/trygvis/rules/scaleway/terraform.drl
new file mode 100644
index 0000000..06bfc68
--- /dev/null
+++ b/module/ri-base/src/main/resources/io/trygvis/rules/scaleway/terraform.drl
@@ -0,0 +1,81 @@
+package io.trygvis.rules.terraform.scaleway
+
+import io.trygvis.rules.dba.Cluster
+import io.trygvis.rules.dba.Container
+import io.trygvis.rules.machine.Machine
+import io.trygvis.rules.dns.DnsEntry
+import io.trygvis.rules.dns.DnsEntryTerraformExpression
+import java.util.ArrayList;
+import java.util.Map;
+
+global io.trygvis.rules.engine.TemplateEngine te;
+
+dialect  "mvel"
+
+declare ScalewayMachine
+    machine : Machine
+    key : String
+end
+
+declare GoogleManagedZoneTerraformExpression
+    name : String
+end
+
+rule "Terraform for Machine"
+when
+    $machine: Machine()
+then
+    ScalewayMachine scw = new ScalewayMachine();
+    scw.setKey($machine.name);
+    scw.setMachine($machine);
+
+    insert(scw);
+end
+
+rule "Create DNS entry for Terraform Machine"
+when
+    $machine : Machine(fqdn != null)
+    not(DnsEntry(fqdn == $machine.fqdn))
+then
+    DnsEntry a = DnsEntry.a($machine.fqdn);
+    insert(a);
+
+    String ipv4 = "scaleway_instance_ip.%s.address".formatted($machine.name);
+    insert(new DnsEntryTerraformExpression(a, $machine.name, ipv4));
+end
+
+rule "main-scaleway-machine.tf"
+    agenda-group "generate"
+when
+    $managedZones : ArrayList() from collect(GoogleManagedZoneTerraformExpression())
+then
+    String path = "terraform/main-scaleway-machine.tf";
+    te.template("terraform/main-scaleway-machine", path, Map.of(
+        "managedZones", $managedZones
+    ));
+end
+
+rule "TF for TerraformMachine"
+    agenda-group "generate"
+when
+    $m: Machine()
+    $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));
+end
+
+rule "Terraform for DNS"
+    agenda-group "generate"
+when
+    $entry: DnsEntry()
+    $tf : DnsEntryTerraformExpression(entry == $entry)
+    $managedZone : GoogleManagedZoneTerraformExpression()
+then
+    String path = "terraform/dns-%s.tf".formatted($tf.key);
+    te.template("terraform/record-set", path, Map.of(
+            "entry", $entry,
+            "managedZone", $managedZone,
+            "tf", $tf)
+    );
+end
diff --git a/module/ri-base/src/main/resources/io/trygvis/rules/terraform/terraform-resources.drl b/module/ri-base/src/main/resources/io/trygvis/rules/terraform/terraform-resources.drl
new file mode 100644
index 0000000..34af8fe
--- /dev/null
+++ b/module/ri-base/src/main/resources/io/trygvis/rules/terraform/terraform-resources.drl
@@ -0,0 +1,14 @@
+package io.trygvis.rules.terraform;
+import java.util.Map
+
+global io.trygvis.rules.engine.TemplateEngine te;
+
+dialect  "mvel"
+
+rule "terraform-resources"
+    agenda-group "generate"
+when
+    $r : TerraformResource()
+then
+    te.template("terraform/resource", $r.output, Map.of("resource", $r));
+end
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
deleted file mode 100644
index 7313998..0000000
--- a/module/ri-base/src/main/resources/io/trygvis/rules/terraform/terraform.drl
+++ /dev/null
@@ -1,81 +0,0 @@
-package io.trygvis.rules.terraform
-
-import io.trygvis.rules.dba.Cluster
-import io.trygvis.rules.dba.Container
-import io.trygvis.rules.machine.Machine
-import io.trygvis.rules.dns.DnsEntry
-import io.trygvis.rules.dns.DnsEntryTerraformExpression
-import java.util.ArrayList;
-import java.util.Map;
-
-global io.trygvis.rules.engine.TemplateEngine te;
-
-dialect  "mvel"
-
-declare ScalewayMachine
-    machine : Machine
-    key : String
-end
-
-declare GoogleManagedZoneTerraformExpression
-    name : String
-end
-
-rule "Terraform for Machine"
-when
-    $machine: Machine()
-then
-    ScalewayMachine scw = new ScalewayMachine();
-    scw.setKey($machine.name);
-    scw.setMachine($machine);
-
-    insert(scw);
-end
-
-rule "Create DNS entry for Terraform Machine"
-when
-    $machine : Machine(fqdn != null)
-    not(DnsEntry(fqdn == $machine.fqdn))
-then
-    DnsEntry a = DnsEntry.a($machine.fqdn);
-    insert(a);
-
-    String ipv4 = "scaleway_instance_ip.%s.address".formatted($machine.name);
-    insert(new DnsEntryTerraformExpression(a, $machine.name, ipv4));
-end
-
-rule "main-scaleway-machine.tf"
-    agenda-group "generate"
-when
-    $managedZones : ArrayList() from collect(GoogleManagedZoneTerraformExpression())
-then
-    String path = "terraform/main-scaleway-machine.tf";
-    te.template("terraform/main-scaleway-machine", path, Map.of(
-        "managedZones", $managedZones
-    ));
-end
-
-rule "TF for TerraformMachine"
-    agenda-group "generate"
-when
-    $m: Machine()
-    $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));
-end
-
-rule "Terraform for DNS"
-    agenda-group "generate"
-when
-    $entry: DnsEntry()
-    $tf : DnsEntryTerraformExpression(entry == $entry)
-    $managedZone : GoogleManagedZoneTerraformExpression()
-then
-    String path = "terraform/dns-%s.tf".formatted($tf.key);
-    te.template("terraform/record-set", path, Map.of(
-            "entry", $entry,
-            "managedZone", $managedZone,
-            "tf", $tf)
-    );
-end
diff --git a/module/ri-base/src/main/resources/templates/terraform/resource.j2 b/module/ri-base/src/main/resources/templates/terraform/resource.j2
new file mode 100644
index 0000000..91af481
--- /dev/null
+++ b/module/ri-base/src/main/resources/templates/terraform/resource.j2
@@ -0,0 +1 @@
+{{ resource.asString() -}}
-- 
cgit v1.2.3