From 912bc8b903dfa6d438c2469ecdad35c181c71830 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Mon, 25 Jan 2021 21:29:12 +0100 Subject: Improving usability, massive refactoring. * Moving all Drools code into their own modules. This fixes ri-engine to acme dependency. * Now they all inherit from their own parent, should be used by third party code too. * Separating acme planning code into its own module. * Splitting rules code from ri-engine into ri-base. ri-engine is now a pure launcher for modules. * Dumping kogito for the most part, but it seems like the planner still requires that. --- .run/CloudPlaningMain.run.xml | 15 ++ .settings.sh | 2 + module/acme-planner/classpath.txt | 133 ++++++++++++++++++ module/acme-planner/pom.xml | 38 ++++++ .../acme/planning/machine/CloudBalance.java | 48 +++++++ .../machine/CloudBalancingEasyScoreCalculator.java | 45 ++++++ .../acme/planning/machine/CloudComputer.java | 16 +++ .../acme/planning/machine/CloudPlaningMain.java | 52 +++++++ .../acme/planning/machine/CloudPlanner.java | 22 +++ .../acme/planning/machine/CloudProcess.java | 48 +++++++ .../machine/CloudProcessDifficultyComparator.java | 15 ++ .../acme/planning/machine/ScalewayInstance.java | 25 ++++ .../acme/planning/machine/solver-config.xml | 18 +++ module/acme/classpath.txt | 62 +-------- module/acme/pom.xml | 23 +--- .../main/java/io/trygvis/acme/AcmeAppsMain.java | 24 ++-- .../src/main/java/io/trygvis/acme/VpnMain.java | 41 +++--- .../acme/planning/machine/CloudBalance.java | 48 ------- .../machine/CloudBalancingEasyScoreCalculator.java | 45 ------ .../acme/planning/machine/CloudComputer.java | 16 --- .../acme/planning/machine/CloudPlaningMain.java | 52 ------- .../acme/planning/machine/CloudPlanner.java | 22 --- .../acme/planning/machine/CloudProcess.java | 48 ------- .../machine/CloudProcessDifficultyComparator.java | 15 -- .../acme/planning/machine/ScalewayInstance.java | 25 ---- .../acme/planning/machine/solver-config.xml | 18 --- module/ri-base/classpath.txt | 26 ++++ module/ri-base/pom.xml | 66 +++++++++ .../main/java/io/trygvis/rules/core/Problem.java | 11 ++ .../main/java/io/trygvis/rules/dba/Cluster.java | 13 ++ .../main/java/io/trygvis/rules/dba/Container.java | 59 ++++++++ .../main/java/io/trygvis/rules/dns/DnsEntry.java | 27 ++++ .../rules/dns/DnsEntryTerraformExpression.java | 21 +++ .../main/java/io/trygvis/rules/dns/DnsZone.java | 9 ++ .../java/io/trygvis/rules/engine/KeyValue.java | 14 ++ .../io/trygvis/rules/engine/TemplateEngine.java | 10 ++ .../java/io/trygvis/rules/machine/Machine.java | 29 ++++ .../rules/machine/MachineSpecification.java | 19 +++ .../main/java/io/trygvis/rules/network/IpCalc.java | 6 + .../java/io/trygvis/rules/network/Ipv4Address.java | 58 ++++++++ .../java/io/trygvis/rules/network/Ipv4Cidr.java | 150 ++++++++++++++++++++ .../trygvis/rules/terraform/TerraformResource.java | 96 +++++++++++++ .../src/main/resources/META-INF/kmodule.xml | 11 ++ .../main/resources/io/trygvis/rules/dba/dba.drl | 69 ++++++++++ .../resources/io/trygvis/rules/engine/init.drl | 17 +++ .../resources/io/trygvis/rules/machine/machine.drl | 1 + .../io/trygvis/rules/terraform/terraform.drl | 81 +++++++++++ .../java/io/trygvis/rules/network/Ipv4CidrTest.txt | 37 +++++ module/ri-engine/classpath.txt | 71 ++++++++-- module/ri-engine/pom.xml | 80 ++++++++++- .../main/java/io/trygvis/rules/core/Problem.java | 11 -- .../main/java/io/trygvis/rules/dba/Cluster.java | 13 -- .../main/java/io/trygvis/rules/dba/Container.java | 59 -------- .../main/java/io/trygvis/rules/dns/DnsEntry.java | 27 ---- .../rules/dns/DnsEntryTerraformExpression.java | 21 --- .../main/java/io/trygvis/rules/dns/DnsZone.java | 9 -- .../main/java/io/trygvis/rules/engine/DbIo.java | 45 ++++-- .../main/java/io/trygvis/rules/engine/Engine.java | 64 +++++++-- .../rules/engine/JinjavaTemplateEngine.java | 40 ++++++ .../java/io/trygvis/rules/engine/KeyValue.java | 14 -- .../main/java/io/trygvis/rules/engine/Main.java | 20 +++ .../io/trygvis/rules/engine/TemplateEngine.java | 34 +---- .../trygvis/rules/engine/cli/DatabaseCommand.java | 20 +++ .../io/trygvis/rules/engine/cli/RunCommand.java | 55 ++++++++ .../java/io/trygvis/rules/machine/Machine.java | 30 ---- .../rules/machine/MachineSpecification.java | 19 --- .../main/java/io/trygvis/rules/network/IpCalc.java | 6 - .../java/io/trygvis/rules/network/Ipv4Address.java | 57 -------- .../java/io/trygvis/rules/network/Ipv4Cidr.java | 152 --------------------- .../src/main/resources/META-INF/kmodule.xml | 11 -- .../main/resources/io/trygvis/rules/dba/dba.drl | 69 ---------- .../resources/io/trygvis/rules/engine/init.drl | 17 --- .../io/trygvis/rules/terraform/terraform.drl | 81 ----------- .../io/trygvis/rules/network/Ipv4CidrTest.java | 36 ----- module/ri-module-parent/classpath.txt | 23 ++++ module/ri-module-parent/pom.xml | 83 +++++++++++ module/ri-wireguard/classpath.txt | 28 +++- module/ri-wireguard/pom.xml | 14 +- module/ri-wireguard/src/main/resources/logback.xml | 13 ++ out/acme/wireguard.yaml | 17 +++ pom.xml | 20 ++- 81 files changed, 1892 insertions(+), 1113 deletions(-) create mode 100644 .run/CloudPlaningMain.run.xml create mode 100644 .settings.sh create mode 100644 module/acme-planner/classpath.txt create mode 100644 module/acme-planner/pom.xml create mode 100644 module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudBalance.java create mode 100644 module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudBalancingEasyScoreCalculator.java create mode 100644 module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudComputer.java create mode 100644 module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudPlaningMain.java create mode 100644 module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudPlanner.java create mode 100644 module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudProcess.java create mode 100644 module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudProcessDifficultyComparator.java create mode 100644 module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/ScalewayInstance.java create mode 100644 module/acme-planner/src/main/resources/io/trygvis/acme/planning/machine/solver-config.xml delete mode 100644 module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudBalance.java delete mode 100644 module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudBalancingEasyScoreCalculator.java delete mode 100644 module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudComputer.java delete mode 100644 module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudPlaningMain.java delete mode 100644 module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudPlanner.java delete mode 100644 module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudProcess.java delete mode 100644 module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudProcessDifficultyComparator.java delete mode 100644 module/acme/src/main/java/io/trygvis/acme/planning/machine/ScalewayInstance.java delete mode 100644 module/acme/src/main/resources/io/trygvis/acme/planning/machine/solver-config.xml create mode 100644 module/ri-base/classpath.txt create mode 100644 module/ri-base/pom.xml create mode 100644 module/ri-base/src/main/java/io/trygvis/rules/core/Problem.java create mode 100644 module/ri-base/src/main/java/io/trygvis/rules/dba/Cluster.java create mode 100644 module/ri-base/src/main/java/io/trygvis/rules/dba/Container.java create mode 100644 module/ri-base/src/main/java/io/trygvis/rules/dns/DnsEntry.java create mode 100644 module/ri-base/src/main/java/io/trygvis/rules/dns/DnsEntryTerraformExpression.java create mode 100644 module/ri-base/src/main/java/io/trygvis/rules/dns/DnsZone.java create mode 100644 module/ri-base/src/main/java/io/trygvis/rules/engine/KeyValue.java create mode 100644 module/ri-base/src/main/java/io/trygvis/rules/engine/TemplateEngine.java create mode 100644 module/ri-base/src/main/java/io/trygvis/rules/machine/Machine.java create mode 100644 module/ri-base/src/main/java/io/trygvis/rules/machine/MachineSpecification.java create mode 100644 module/ri-base/src/main/java/io/trygvis/rules/network/IpCalc.java create mode 100644 module/ri-base/src/main/java/io/trygvis/rules/network/Ipv4Address.java create mode 100644 module/ri-base/src/main/java/io/trygvis/rules/network/Ipv4Cidr.java create mode 100644 module/ri-base/src/main/java/io/trygvis/rules/terraform/TerraformResource.java create mode 100644 module/ri-base/src/main/resources/META-INF/kmodule.xml create mode 100644 module/ri-base/src/main/resources/io/trygvis/rules/dba/dba.drl create mode 100644 module/ri-base/src/main/resources/io/trygvis/rules/engine/init.drl create mode 100644 module/ri-base/src/main/resources/io/trygvis/rules/machine/machine.drl create mode 100644 module/ri-base/src/main/resources/io/trygvis/rules/terraform/terraform.drl create mode 100644 module/ri-base/src/test/java/io/trygvis/rules/network/Ipv4CidrTest.txt delete mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/core/Problem.java delete mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/dba/Cluster.java delete mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/dba/Container.java delete mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/dns/DnsEntry.java delete mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/dns/DnsEntryTerraformExpression.java delete mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/dns/DnsZone.java create mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/engine/JinjavaTemplateEngine.java delete mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/engine/KeyValue.java create mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/engine/Main.java create mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/DatabaseCommand.java create mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/RunCommand.java delete mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/machine/Machine.java delete mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/machine/MachineSpecification.java delete mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/network/IpCalc.java delete mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/network/Ipv4Address.java delete mode 100644 module/ri-engine/src/main/java/io/trygvis/rules/network/Ipv4Cidr.java delete mode 100644 module/ri-engine/src/main/resources/META-INF/kmodule.xml delete mode 100644 module/ri-engine/src/main/resources/io/trygvis/rules/dba/dba.drl delete mode 100644 module/ri-engine/src/main/resources/io/trygvis/rules/engine/init.drl delete mode 100644 module/ri-engine/src/main/resources/io/trygvis/rules/terraform/terraform.drl delete mode 100644 module/ri-engine/src/test/java/io/trygvis/rules/network/Ipv4CidrTest.java create mode 100644 module/ri-module-parent/classpath.txt create mode 100644 module/ri-module-parent/pom.xml create mode 100644 module/ri-wireguard/src/main/resources/logback.xml diff --git a/.run/CloudPlaningMain.run.xml b/.run/CloudPlaningMain.run.xml new file mode 100644 index 0000000..dfee516 --- /dev/null +++ b/.run/CloudPlaningMain.run.xml @@ -0,0 +1,15 @@ + + + + \ No newline at end of file diff --git a/.settings.sh b/.settings.sh new file mode 100644 index 0000000..6cdf786 --- /dev/null +++ b/.settings.sh @@ -0,0 +1,2 @@ +alias mvn="$(pwd)/mvnw" +alias engine="java --enable-preview -jar $(echo $(pwd)/module/ri-engine/target/*.jar)" diff --git a/module/acme-planner/classpath.txt b/module/acme-planner/classpath.txt new file mode 100644 index 0000000..3aadd88 --- /dev/null +++ b/module/acme-planner/classpath.txt @@ -0,0 +1,133 @@ +io.trygvis.rules-sandbox:acme-planner:1.0-SNAPSHOT:jar +aopalliance:aopalliance:1.0:jar +ch.obermuhlner:big-math:2.0.0:jar +ch.qos.logback:logback-classic:1.2.3:jar +ch.qos.logback:logback-core:1.2.3:jar +com.fasterxml.jackson.core:jackson-annotations:2.12.0:jar +com.fasterxml.jackson.core:jackson-core:2.12.0:jar +com.fasterxml.jackson.core:jackson-databind:2.12.0:jar +com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.12.0:jar +com.github.javaparser:javaparser-core:3.13.10:jar +com.github.virtuald:curvesapi:1.06:jar +com.google.code.findbugs:annotations:3.0.1:jar +com.google.errorprone:error_prone_annotations:2.1.3:jar +com.google.guava:guava:25.0-jre:jar +com.google.inject:guice:4.0:jar +com.google.j2objc:j2objc-annotations:1.1:jar +com.google.protobuf:protobuf-java:3.6.1:jar +com.google.re2j:re2j:1.2:jar +com.googlecode.java-ipv6:java-ipv6:0.17:jar +com.hubspot.jinjava:jinjava:2.5.6:jar +com.sun.activation:jakarta.activation:1.2.2:jar +com.sun.istack:istack-commons-runtime:3.0.8:jar +com.thoughtworks.xstream:xstream:1.4.14:jar +com.zaxxer:SparseBitSet:1.2:jar +commons-codec:commons-codec:1.14:jar +commons-io:commons-io:2.8.0:jar +commons-net:commons-net:3.3:jar +info.picocli:picocli:4.6.1:jar +io.trygvis.rules-sandbox:ri-engine:1.0-SNAPSHOT:jar +jakarta.activation:jakarta.activation-api:1.2.2:jar +jakarta.xml.bind:jakarta.xml.bind-api:2.3.3:jar +javax.annotation:jsr250-api:1.0:jar +javax.enterprise:cdi-api:1.0:jar +javax.inject:javax.inject:1:jar +org.antlr:antlr-runtime:3.5.2:jar +org.apache.ant:ant:1.9.15:jar +org.apache.ant:ant-launcher:1.9.15:jar +org.apache.commons:commons-collections4:4.4:jar +org.apache.commons:commons-compress:1.19:jar +org.apache.commons:commons-lang3:3.10:jar +org.apache.commons:commons-math3:3.4.1:jar +org.apache.httpcomponents:httpclient:4.5.12:jar +org.apache.httpcomponents:httpcore:4.4.13:jar +org.apache.maven:maven-aether-provider:3.3.9:jar +org.apache.maven:maven-artifact:3.3.9:jar +org.apache.maven:maven-builder-support:3.3.9:jar +org.apache.maven:maven-compat:3.3.9:jar +org.apache.maven:maven-core:3.3.9:jar +org.apache.maven:maven-model:3.3.9:jar +org.apache.maven:maven-model-builder:3.3.9:jar +org.apache.maven:maven-plugin-api:3.3.9:jar +org.apache.maven:maven-repository-metadata:3.3.9:jar +org.apache.maven:maven-settings:3.3.9:jar +org.apache.maven:maven-settings-builder:3.3.9:jar +org.apache.maven.wagon:wagon-http:3.0.0:jar +org.apache.maven.wagon:wagon-http-shared:3.0.0:jar +org.apache.maven.wagon:wagon-provider-api:3.0.0:jar +org.apache.poi:poi:4.1.2:jar +org.apache.poi:poi-ooxml:4.1.2:jar +org.apache.poi:poi-ooxml-schemas:4.1.2:jar +org.apache.xmlbeans:xmlbeans:3.1.0:jar +org.checkerframework:checker-compat-qual:2.0.0:jar +org.codehaus.mojo:animal-sniffer-annotations:1.14:jar +org.codehaus.plexus:plexus-classworlds:2.5.2:jar +org.codehaus.plexus:plexus-component-annotations:1.6:jar +org.codehaus.plexus:plexus-interpolation:1.21:jar +org.codehaus.plexus:plexus-utils:3.0.22:jar +org.drools:drools-canonical-model:7.48.0.Final:jar +org.drools:drools-compiler:7.48.0.Final:jar +org.drools:drools-core:7.48.0.Final:jar +org.drools:drools-core-dynamic:7.48.0.Final:jar +org.drools:drools-core-reflective:7.48.0.Final:jar +org.drools:drools-decisiontables:7.48.0.Final:jar +org.drools:drools-ecj:7.48.0.Final:jar +org.drools:drools-model-compiler:7.48.0.Final:jar +org.drools:drools-mvel:7.48.0.Final:jar +org.drools:drools-mvel-compiler:7.48.0.Final:jar +org.drools:drools-mvel-parser:7.48.0.Final:jar +org.drools:drools-serialization-protobuf:7.48.0.Final:jar +org.drools:drools-templates:7.48.0.Final:jar +org.eclipse.aether:aether-api:1.1.0:jar +org.eclipse.aether:aether-connector-basic:1.1.0:jar +org.eclipse.aether:aether-impl:1.1.0:jar +org.eclipse.aether:aether-spi:1.1.0:jar +org.eclipse.aether:aether-transport-file:1.1.0:jar +org.eclipse.aether:aether-transport-http:1.1.0:jar +org.eclipse.aether:aether-transport-wagon:1.1.0:jar +org.eclipse.aether:aether-util:1.1.0:jar +org.eclipse.sisu:org.eclipse.sisu.inject:0.3.2:jar +org.eclipse.sisu:org.eclipse.sisu.plexus:0.3.2:jar +org.glassfish.jaxb:jaxb-runtime:2.3.3:jar +org.glassfish.jaxb:txw2:2.3.3:jar +org.javassist:javassist:3.24.1-GA:jar +org.jsoup:jsoup:1.10.3:jar +org.kie:kie-api:7.48.0.Final:jar +org.kie:kie-ci:7.48.0.Final:jar +org.kie:kie-internal:7.48.0.Final:jar +org.kie:kie-memory-compiler:7.48.0.Final:jar +org.kie.kogito:drools-compiler:1.1.0.Final:jar +org.kie.kogito:drools-core:1.1.0.Final:jar +org.kie.kogito:drools-core-dynamic:1.1.0.Final:jar +org.kie.kogito:drools-core-static:1.1.0.Final:jar +org.kie.kogito:kogito-api:1.1.0.Final:jar +org.kie.kogito:kogito-drools-model:1.1.0.Final:jar +org.kie.kogito:kogito-internal:1.1.0.Final:jar +org.kie.kogito:kogito-services:1.1.0.Final:jar +org.kie.soup:kie-soup-commons:7.48.0.Final:jar +org.kie.soup:kie-soup-maven-integration:7.48.0.Final:jar +org.kie.soup:kie-soup-maven-support:7.48.0.Final:jar +org.kie.soup:kie-soup-project-datamodel-api:7.48.0.Final:jar +org.kie.soup:kie-soup-project-datamodel-commons:7.48.0.Final:jar +org.kie.soup:kie-soup-xstream:7.48.0.Final:jar +org.mvel:mvel2:2.4.11.Final:jar +org.optaplanner:optaplanner-core:8.1.0.Final:jar +org.optaplanner:optaplanner-persistence-common:8.1.0.Final:jar +org.optaplanner:optaplanner-persistence-jackson:8.1.0.Final:jar +org.optaplanner:optaplanner-spring-boot-autoconfigure:8.1.0.Final:jar +org.optaplanner:optaplanner-spring-boot-starter:8.1.0.Final:jar +org.slf4j:jcl-over-slf4j:1.7.30:jar +org.slf4j:slf4j-api:1.7.30:jar +org.sonatype.plexus:plexus-cipher:1.7:jar +org.sonatype.plexus:plexus-sec-dispatcher:1.3:jar +org.springframework:spring-aop:5.2.7.RELEASE:jar +org.springframework:spring-beans:5.2.7.RELEASE:jar +org.springframework:spring-context:5.2.7.RELEASE:jar +org.springframework:spring-core:5.2.7.RELEASE:jar +org.springframework:spring-expression:5.2.7.RELEASE:jar +org.springframework:spring-jcl:5.2.7.RELEASE:jar +org.springframework.boot:spring-boot:2.3.1.RELEASE:jar +org.springframework.boot:spring-boot-autoconfigure:2.3.1.RELEASE:jar +org.yaml:snakeyaml:1.26:jar +xmlpull:xmlpull:1.1.3.1:jar +xpp3:xpp3_min:1.1.4c:jar diff --git a/module/acme-planner/pom.xml b/module/acme-planner/pom.xml new file mode 100644 index 0000000..ed8699d --- /dev/null +++ b/module/acme-planner/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + + io.trygvis.rules-sandbox + rules-sandbox + 1.0-SNAPSHOT + ../../pom.xml + + + acme-planner + + + + org.optaplanner + optaplanner-spring-boot-starter + + + ${project.groupId} + ri-engine + ${project.version} + + + + + + + org.optaplanner + optaplanner-spring-boot-starter + 8.1.0.Final + + + + + diff --git a/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudBalance.java b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudBalance.java new file mode 100644 index 0000000..7311918 --- /dev/null +++ b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudBalance.java @@ -0,0 +1,48 @@ +package io.trygvis.acme.planning.machine; + +import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty; +import org.optaplanner.core.api.domain.solution.PlanningScore; +import org.optaplanner.core.api.domain.solution.PlanningSolution; +import org.optaplanner.core.api.domain.solution.ProblemFactCollectionProperty; +import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider; +import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore; + +import java.util.List; + +@PlanningSolution +public class CloudBalance { + + private List computerList; + + private List processList; + + private HardSoftScore score; + + public CloudBalance(List computerList, List processList) { + this.computerList = computerList; + this.processList = processList; + } + + public CloudBalance() { + } + + @ValueRangeProvider(id = "computerRange") + @ProblemFactCollectionProperty + public List getComputerList() { + return computerList; + } + + @PlanningEntityCollectionProperty + public List getProcessList() { + return processList; + } + + @PlanningScore + public HardSoftScore getScore() { + return score; + } + + public void setScore(HardSoftScore score) { + this.score = score; + } +} diff --git a/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudBalancingEasyScoreCalculator.java b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudBalancingEasyScoreCalculator.java new file mode 100644 index 0000000..6a14372 --- /dev/null +++ b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudBalancingEasyScoreCalculator.java @@ -0,0 +1,45 @@ +package io.trygvis.acme.planning.machine; + +import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore; +import org.optaplanner.core.api.score.calculator.EasyScoreCalculator; + +public class CloudBalancingEasyScoreCalculator implements EasyScoreCalculator { + + @Override + public HardSoftScore calculateScore(CloudBalance cloudBalance) { + int hardScore = 0; + int softScore = 0; + for (CloudComputer computer : cloudBalance.getComputerList()) { + int cpu = 0; + int memory = 0; + boolean used = false; + + // Calculate usage + for (CloudProcess process : cloudBalance.getProcessList()) { + if (computer.equals(process.computer)) { + cpu += process.requiredCpu; + memory += process.requiredMemory; + used = true; + } + } + + var instance = computer.instance; + + // Hard constraints + int cpuPowerAvailable = instance.cpu - cpu; + if (cpuPowerAvailable < 0) { + hardScore += cpuPowerAvailable; + } + int memoryAvailable = instance.memory - memory; + if (memoryAvailable < 0) { + hardScore += memoryAvailable; + } + + // Soft constraints + if (used) { + softScore -= instance.cost; + } + } + return HardSoftScore.of(hardScore, softScore); + } +} diff --git a/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudComputer.java b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudComputer.java new file mode 100644 index 0000000..aa2087d --- /dev/null +++ b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudComputer.java @@ -0,0 +1,16 @@ +package io.trygvis.acme.planning.machine; + +public class CloudComputer { + public final String host; + public final ScalewayInstance instance; + + public CloudComputer(String host, ScalewayInstance instance) { + this.host = host; + this.instance = instance; + } + + @Override + public String toString() { + return host; + } +} diff --git a/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudPlaningMain.java b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudPlaningMain.java new file mode 100644 index 0000000..60b3fd3 --- /dev/null +++ b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudPlaningMain.java @@ -0,0 +1,52 @@ +package io.trygvis.acme.planning.machine; + +import org.optaplanner.core.api.solver.SolverFactory; + +import java.util.ArrayList; + +public class CloudPlaningMain { + public static final ScalewayInstance Stardust1_s = new ScalewayInstance("Stardust1-s", 0.0025, 1000, 1000); + public static final ScalewayInstance DEV1_S = new ScalewayInstance("DEV1-S", 0.01, 2000, 2000); + public static final ScalewayInstance DEV1_M = new ScalewayInstance("DEV1-M", 0.02, 3000, 4000); + public static final ScalewayInstance DEV1_L = new ScalewayInstance("DEV1-L", 0.04, 4000, 8000); + public static final ScalewayInstance DEV1_XL = new ScalewayInstance("DEV1-XL", 0.06, 4000, 12000); + + public static void main(String[] args) { + var solverFactory = SolverFactory.createFromXmlResource("io/trygvis/acme/planning/machine/solver-config.xml"); + var solver = solverFactory.buildSolver(); + + var computers = new ArrayList(); + + computers.add(new CloudComputer("acme-1", DEV1_S)); + computers.add(new CloudComputer("acme-2", DEV1_M)); + computers.add(new CloudComputer("acme-3", DEV1_S)); + + var processes = new ArrayList(); + + processes.add(new CloudProcess("statera", 200, 1000)); + processes.add(new CloudProcess("statera-console", 100, 50)); + processes.add(new CloudProcess("4tune-web", 100, 50)); + processes.add(new CloudProcess("4tune-api", 200, 200)); + processes.add(new CloudProcess("pdb", 500, 500)); + processes.add(new CloudProcess("mdb", 500, 200)); + + var unsolvedCloudBalance = new CloudBalance(computers, processes); + + var solvedCloudBalance = solver.solve(unsolvedCloudBalance); + + System.out.println("solvedCloudBalance.getScore() = " + solvedCloudBalance.getScore()); + for (CloudProcess process : solvedCloudBalance.getProcessList()) { + System.out.println("process.id = " + process.id); + if (process.computer == null) { + System.out.println("COMPUTER IS NULL"); + } else { + System.out.println("process.computer.host = " + process.computer.host); + } + } + + System.out.println("------------------------------------------------------------------------"); + +// System.out.println("\nSolved cloudBalance with 400 computers and 1200 processes:\n" +// + toDisplayString(solvedCloudBalance)); + } +} diff --git a/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudPlanner.java b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudPlanner.java new file mode 100644 index 0000000..c629656 --- /dev/null +++ b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudPlanner.java @@ -0,0 +1,22 @@ +package io.trygvis.acme.planning.machine; + +import org.optaplanner.core.api.domain.entity.PlanningEntity; +import org.optaplanner.core.api.domain.variable.PlanningVariable; + +@PlanningEntity() +public class CloudPlanner { + private int requiredCpuPower; + private int requiredMemory; + private int requiredNetworkBandwidth; + + private CloudComputer computer; + + @PlanningVariable(valueRangeProviderRefs = {"computerRange"}) + public CloudComputer getComputer() { + return computer; + } + + public void setComputer(CloudComputer computer) { + this.computer = computer; + } +} diff --git a/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudProcess.java b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudProcess.java new file mode 100644 index 0000000..2002903 --- /dev/null +++ b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudProcess.java @@ -0,0 +1,48 @@ +package io.trygvis.acme.planning.machine; + +import org.apache.commons.lang3.builder.CompareToBuilder; +import org.optaplanner.core.api.domain.entity.PlanningEntity; +import org.optaplanner.core.api.domain.variable.PlanningVariable; + +import java.util.Comparator; + +@PlanningEntity(difficultyComparatorClass = CloudProcessDifficultyComparator.class) +public class CloudProcess { + public String id; + public int requiredCpu; + public int requiredMemory; + public int requiredMultiplicand; + + @PlanningVariable( + valueRangeProviderRefs = "computerRange", + strengthComparatorClass = CloudComputerStrengthComparator.class) + public CloudComputer computer; + + public CloudProcess(String id, int requiredCpu, int requiredMemory) { + this.id = id; + this.requiredCpu = requiredCpu; + this.requiredMemory = requiredMemory; + + this.requiredMultiplicand = requiredCpu * requiredMemory; + } + + @SuppressWarnings("unused") + public CloudProcess() { + } + + public String toString() { + return id; + } + + public static class CloudComputerStrengthComparator implements Comparator { + public int compare(CloudComputer a, CloudComputer b) { + var x = a.instance; + var y = b.instance; + return new CompareToBuilder() + .append(x.multiplicand, y.multiplicand) + .append(y.cost, x.cost) // Descending (but this is debatable) + .append(x.kind, y.kind) + .toComparison(); + } + } +} diff --git a/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudProcessDifficultyComparator.java b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudProcessDifficultyComparator.java new file mode 100644 index 0000000..658e826 --- /dev/null +++ b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/CloudProcessDifficultyComparator.java @@ -0,0 +1,15 @@ +package io.trygvis.acme.planning.machine; + +import org.apache.commons.lang3.builder.CompareToBuilder; + +import java.util.Comparator; + +public class CloudProcessDifficultyComparator implements Comparator { + + public int compare(CloudProcess a, CloudProcess b) { + return new CompareToBuilder() + .append(a.requiredMultiplicand, b.requiredMultiplicand) + .append(a.id, b.id) + .toComparison(); + } +} diff --git a/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/ScalewayInstance.java b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/ScalewayInstance.java new file mode 100644 index 0000000..dfdc0e0 --- /dev/null +++ b/module/acme-planner/src/main/java/io/trygvis/acme/planning/machine/ScalewayInstance.java @@ -0,0 +1,25 @@ +package io.trygvis.acme.planning.machine; + +public class ScalewayInstance { + public final String kind; + // Euros / hour + public final double cost; + public final int cpu; + public final int memory; + + public int multiplicand; + + public ScalewayInstance(String kind, double cost, int cpu, int memory) { + this.kind = kind; + this.cost = cost; + this.cpu = cpu; + this.memory = memory; + + this.multiplicand = cpu * memory; + } + + @Override + public String toString() { + return kind; + } +} diff --git a/module/acme-planner/src/main/resources/io/trygvis/acme/planning/machine/solver-config.xml b/module/acme-planner/src/main/resources/io/trygvis/acme/planning/machine/solver-config.xml new file mode 100644 index 0000000..81ae8ed --- /dev/null +++ b/module/acme-planner/src/main/resources/io/trygvis/acme/planning/machine/solver-config.xml @@ -0,0 +1,18 @@ + + + + io.trygvis.acme.planning.machine.CloudBalance + io.trygvis.acme.planning.machine.CloudProcess + + + + io.trygvis.acme.planning.machine.CloudBalancingEasyScoreCalculator + + + + + + 3 + + diff --git a/module/acme/classpath.txt b/module/acme/classpath.txt index ea09fc3..96576c4 100644 --- a/module/acme/classpath.txt +++ b/module/acme/classpath.txt @@ -1,78 +1,28 @@ -io.trygvis.rules-sandbox:acme:1.0-SNAPSHOT:jar -ch.obermuhlner:big-math:2.0.0:jar -ch.qos.logback:logback-classic:1.2.3:jar -ch.qos.logback:logback-core:1.2.3:jar +io.trygvis.rules-sandbox.module:acme:1.0-SNAPSHOT:jar com.fasterxml.jackson.core:jackson-annotations:2.12.0:jar com.fasterxml.jackson.core:jackson-core:2.12.0:jar com.fasterxml.jackson.core:jackson-databind:2.12.0:jar -com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.12.0:jar com.github.javaparser:javaparser-core:3.13.10:jar -com.google.code.findbugs:annotations:3.0.1:jar -com.google.errorprone:error_prone_annotations:2.1.3:jar -com.google.guava:guava:25.0-jre:jar -com.google.j2objc:j2objc-annotations:1.1:jar -com.google.re2j:re2j:1.2:jar -com.googlecode.java-ipv6:java-ipv6:0.17:jar -com.hubspot.jinjava:jinjava:2.5.6:jar -com.sun.activation:jakarta.activation:1.2.2:jar -com.sun.istack:istack-commons-runtime:3.0.8:jar com.thoughtworks.xstream:xstream:1.4.14:jar commons-codec:commons-codec:1.14:jar commons-io:commons-io:2.8.0:jar -commons-net:commons-net:3.3:jar -info.picocli:picocli:4.6.1:jar -io.trygvis.rules-sandbox:ri-engine:1.0-SNAPSHOT:jar -io.trygvis.rules-sandbox:ri-wireguard:1.0-SNAPSHOT:jar -jakarta.activation:jakarta.activation-api:1.2.2:jar -jakarta.xml.bind:jakarta.xml.bind-api:2.3.3:jar +io.trygvis.rules-sandbox.module:ri-base:1.0-SNAPSHOT:jar +io.trygvis.rules-sandbox.module:ri-wireguard:1.0-SNAPSHOT:jar org.antlr:antlr-runtime:3.5.2:jar -org.apache.commons:commons-lang3:3.10:jar -org.apache.commons:commons-math3:3.4.1:jar -org.checkerframework:checker-compat-qual:2.0.0:jar -org.codehaus.mojo:animal-sniffer-annotations:1.14:jar org.drools:drools-canonical-model:7.48.0.Final:jar org.drools:drools-compiler:7.48.0.Final:jar org.drools:drools-core:7.48.0.Final:jar +org.drools:drools-core-dynamic:7.48.0.Final:jar org.drools:drools-core-reflective:7.48.0.Final:jar org.drools:drools-ecj:7.48.0.Final:jar org.drools:drools-model-compiler:7.48.0.Final:jar -org.drools:drools-mvel:7.48.0.Final:jar org.drools:drools-mvel-compiler:7.48.0.Final:jar org.drools:drools-mvel-parser:7.48.0.Final:jar -org.glassfish.jaxb:jaxb-runtime:2.3.3:jar -org.glassfish.jaxb:txw2:2.3.3:jar -org.javassist:javassist:3.24.1-GA:jar -org.jsoup:jsoup:1.10.3:jar +org.kie:kie-api:7.48.0.Final:jar +org.kie:kie-internal:7.48.0.Final:jar org.kie:kie-memory-compiler:7.48.0.Final:jar -org.kie.kogito:drools-compiler:1.1.0.Final:jar -org.kie.kogito:drools-core:1.1.0.Final:jar -org.kie.kogito:drools-core-dynamic:1.1.0.Final:jar -org.kie.kogito:drools-core-static:1.1.0.Final:jar -org.kie.kogito:kogito-api:1.1.0.Final:jar -org.kie.kogito:kogito-drools-model:1.1.0.Final:jar -org.kie.kogito:kogito-internal:1.1.0.Final:jar -org.kie.kogito:kogito-services:1.1.0.Final:jar -org.kie.kogito:kogito-timer:1.1.0.Final:jar -org.kie.soup:kie-soup-commons:7.48.0.Final:jar org.kie.soup:kie-soup-maven-support:7.48.0.Final:jar -org.kie.soup:kie-soup-project-datamodel-api:7.48.0.Final:jar -org.kie.soup:kie-soup-project-datamodel-commons:7.48.0.Final:jar org.kie.soup:kie-soup-xstream:7.48.0.Final:jar -org.mvel:mvel2:2.4.11.Final:jar -org.optaplanner:optaplanner-core:8.1.0.Final:jar -org.optaplanner:optaplanner-persistence-common:8.1.0.Final:jar -org.optaplanner:optaplanner-persistence-jackson:8.1.0.Final:jar -org.optaplanner:optaplanner-spring-boot-autoconfigure:8.1.0.Final:jar -org.optaplanner:optaplanner-spring-boot-starter:8.1.0.Final:jar org.slf4j:slf4j-api:1.7.30:jar -org.springframework:spring-aop:5.2.7.RELEASE:jar -org.springframework:spring-beans:5.2.7.RELEASE:jar -org.springframework:spring-context:5.2.7.RELEASE:jar -org.springframework:spring-core:5.2.7.RELEASE:jar -org.springframework:spring-expression:5.2.7.RELEASE:jar -org.springframework:spring-jcl:5.2.7.RELEASE:jar -org.springframework.boot:spring-boot:2.3.1.RELEASE:jar -org.springframework.boot:spring-boot-autoconfigure:2.3.1.RELEASE:jar -org.yaml:snakeyaml:1.26:jar xmlpull:xmlpull:1.1.3.1:jar xpp3:xpp3_min:1.1.4c:jar diff --git a/module/acme/pom.xml b/module/acme/pom.xml index 396b1d2..3081602 100644 --- a/module/acme/pom.xml +++ b/module/acme/pom.xml @@ -5,34 +5,25 @@ 4.0.0 - io.trygvis.rules-sandbox - rules-sandbox + io.trygvis.rules-sandbox.module + ri-module-parent 1.0-SNAPSHOT - ../../pom.xml + ../ri-module-parent/pom.xml acme - org.optaplanner - optaplanner-spring-boot-starter + ${project.groupId} + ri-base + ${project.version} ${project.groupId} - ri-engine + ri-wireguard ${project.version} - - - - org.optaplanner - optaplanner-spring-boot-starter - 8.1.0.Final - - - - diff --git a/module/acme/src/main/java/io/trygvis/acme/AcmeAppsMain.java b/module/acme/src/main/java/io/trygvis/acme/AcmeAppsMain.java index caab325..c65a3b2 100644 --- a/module/acme/src/main/java/io/trygvis/acme/AcmeAppsMain.java +++ b/module/acme/src/main/java/io/trygvis/acme/AcmeAppsMain.java @@ -1,18 +1,14 @@ package io.trygvis.acme; -import io.trygvis.rules.engine.Engine; - -import java.io.File; -import java.io.IOException; - public class AcmeAppsMain { - public static void main(String[] args) throws IOException { - try (var engine = new Engine( - "acme-apps", - "acme.yaml", - new File("acme-apps"), - new String[]{"init", "generate"})) { - engine.io.dump("acme/apps", engine.session.getFactHandles()); - } - } +// 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/module/acme/src/main/java/io/trygvis/acme/VpnMain.java b/module/acme/src/main/java/io/trygvis/acme/VpnMain.java index 1859e2a..cbf962c 100644 --- a/module/acme/src/main/java/io/trygvis/acme/VpnMain.java +++ b/module/acme/src/main/java/io/trygvis/acme/VpnMain.java @@ -1,28 +1,21 @@ package io.trygvis.acme; -import io.trygvis.rules.dns.DnsEntry; -import io.trygvis.rules.engine.Engine; -import io.trygvis.rules.machine.Machine; -import io.trygvis.rules.network.Ipv4Address; -import io.trygvis.rules.network.Ipv4Cidr; - -import java.io.File; -import java.io.IOException; - public class VpnMain { - public static void main(String[] args) throws IOException { - try (var engine = new Engine( - "acme-wireguard", - "acme.yaml", - new File("acme-wireguard"), - new String[]{"init", "generate"})) { - engine.io.dump("acme/wireguard", engine.session.getFactHandles(), (Object o) -> - o.getClass().getName().contains("Wg") - || o instanceof Machine - || o instanceof DnsEntry - || o instanceof Ipv4Cidr - || o instanceof Ipv4Address - ); - } - } +// 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/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudBalance.java b/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudBalance.java deleted file mode 100644 index 7311918..0000000 --- a/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudBalance.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.trygvis.acme.planning.machine; - -import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty; -import org.optaplanner.core.api.domain.solution.PlanningScore; -import org.optaplanner.core.api.domain.solution.PlanningSolution; -import org.optaplanner.core.api.domain.solution.ProblemFactCollectionProperty; -import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider; -import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore; - -import java.util.List; - -@PlanningSolution -public class CloudBalance { - - private List computerList; - - private List processList; - - private HardSoftScore score; - - public CloudBalance(List computerList, List processList) { - this.computerList = computerList; - this.processList = processList; - } - - public CloudBalance() { - } - - @ValueRangeProvider(id = "computerRange") - @ProblemFactCollectionProperty - public List getComputerList() { - return computerList; - } - - @PlanningEntityCollectionProperty - public List getProcessList() { - return processList; - } - - @PlanningScore - public HardSoftScore getScore() { - return score; - } - - public void setScore(HardSoftScore score) { - this.score = score; - } -} diff --git a/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudBalancingEasyScoreCalculator.java b/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudBalancingEasyScoreCalculator.java deleted file mode 100644 index 6a14372..0000000 --- a/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudBalancingEasyScoreCalculator.java +++ /dev/null @@ -1,45 +0,0 @@ -package io.trygvis.acme.planning.machine; - -import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore; -import org.optaplanner.core.api.score.calculator.EasyScoreCalculator; - -public class CloudBalancingEasyScoreCalculator implements EasyScoreCalculator { - - @Override - public HardSoftScore calculateScore(CloudBalance cloudBalance) { - int hardScore = 0; - int softScore = 0; - for (CloudComputer computer : cloudBalance.getComputerList()) { - int cpu = 0; - int memory = 0; - boolean used = false; - - // Calculate usage - for (CloudProcess process : cloudBalance.getProcessList()) { - if (computer.equals(process.computer)) { - cpu += process.requiredCpu; - memory += process.requiredMemory; - used = true; - } - } - - var instance = computer.instance; - - // Hard constraints - int cpuPowerAvailable = instance.cpu - cpu; - if (cpuPowerAvailable < 0) { - hardScore += cpuPowerAvailable; - } - int memoryAvailable = instance.memory - memory; - if (memoryAvailable < 0) { - hardScore += memoryAvailable; - } - - // Soft constraints - if (used) { - softScore -= instance.cost; - } - } - return HardSoftScore.of(hardScore, softScore); - } -} diff --git a/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudComputer.java b/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudComputer.java deleted file mode 100644 index aa2087d..0000000 --- a/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudComputer.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.trygvis.acme.planning.machine; - -public class CloudComputer { - public final String host; - public final ScalewayInstance instance; - - public CloudComputer(String host, ScalewayInstance instance) { - this.host = host; - this.instance = instance; - } - - @Override - public String toString() { - return host; - } -} diff --git a/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudPlaningMain.java b/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudPlaningMain.java deleted file mode 100644 index 60b3fd3..0000000 --- a/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudPlaningMain.java +++ /dev/null @@ -1,52 +0,0 @@ -package io.trygvis.acme.planning.machine; - -import org.optaplanner.core.api.solver.SolverFactory; - -import java.util.ArrayList; - -public class CloudPlaningMain { - public static final ScalewayInstance Stardust1_s = new ScalewayInstance("Stardust1-s", 0.0025, 1000, 1000); - public static final ScalewayInstance DEV1_S = new ScalewayInstance("DEV1-S", 0.01, 2000, 2000); - public static final ScalewayInstance DEV1_M = new ScalewayInstance("DEV1-M", 0.02, 3000, 4000); - public static final ScalewayInstance DEV1_L = new ScalewayInstance("DEV1-L", 0.04, 4000, 8000); - public static final ScalewayInstance DEV1_XL = new ScalewayInstance("DEV1-XL", 0.06, 4000, 12000); - - public static void main(String[] args) { - var solverFactory = SolverFactory.createFromXmlResource("io/trygvis/acme/planning/machine/solver-config.xml"); - var solver = solverFactory.buildSolver(); - - var computers = new ArrayList(); - - computers.add(new CloudComputer("acme-1", DEV1_S)); - computers.add(new CloudComputer("acme-2", DEV1_M)); - computers.add(new CloudComputer("acme-3", DEV1_S)); - - var processes = new ArrayList(); - - processes.add(new CloudProcess("statera", 200, 1000)); - processes.add(new CloudProcess("statera-console", 100, 50)); - processes.add(new CloudProcess("4tune-web", 100, 50)); - processes.add(new CloudProcess("4tune-api", 200, 200)); - processes.add(new CloudProcess("pdb", 500, 500)); - processes.add(new CloudProcess("mdb", 500, 200)); - - var unsolvedCloudBalance = new CloudBalance(computers, processes); - - var solvedCloudBalance = solver.solve(unsolvedCloudBalance); - - System.out.println("solvedCloudBalance.getScore() = " + solvedCloudBalance.getScore()); - for (CloudProcess process : solvedCloudBalance.getProcessList()) { - System.out.println("process.id = " + process.id); - if (process.computer == null) { - System.out.println("COMPUTER IS NULL"); - } else { - System.out.println("process.computer.host = " + process.computer.host); - } - } - - System.out.println("------------------------------------------------------------------------"); - -// System.out.println("\nSolved cloudBalance with 400 computers and 1200 processes:\n" -// + toDisplayString(solvedCloudBalance)); - } -} diff --git a/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudPlanner.java b/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudPlanner.java deleted file mode 100644 index c629656..0000000 --- a/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudPlanner.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.trygvis.acme.planning.machine; - -import org.optaplanner.core.api.domain.entity.PlanningEntity; -import org.optaplanner.core.api.domain.variable.PlanningVariable; - -@PlanningEntity() -public class CloudPlanner { - private int requiredCpuPower; - private int requiredMemory; - private int requiredNetworkBandwidth; - - private CloudComputer computer; - - @PlanningVariable(valueRangeProviderRefs = {"computerRange"}) - public CloudComputer getComputer() { - return computer; - } - - public void setComputer(CloudComputer computer) { - this.computer = computer; - } -} diff --git a/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudProcess.java b/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudProcess.java deleted file mode 100644 index 2002903..0000000 --- a/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudProcess.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.trygvis.acme.planning.machine; - -import org.apache.commons.lang3.builder.CompareToBuilder; -import org.optaplanner.core.api.domain.entity.PlanningEntity; -import org.optaplanner.core.api.domain.variable.PlanningVariable; - -import java.util.Comparator; - -@PlanningEntity(difficultyComparatorClass = CloudProcessDifficultyComparator.class) -public class CloudProcess { - public String id; - public int requiredCpu; - public int requiredMemory; - public int requiredMultiplicand; - - @PlanningVariable( - valueRangeProviderRefs = "computerRange", - strengthComparatorClass = CloudComputerStrengthComparator.class) - public CloudComputer computer; - - public CloudProcess(String id, int requiredCpu, int requiredMemory) { - this.id = id; - this.requiredCpu = requiredCpu; - this.requiredMemory = requiredMemory; - - this.requiredMultiplicand = requiredCpu * requiredMemory; - } - - @SuppressWarnings("unused") - public CloudProcess() { - } - - public String toString() { - return id; - } - - public static class CloudComputerStrengthComparator implements Comparator { - public int compare(CloudComputer a, CloudComputer b) { - var x = a.instance; - var y = b.instance; - return new CompareToBuilder() - .append(x.multiplicand, y.multiplicand) - .append(y.cost, x.cost) // Descending (but this is debatable) - .append(x.kind, y.kind) - .toComparison(); - } - } -} diff --git a/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudProcessDifficultyComparator.java b/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudProcessDifficultyComparator.java deleted file mode 100644 index 658e826..0000000 --- a/module/acme/src/main/java/io/trygvis/acme/planning/machine/CloudProcessDifficultyComparator.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.trygvis.acme.planning.machine; - -import org.apache.commons.lang3.builder.CompareToBuilder; - -import java.util.Comparator; - -public class CloudProcessDifficultyComparator implements Comparator { - - public int compare(CloudProcess a, CloudProcess b) { - return new CompareToBuilder() - .append(a.requiredMultiplicand, b.requiredMultiplicand) - .append(a.id, b.id) - .toComparison(); - } -} diff --git a/module/acme/src/main/java/io/trygvis/acme/planning/machine/ScalewayInstance.java b/module/acme/src/main/java/io/trygvis/acme/planning/machine/ScalewayInstance.java deleted file mode 100644 index dfdc0e0..0000000 --- a/module/acme/src/main/java/io/trygvis/acme/planning/machine/ScalewayInstance.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.trygvis.acme.planning.machine; - -public class ScalewayInstance { - public final String kind; - // Euros / hour - public final double cost; - public final int cpu; - public final int memory; - - public int multiplicand; - - public ScalewayInstance(String kind, double cost, int cpu, int memory) { - this.kind = kind; - this.cost = cost; - this.cpu = cpu; - this.memory = memory; - - this.multiplicand = cpu * memory; - } - - @Override - public String toString() { - return kind; - } -} diff --git a/module/acme/src/main/resources/io/trygvis/acme/planning/machine/solver-config.xml b/module/acme/src/main/resources/io/trygvis/acme/planning/machine/solver-config.xml deleted file mode 100644 index 81ae8ed..0000000 --- a/module/acme/src/main/resources/io/trygvis/acme/planning/machine/solver-config.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - io.trygvis.acme.planning.machine.CloudBalance - io.trygvis.acme.planning.machine.CloudProcess - - - - io.trygvis.acme.planning.machine.CloudBalancingEasyScoreCalculator - - - - - - 3 - - diff --git a/module/ri-base/classpath.txt b/module/ri-base/classpath.txt new file mode 100644 index 0000000..1461d46 --- /dev/null +++ b/module/ri-base/classpath.txt @@ -0,0 +1,26 @@ +io.trygvis.rules-sandbox.module:ri-base:1.0-SNAPSHOT:kjar +com.fasterxml.jackson.core:jackson-annotations:2.12.0:jar +com.fasterxml.jackson.core:jackson-core:2.12.0:jar +com.fasterxml.jackson.core:jackson-databind:2.12.0:jar +com.github.javaparser:javaparser-core:3.13.10:jar +com.thoughtworks.xstream:xstream:1.4.14:jar +commons-codec:commons-codec:1.14:jar +commons-io:commons-io:2.8.0:jar +org.antlr:antlr-runtime:3.5.2:jar +org.drools:drools-canonical-model:7.48.0.Final:jar +org.drools:drools-compiler:7.48.0.Final:jar +org.drools:drools-core:7.48.0.Final:jar +org.drools:drools-core-dynamic:7.48.0.Final:jar +org.drools:drools-core-reflective:7.48.0.Final:jar +org.drools:drools-ecj:7.48.0.Final:jar +org.drools:drools-model-compiler:7.48.0.Final:jar +org.drools:drools-mvel-compiler:7.48.0.Final:jar +org.drools:drools-mvel-parser:7.48.0.Final:jar +org.kie:kie-api:7.48.0.Final:jar +org.kie:kie-internal:7.48.0.Final:jar +org.kie:kie-memory-compiler:7.48.0.Final:jar +org.kie.soup:kie-soup-maven-support:7.48.0.Final:jar +org.kie.soup:kie-soup-xstream:7.48.0.Final:jar +org.slf4j:slf4j-api:1.7.30:jar +xmlpull:xmlpull:1.1.3.1:jar +xpp3:xpp3_min:1.1.4c:jar diff --git a/module/ri-base/pom.xml b/module/ri-base/pom.xml new file mode 100644 index 0000000..43703f7 --- /dev/null +++ b/module/ri-base/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + + + io.trygvis.rules-sandbox.module + ri-module-parent + 1.0-SNAPSHOT + ../ri-module-parent/pom.xml + + + ri-base + kjar + + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-databind + + + + org.junit.jupiter + junit-jupiter-api + 5.7.0 + test + + + org.junit.jupiter + junit-jupiter-params + 5.7.0 + test + + + org.junit.platform + junit-platform-commons + 1.7.0 + test + + + + + + + org.kie + kie-maven-plugin + ${version.drools} + true + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + false + + + + + + diff --git a/module/ri-base/src/main/java/io/trygvis/rules/core/Problem.java b/module/ri-base/src/main/java/io/trygvis/rules/core/Problem.java new file mode 100644 index 0000000..04d1af3 --- /dev/null +++ b/module/ri-base/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-base/src/main/java/io/trygvis/rules/dba/Cluster.java b/module/ri-base/src/main/java/io/trygvis/rules/dba/Cluster.java new file mode 100644 index 0000000..0b65aaa --- /dev/null +++ b/module/ri-base/src/main/java/io/trygvis/rules/dba/Cluster.java @@ -0,0 +1,13 @@ +package io.trygvis.rules.dba; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; + +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") +public class Cluster { + public String name; + + public Cluster(String name) { + this.name = name; + } +} diff --git a/module/ri-base/src/main/java/io/trygvis/rules/dba/Container.java b/module/ri-base/src/main/java/io/trygvis/rules/dba/Container.java new file mode 100644 index 0000000..3888661 --- /dev/null +++ b/module/ri-base/src/main/java/io/trygvis/rules/dba/Container.java @@ -0,0 +1,59 @@ +package io.trygvis.rules.dba; + +import com.fasterxml.jackson.annotation.JsonIdentityReference; +import io.trygvis.rules.machine.Machine; +import io.trygvis.rules.machine.MachineSpecification; + +//@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") +public class Container { + public final String id; + +// @JsonIdentityReference(alwaysAsId = true) + public final Cluster cluster; + public final String name; + public final String machineRole; + public final String image; + public final String tag; + + private Machine machine; + public final MachineSpecification machineSpecification; + + public Container(Cluster cluster, String name, String machineRole, String image, String tag, + MachineSpecification machineSpecification) { + this.id = cluster.name + "-" + name; + this.cluster = cluster; + this.name = name; + this.machineRole = machineRole; + this.image = image; + this.tag = tag; + this.machineSpecification = machineSpecification; + } + + 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-base/src/main/java/io/trygvis/rules/dns/DnsEntry.java b/module/ri-base/src/main/java/io/trygvis/rules/dns/DnsEntry.java new file mode 100644 index 0000000..105ef79 --- /dev/null +++ b/module/ri-base/src/main/java/io/trygvis/rules/dns/DnsEntry.java @@ -0,0 +1,27 @@ +package io.trygvis.rules.dns; + +public class DnsEntry { + public String fqdn; + public String type; + + public DnsEntry(String fqdn, String type) { + this.fqdn = fqdn; + this.type = type; + } + + public static DnsEntry a(String fqdn) { + return new DnsEntry(fqdn, "A"); + } + + public static DnsEntry aaaa(String fqdn) { + return new DnsEntry(fqdn, "AAAA"); + } + + public String getFqdn() { + return fqdn; + } + + public String getType() { + return type; + } +} diff --git a/module/ri-base/src/main/java/io/trygvis/rules/dns/DnsEntryTerraformExpression.java b/module/ri-base/src/main/java/io/trygvis/rules/dns/DnsEntryTerraformExpression.java new file mode 100644 index 0000000..79bf934 --- /dev/null +++ b/module/ri-base/src/main/java/io/trygvis/rules/dns/DnsEntryTerraformExpression.java @@ -0,0 +1,21 @@ +package io.trygvis.rules.dns; + +public class DnsEntryTerraformExpression { + public DnsEntry entry; + public String key; + public String expression; + + public DnsEntryTerraformExpression(DnsEntry entry, String key, String expression) { + this.entry = entry; + this.key = key; + this.expression = expression; + } + + public String getKey() { + return key; + } + + public String getExpression() { + return expression; + } +} diff --git a/module/ri-base/src/main/java/io/trygvis/rules/dns/DnsZone.java b/module/ri-base/src/main/java/io/trygvis/rules/dns/DnsZone.java new file mode 100644 index 0000000..1af5c8f --- /dev/null +++ b/module/ri-base/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-base/src/main/java/io/trygvis/rules/engine/KeyValue.java b/module/ri-base/src/main/java/io/trygvis/rules/engine/KeyValue.java new file mode 100644 index 0000000..5046169 --- /dev/null +++ b/module/ri-base/src/main/java/io/trygvis/rules/engine/KeyValue.java @@ -0,0 +1,14 @@ +package io.trygvis.rules.engine; + +public class KeyValue { + public String key; + public String value; + + public KeyValue() { + } + + public KeyValue(String key, String value) { + this.key = key; + this.value = value; + } +} diff --git a/module/ri-base/src/main/java/io/trygvis/rules/engine/TemplateEngine.java b/module/ri-base/src/main/java/io/trygvis/rules/engine/TemplateEngine.java new file mode 100644 index 0000000..eafa6e4 --- /dev/null +++ b/module/ri-base/src/main/java/io/trygvis/rules/engine/TemplateEngine.java @@ -0,0 +1,10 @@ +package io.trygvis.rules.engine; + +import java.io.IOException; +import java.util.Map; + +public interface TemplateEngine { + void clean(); + + void template(String name, String output, Map params) throws IOException; +} diff --git a/module/ri-base/src/main/java/io/trygvis/rules/machine/Machine.java b/module/ri-base/src/main/java/io/trygvis/rules/machine/Machine.java new file mode 100644 index 0000000..8f162c6 --- /dev/null +++ b/module/ri-base/src/main/java/io/trygvis/rules/machine/Machine.java @@ -0,0 +1,29 @@ +package io.trygvis.rules.machine; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; + +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") +public class Machine { + public String name; + private String fqdn; + + public Machine() { + } + + public Machine(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public String getFqdn() { + return fqdn; + } + + public void setFqdn(String fqdn) { + this.fqdn = fqdn; + } +} 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 new file mode 100644 index 0000000..2e17ae5 --- /dev/null +++ b/module/ri-base/src/main/java/io/trygvis/rules/machine/MachineSpecification.java @@ -0,0 +1,19 @@ +package io.trygvis.rules.machine; + +public class MachineSpecification { + public final int cpu; + public final int memory; + + public MachineSpecification(int cpu, int memory) { + this.cpu = cpu; + this.memory = memory; + } + + public int getCpu() { + return cpu; + } + + public int getMemory() { + return memory; + } +} diff --git a/module/ri-base/src/main/java/io/trygvis/rules/network/IpCalc.java b/module/ri-base/src/main/java/io/trygvis/rules/network/IpCalc.java new file mode 100644 index 0000000..7ec344c --- /dev/null +++ b/module/ri-base/src/main/java/io/trygvis/rules/network/IpCalc.java @@ -0,0 +1,6 @@ +package io.trygvis.rules.network; + +import java.util.regex.Pattern; + +public class IpCalc { +} diff --git a/module/ri-base/src/main/java/io/trygvis/rules/network/Ipv4Address.java b/module/ri-base/src/main/java/io/trygvis/rules/network/Ipv4Address.java new file mode 100644 index 0000000..9021198 --- /dev/null +++ b/module/ri-base/src/main/java/io/trygvis/rules/network/Ipv4Address.java @@ -0,0 +1,58 @@ +package io.trygvis.rules.network; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.io.IOException; +import java.util.Objects; + +@JsonSerialize(using = Ipv4Address.Serializer.class) +public class Ipv4Address implements Comparable { + public final int address; + + public Ipv4Address(int address) { + this.address = address; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o instanceof Ipv4Address) { + Ipv4Address other = (Ipv4Address) o; + return address == other.address; + } + + return false; + } + + @Override + public int hashCode() { + return Objects.hash(address); + } + + @Override + public int compareTo(Ipv4Address o) { + return address - o.address; + } + + @Override + public String toString() { + return "%d.%d.%d.%d".formatted( + address >> 24 & 0xff, + address >> 16 & 0xff, + address >> 8 & 0xff, + address & 0xff); + } + + public static class Serializer extends JsonSerializer { + @Override + public void serialize(Ipv4Address value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartObject(); + gen.writeObjectField("value", value.toString()); + gen.writeEndObject(); + } + } +} diff --git a/module/ri-base/src/main/java/io/trygvis/rules/network/Ipv4Cidr.java b/module/ri-base/src/main/java/io/trygvis/rules/network/Ipv4Cidr.java new file mode 100644 index 0000000..851af95 --- /dev/null +++ b/module/ri-base/src/main/java/io/trygvis/rules/network/Ipv4Cidr.java @@ -0,0 +1,150 @@ +package io.trygvis.rules.network; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.regex.Pattern; + +@JsonSerialize(using = Ipv4Cidr.Serializer.class) +public class Ipv4Cidr implements Comparable { + public final int network; + public final int bits; + + public Ipv4Cidr(int network, int bits) { + if (bits < 0 || bits > 32) { + throw new IllegalArgumentException("bits must be [0, 32]"); + } + + int hostBits = 32 - bits; + int netmask = (-1 >> hostBits) << hostBits; + + int x = network & ~netmask; + + if (x != 0) { + throw new IllegalArgumentException("The host part of the address must be 0."); + } + + this.network = network; + this.bits = bits; + } + + @Override + public String toString() { + return "%d.%d.%d.%d/%d".formatted( + network >> 24 & 0xff, + network >> 16 & 0xff, + network >> 8 & 0xff, + network & 0xff, + bits); + } + + private String formatIpv4(int address) { + return "%d.%d.%d.%d".formatted(address >> 24 & 0xff, address >> 16 & 0xff, address >> 8 & 0xff, address & 0xff); + } + + public List partition(int bits) { + if (bits <= 0 || bits <= this.bits || bits > 32) { + throw new IllegalArgumentException("Invalid new network size"); + } + + var list = new ArrayList(); + + int count = 1 << (bits - this.bits); + for (int i = 0; i < count; i++) { + var network = this.network | (i << (32 - bits)); + + list.add(new Ipv4Cidr(network, bits)); + } + + return list; + } + + public List addresses() { + int size = 1 << 32 - bits; + var end = network + size; + var addresses = new ArrayList(size); + for (int address = network; address < end; address++) { + addresses.add(new Ipv4Address(address)); + } + + return addresses; + } + + @Override + public int compareTo(Ipv4Cidr o) { + if (this == o) { + return 0; + } + + var ret = network - o.network; + if (ret != 0) { + return ret; + } + + return bits - o.bits; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Ipv4Cidr ipv4Cidr = (Ipv4Cidr) o; + return network == ipv4Cidr.network && bits == ipv4Cidr.bits; + } + + @Override + public int hashCode() { + return Objects.hash(network, bits); + } + + private static final Pattern pattern = Pattern.compile("([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})/([0-9]{1,3})"); + + public static Ipv4Cidr parseCidr(String cidr) { + var matcher = pattern.matcher(cidr); + if (!matcher.matches()) { + throw new IllegalArgumentException("Not a CIDR: " + cidr); + } + + var b1 = matcher.group(1); + var b2 = matcher.group(2); + var b3 = matcher.group(3); + var b4 = matcher.group(4); + + int network = parse(b1) << 24 | + parse(b2) << 16 | + parse(b3) << 8 | + parse(b4); + +// System.out.printf("network = %x%n", network); + + var l = matcher.group(5); + var bits = Integer.parseInt(l); +// System.out.printf("netmask = %08x%n", netmask); + + return new Ipv4Cidr(network, bits); + } + + private static int parse(String s) { + var i = Integer.parseInt(s); + if (i > 255) { + throw new IllegalArgumentException("Not a CIDR"); + } + + return i; + } + + public static class Serializer extends JsonSerializer { + @Override + public void serialize(Ipv4Cidr value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartObject(); + gen.writeObjectField("value", value.toString()); + gen.writeEndObject(); + } + } +} 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 new file mode 100644 index 0000000..41bd6ae --- /dev/null +++ b/module/ri-base/src/main/java/io/trygvis/rules/terraform/TerraformResource.java @@ -0,0 +1,96 @@ +package io.trygvis.rules.terraform; + +import java.util.HashMap; +import java.util.Map; + +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 values = new HashMap<>(); + + public TerraformResource(String output, String kind, String instance) { + this.output = output; + this.kind = kind; + this.instance = instance; + } + + public String getOutput() { + return output; + } + + public void putString(String key, String value) { + values.put(key, new StringTerraformValue(value)); + } + + public String asString() { + var buf = new StringBuilder(); + + buf.append(quote(kind)); + buf.append(" "); + buf.append(quote(instance)); + buf.append(" {"); + buf.append(EOL); + + for (var entry : values.entrySet()) { + buf.append(" "); + buf.append(entry.getKey()); + buf.append(" = "); + buf.append(entry.getValue().asString()); + buf.append(EOL); + } + + buf.append("}"); + buf.append(EOL); + + return buf.toString(); + } + + public interface TerraformValue { + String asString(); + } + + public static class StringTerraformValue implements TerraformValue { + private final String value; + + public StringTerraformValue(String value) { + this.value = value; + } + + @Override + public String asString() { + return quote(value); + } + } + + public static class BooleanTerraformValue implements TerraformValue { + private final boolean value; + + public BooleanTerraformValue(boolean value) { + this.value = value; + } + + @Override + public String asString() { + return String.valueOf(value); + } + } + + public static class ExpressionTerraformValue implements TerraformValue { + private final String value; + + public ExpressionTerraformValue(String value) { + this.value = value; + } + + @Override + public String asString() { + return value; + } + } + + 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 new file mode 100644 index 0000000..79c5e79 --- /dev/null +++ b/module/ri-base/src/main/resources/META-INF/kmodule.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/module/ri-base/src/main/resources/io/trygvis/rules/dba/dba.drl b/module/ri-base/src/main/resources/io/trygvis/rules/dba/dba.drl new file mode 100644 index 0000000..c31bc57 --- /dev/null +++ b/module/ri-base/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 machine" +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; + + List 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); + + String path = "ansible/dba/" + $cluster.name + ".yml"; + te.template("dba/cluster", path, Map.of( + "cluster", $cluster, + "containers", $containers, + "containersByMachine", containersByMachine + )); +end diff --git a/module/ri-base/src/main/resources/io/trygvis/rules/engine/init.drl b/module/ri-base/src/main/resources/io/trygvis/rules/engine/init.drl new file mode 100644 index 0000000..267cc4a --- /dev/null +++ b/module/ri-base/src/main/resources/io/trygvis/rules/engine/init.drl @@ -0,0 +1,17 @@ +package io.trygvis.rules.engine; + +import java.util.Map +import org.apache.commons.io.FileSystem +import org.apache.commons.io.FileUtils +import java.io.File + +global io.trygvis.rules.engine.TemplateEngine te; + +rule "Clean directories" + agenda-group "init" +when + not(KeyValue(key == "rm-gen")); +then + te.clean(); + insert(new KeyValue("rm-gen", null)); +end diff --git a/module/ri-base/src/main/resources/io/trygvis/rules/machine/machine.drl b/module/ri-base/src/main/resources/io/trygvis/rules/machine/machine.drl new file mode 100644 index 0000000..0250cc6 --- /dev/null +++ b/module/ri-base/src/main/resources/io/trygvis/rules/machine/machine.drl @@ -0,0 +1 @@ +package io.trygvis.rules.machine; 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 new file mode 100644 index 0000000..5ebd082 --- /dev/null +++ b/module/ri-base/src/main/resources/io/trygvis/rules/terraform/terraform.drl @@ -0,0 +1,81 @@ +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/test/java/io/trygvis/rules/network/Ipv4CidrTest.txt b/module/ri-base/src/test/java/io/trygvis/rules/network/Ipv4CidrTest.txt new file mode 100644 index 0000000..826f586 --- /dev/null +++ b/module/ri-base/src/test/java/io/trygvis/rules/network/Ipv4CidrTest.txt @@ -0,0 +1,37 @@ +package io.trygvis.rules.network; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static io.trygvis.rules.network.Ipv4Cidr.parseCidr; +import static org.junit.jupiter.api.Assertions.*; + +class Ipv4CidrTest { + + @Test + public void basic() { + Assertions.assertThrows(IllegalArgumentException.class, () -> parseCidr("192.168.1.1/24").addresses()); + assertEquals(256, parseCidr("192.168.1.0/24").addresses().size()); + assertEquals(128, parseCidr("192.168.1.128/25").addresses().size()); + } + + @ParameterizedTest + @ValueSource(strings = { + "192.168.1.0/24", + "192.168.1.128/25", + }) + public void testParsing(String s) { + assertEquals(s, parseCidr(s).toString()); + } + + @Test + public void partition() { + var children = parseCidr("192.168.1.0/24").partition(26); + assertEquals(1 << 2, children.size()); + for (var cidr : children) { + assertEquals(26, cidr.bits); + } + } +} diff --git a/module/ri-engine/classpath.txt b/module/ri-engine/classpath.txt index 7d0804a..580eec1 100644 --- a/module/ri-engine/classpath.txt +++ b/module/ri-engine/classpath.txt @@ -1,4 +1,5 @@ io.trygvis.rules-sandbox:ri-engine:1.0-SNAPSHOT:jar +aopalliance:aopalliance:1.0:jar ch.obermuhlner:big-math:2.0.0:jar ch.qos.logback:logback-classic:1.2.3:jar ch.qos.logback:logback-core:1.2.3:jar @@ -6,50 +7,94 @@ com.fasterxml.jackson.core:jackson-annotations:2.12.0:jar com.fasterxml.jackson.core:jackson-core:2.12.0:jar com.fasterxml.jackson.core:jackson-databind:2.12.0:jar com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.12.0:jar +com.github.virtuald:curvesapi:1.06:jar com.google.code.findbugs:annotations:3.0.1:jar com.google.errorprone:error_prone_annotations:2.1.3:jar com.google.guava:guava:25.0-jre:jar +com.google.inject:guice:4.0:jar com.google.j2objc:j2objc-annotations:1.1:jar +com.google.protobuf:protobuf-java:3.6.1:jar com.google.re2j:re2j:1.2:jar com.googlecode.java-ipv6:java-ipv6:0.17:jar com.hubspot.jinjava:jinjava:2.5.6:jar com.thoughtworks.xstream:xstream:1.4.14:jar +com.zaxxer:SparseBitSet:1.2:jar commons-codec:commons-codec:1.14:jar commons-io:commons-io:2.8.0:jar commons-net:commons-net:3.3:jar info.picocli:picocli:4.6.1:jar -io.trygvis.rules-sandbox:ri-wireguard:1.0-SNAPSHOT:jar +javax.annotation:jsr250-api:1.0:jar +javax.enterprise:cdi-api:1.0:jar +javax.inject:javax.inject:1:jar org.antlr:antlr-runtime:3.5.2:jar +org.apache.ant:ant:1.9.15:jar +org.apache.ant:ant-launcher:1.9.15:jar +org.apache.commons:commons-collections4:4.4:jar +org.apache.commons:commons-compress:1.19:jar org.apache.commons:commons-lang3:3.10:jar +org.apache.commons:commons-math3:3.6.1:jar +org.apache.httpcomponents:httpclient:4.5.12:jar +org.apache.httpcomponents:httpcore:4.4.13:jar +org.apache.maven:maven-aether-provider:3.3.9:jar +org.apache.maven:maven-artifact:3.3.9:jar +org.apache.maven:maven-builder-support:3.3.9:jar +org.apache.maven:maven-compat:3.3.9:jar +org.apache.maven:maven-core:3.3.9:jar +org.apache.maven:maven-model:3.3.9:jar +org.apache.maven:maven-model-builder:3.3.9:jar +org.apache.maven:maven-plugin-api:3.3.9:jar +org.apache.maven:maven-repository-metadata:3.3.9:jar +org.apache.maven:maven-settings:3.3.9:jar +org.apache.maven:maven-settings-builder:3.3.9:jar +org.apache.maven.wagon:wagon-http:3.0.0:jar +org.apache.maven.wagon:wagon-http-shared:3.0.0:jar +org.apache.maven.wagon:wagon-provider-api:3.0.0:jar +org.apache.poi:poi:4.1.2:jar +org.apache.poi:poi-ooxml:4.1.2:jar +org.apache.poi:poi-ooxml-schemas:4.1.2:jar +org.apache.xmlbeans:xmlbeans:3.1.0:jar org.checkerframework:checker-compat-qual:2.0.0:jar org.codehaus.mojo:animal-sniffer-annotations:1.14:jar +org.codehaus.plexus:plexus-classworlds:2.5.2:jar +org.codehaus.plexus:plexus-component-annotations:1.6:jar +org.codehaus.plexus:plexus-interpolation:1.21:jar +org.codehaus.plexus:plexus-utils:3.0.22:jar org.drools:drools-compiler:7.48.0.Final:jar org.drools:drools-core:7.48.0.Final:jar +org.drools:drools-core-dynamic:7.48.0.Final:jar org.drools:drools-core-reflective:7.48.0.Final:jar +org.drools:drools-decisiontables:7.48.0.Final:jar org.drools:drools-ecj:7.48.0.Final:jar org.drools:drools-mvel:7.48.0.Final:jar +org.drools:drools-serialization-protobuf:7.48.0.Final:jar +org.drools:drools-templates:7.48.0.Final:jar +org.eclipse.aether:aether-api:1.1.0:jar +org.eclipse.aether:aether-connector-basic:1.1.0:jar +org.eclipse.aether:aether-impl:1.1.0:jar +org.eclipse.aether:aether-spi:1.1.0:jar +org.eclipse.aether:aether-transport-file:1.1.0:jar +org.eclipse.aether:aether-transport-http:1.1.0:jar +org.eclipse.aether:aether-transport-wagon:1.1.0:jar +org.eclipse.aether:aether-util:1.1.0:jar +org.eclipse.sisu:org.eclipse.sisu.inject:0.3.2:jar +org.eclipse.sisu:org.eclipse.sisu.plexus:0.3.2:jar org.javassist:javassist:3.24.1-GA:jar org.jsoup:jsoup:1.10.3:jar -org.kie:kie-dmn-api:7.48.0.Final:jar -org.kie:kie-dmn-model:7.48.0.Final:jar +org.kie:kie-api:7.48.0.Final:jar +org.kie:kie-ci:7.48.0.Final:jar +org.kie:kie-internal:7.48.0.Final:jar org.kie:kie-memory-compiler:7.48.0.Final:jar -org.kie:kie-pmml-api:7.48.0.Final:jar -org.kie:kie-pmml-commons:7.48.0.Final:jar -org.kie:kie-pmml-evaluator-api:7.48.0.Final:jar -org.kie.kogito:drools-core:1.1.0.Final:jar -org.kie.kogito:drools-core-static:1.1.0.Final:jar -org.kie.kogito:kogito-api:1.1.0.Final:jar -org.kie.kogito:kogito-internal:1.1.0.Final:jar -org.kie.kogito:kogito-pmml-api-dependencies:1.1.0.Final:pom -org.kie.kogito:kogito-services:1.1.0.Final:jar -org.kie.kogito:kogito-timer:1.1.0.Final:jar org.kie.soup:kie-soup-commons:7.48.0.Final:jar +org.kie.soup:kie-soup-maven-integration:7.48.0.Final:jar org.kie.soup:kie-soup-maven-support:7.48.0.Final:jar org.kie.soup:kie-soup-project-datamodel-api:7.48.0.Final:jar org.kie.soup:kie-soup-project-datamodel-commons:7.48.0.Final:jar org.kie.soup:kie-soup-xstream:7.48.0.Final:jar org.mvel:mvel2:2.4.11.Final:jar +org.slf4j:jcl-over-slf4j:1.7.30:jar org.slf4j:slf4j-api:1.7.30:jar +org.sonatype.plexus:plexus-cipher:1.7:jar +org.sonatype.plexus:plexus-sec-dispatcher:1.3:jar org.yaml:snakeyaml:1.26:jar xmlpull:xmlpull:1.1.3.1:jar xpp3:xpp3_min:1.1.4c:jar diff --git a/module/ri-engine/pom.xml b/module/ri-engine/pom.xml index 3a7243e..97fee1c 100644 --- a/module/ri-engine/pom.xml +++ b/module/ri-engine/pom.xml @@ -15,15 +15,26 @@ - ${project.groupId} - ri-wireguard - ${project.version} + org.drools + drools-core - - org.kie.kogito - drools-core + org.drools + drools-compiler + + + org.drools + drools-decisiontables + + org.drools + drools-templates + + + org.kie + kie-ci + + ch.qos.logback @@ -63,6 +75,11 @@ commons-io commons-io + + info.picocli + picocli + ${version.picocli} + org.junit.jupiter @@ -77,4 +94,55 @@ test + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + info.picocli + picocli-codegen + ${version.picocli} + + + + -Aproject=${project.groupId}/${project.artifactId} + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + true + lib/ + io.trygvis.rules.engine.Main + + + + + + 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 deleted file mode 100644 index 04d1af3..0000000 --- a/module/ri-engine/src/main/java/io/trygvis/rules/core/Problem.java +++ /dev/null @@ -1,11 +0,0 @@ -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/Cluster.java b/module/ri-engine/src/main/java/io/trygvis/rules/dba/Cluster.java deleted file mode 100644 index 0b65aaa..0000000 --- a/module/ri-engine/src/main/java/io/trygvis/rules/dba/Cluster.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.trygvis.rules.dba; - -import com.fasterxml.jackson.annotation.JsonIdentityInfo; -import com.fasterxml.jackson.annotation.ObjectIdGenerators; - -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") -public class Cluster { - public String name; - - public Cluster(String name) { - this.name = name; - } -} 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 deleted file mode 100644 index 3888661..0000000 --- a/module/ri-engine/src/main/java/io/trygvis/rules/dba/Container.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.trygvis.rules.dba; - -import com.fasterxml.jackson.annotation.JsonIdentityReference; -import io.trygvis.rules.machine.Machine; -import io.trygvis.rules.machine.MachineSpecification; - -//@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") -public class Container { - public final String id; - -// @JsonIdentityReference(alwaysAsId = true) - public final Cluster cluster; - public final String name; - public final String machineRole; - public final String image; - public final String tag; - - private Machine machine; - public final MachineSpecification machineSpecification; - - public Container(Cluster cluster, String name, String machineRole, String image, String tag, - MachineSpecification machineSpecification) { - this.id = cluster.name + "-" + name; - this.cluster = cluster; - this.name = name; - this.machineRole = machineRole; - this.image = image; - this.tag = tag; - this.machineSpecification = machineSpecification; - } - - 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/DnsEntry.java b/module/ri-engine/src/main/java/io/trygvis/rules/dns/DnsEntry.java deleted file mode 100644 index 105ef79..0000000 --- a/module/ri-engine/src/main/java/io/trygvis/rules/dns/DnsEntry.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.trygvis.rules.dns; - -public class DnsEntry { - public String fqdn; - public String type; - - public DnsEntry(String fqdn, String type) { - this.fqdn = fqdn; - this.type = type; - } - - public static DnsEntry a(String fqdn) { - return new DnsEntry(fqdn, "A"); - } - - public static DnsEntry aaaa(String fqdn) { - return new DnsEntry(fqdn, "AAAA"); - } - - public String getFqdn() { - return fqdn; - } - - public String getType() { - return type; - } -} diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/dns/DnsEntryTerraformExpression.java b/module/ri-engine/src/main/java/io/trygvis/rules/dns/DnsEntryTerraformExpression.java deleted file mode 100644 index 79bf934..0000000 --- a/module/ri-engine/src/main/java/io/trygvis/rules/dns/DnsEntryTerraformExpression.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.trygvis.rules.dns; - -public class DnsEntryTerraformExpression { - public DnsEntry entry; - public String key; - public String expression; - - public DnsEntryTerraformExpression(DnsEntry entry, String key, String expression) { - this.entry = entry; - this.key = key; - this.expression = expression; - } - - public String getKey() { - return key; - } - - public String getExpression() { - return expression; - } -} 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 deleted file mode 100644 index 1af5c8f..0000000 --- a/module/ri-engine/src/main/java/io/trygvis/rules/dns/DnsZone.java +++ /dev/null @@ -1,9 +0,0 @@ -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/java/io/trygvis/rules/engine/DbIo.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/DbIo.java index b8ee03a..d3d309a 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,6 +14,8 @@ 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 java.io.File; @@ -29,14 +31,14 @@ public class DbIo { private static final List prioritizedKeys = List.of("key", "name", "fqdn"); - public DbIo(KieBase kieBase) { + public DbIo(KieContainer container, KieBase kieBase) { var factory = new YAMLFactory(); factory.enable(YAMLGenerator.Feature.USE_NATIVE_TYPE_ID); factory.enable(YAMLGenerator.Feature.USE_NATIVE_OBJECT_ID); mapper = new ObjectMapper(factory); mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); var typeFactory = TypeFactory.defaultInstance() - .withClassLoader(new AcmeClassLoader(kieBase)); + .withClassLoader(new DbClassLoader(container, kieBase)); mapper.setTypeFactory(typeFactory); mapper.findAndRegisterModules(); @@ -50,7 +52,7 @@ public class DbIo { for (String name : prioritizedKeys) { try { final String getter = "get" + name.substring(0, 1).toUpperCase() + name.substring(1); - var f = klass.getMethod(getter); + klass.getMethod(getter); return new ObjectIdInfo(PropertyName.construct(name), null, ObjectIdGenerators.PropertyGenerator.class, null); } catch (NoSuchMethodException ignore) { } @@ -64,8 +66,8 @@ public class DbIo { }); } - public List load(String file) throws IOException { - var parser = mapper.getFactory().createParser(new File(file)); + public List load(File file) throws IOException { + var parser = mapper.getFactory().createParser(file); var objects = mapper.readValues(parser, DbObject.class).readAll(new ArrayList<>()); @@ -79,6 +81,8 @@ public class DbIo { } items.add(x); } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { + System.out.println("e.getClass() = " + e.getClass().getName()); + System.out.println("e.getMessage() = " + e.getMessage()); // ignore } } @@ -86,8 +90,8 @@ public class DbIo { return items; } - public void dump(String s, Collection factHandles) throws IOException { - dump(s, factHandles, (o) -> true); + public void dump(File file, Collection factHandles) throws IOException { + dump(file, factHandles, (o) -> true); } // This should just sort by all getters instead. @@ -221,10 +225,8 @@ public class DbIo { static record DbObject2(String type, Object data) { } - public void dump(String s, Collection factHandles, Function filter) throws IOException { - var yamlFile = new File("out", s + ".yaml"); - - FileUtil.createMissingParentDirectories(yamlFile); + public void dump(File file, Collection factHandles, Function filter) throws IOException { + FileUtil.createMissingParentDirectories(file); var facts = new TreeMap, FactCollection>(Comparator.comparing(Class::getName)); for (var handle : factHandles) { @@ -260,16 +262,18 @@ public class DbIo { objects.sort(new DbObjectComparator()); var factory = mapper.getFactory(); - try (var writer = new FileWriter(yamlFile); + try (var writer = new FileWriter(file); var g = factory.createGenerator(writer)) { g.writeObject(objects); } } - private static class AcmeClassLoader extends ClassLoader { + private static class DbClassLoader extends ClassLoader { private final KieBase kieBase; + private final KieContainer container; - public AcmeClassLoader(KieBase kieBase) { + public DbClassLoader(KieContainer container, KieBase kieBase) { + this.container = container; this.kieBase = kieBase; } @@ -287,7 +291,18 @@ public class DbIo { pkg = name.substring(0, i); klass = name.substring(i + 1); } - var clazz = kieBase.getFactType(pkg, klass); + + try { + return container.getClassLoader().loadClass(name); + } catch (ClassNotFoundException ignore) { + } + + FactType clazz = null; + try { + clazz = kieBase.getFactType(pkg, klass); + } catch (UnsupportedOperationException ignore) { + System.out.println("AcmeClassLoader.loadClass: " + name); + } if (clazz == null) { 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 b73e2e8..3db1625 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 @@ -2,41 +2,83 @@ package io.trygvis.rules.engine; import org.drools.core.audit.WorkingMemoryConsoleLogger; import org.kie.api.KieServices; +import org.kie.api.builder.Message; +import org.kie.api.builder.Message.Level; +import org.kie.api.builder.ReleaseId; import org.kie.api.event.rule.AgendaEventListener; import org.kie.api.event.rule.RuleRuntimeEventListener; import org.kie.api.runtime.KieSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.Closeable; import java.io.File; import java.io.IOException; public class Engine implements Closeable { + private final Logger logger = LoggerFactory.getLogger(getClass()); + public final DbIo io; public final KieSession session; - public Engine(String name, String database, File output, String[] agendaGroups) throws IOException { + public Engine(String name, File database, File output, String[] agendaGroups, File[] modules) throws IOException { + logger.info("Getting KieServices"); + var services = KieServices.Factory.get(); - var container = services.getKieClasspathContainer(); - var kieBase = container.getKieBase(name); - io = new DbIo(kieBase); - var objects = io.load(database); + ReleaseId releaseId = null; + for (File path : (modules == null ? new File[0] : modules)) { + logger.info("New KieBuilder: {}", path); + + +// var kieBuilder = services.newKieBuilder(fileSystem); + var kieBuilder = services.newKieBuilder(path); + logger.info("Building module"); + kieBuilder.buildAll(); + + logger.info("Module built!"); + + var results = kieBuilder.getResults(); + + for (Message message : results.getMessages(Level.INFO, Level.WARNING, Level.ERROR)) { +// logger.info("{} {}", message.getLevel(), message.getText()); + logger.info(message.toString()); + } + + var module = kieBuilder.getKieModule(); + releaseId = module.getReleaseId(); + logger.info("module.getReleaseId() = {}", releaseId); + logger.info("module.getClass() = {}", module.getClass()); + } + + logger.info("Creating classpath container"); +// var container = services.getKieClasspathContainer(); + var container = services.newKieContainer(releaseId); + + logger.info("Creating KieBase"); + logger.info("Available kie base names: {}", container.getKieBaseNames()); + var kieBase = container.getKieBase(name); session = container.newKieSession(name); - var logger = new WorkingMemoryConsoleLogger(session); - session.addEventListener((AgendaEventListener) logger); - session.addEventListener((RuleRuntimeEventListener) logger); + var l = new WorkingMemoryConsoleLogger(session); + session.addEventListener((AgendaEventListener) l); + session.addEventListener((RuleRuntimeEventListener) l); - session.setGlobal("te", new TemplateEngine(output)); + session.setGlobal("te", new JinjavaTemplateEngine(output)); + + logger.info("Loading data"); + io = new DbIo(container, kieBase); + var objects = io.load(database); + logger.info("Loaded {} objects", objects.size()); for (var object : objects) { - System.out.println("object = " + object); + logger.info("object = " + object); session.insert(object); } for (var agendaGroup : agendaGroups) { - System.out.println("Setting agenda: " + agendaGroup); + logger.info("Setting agenda: " + agendaGroup); session.getAgenda().getAgendaGroup(agendaGroup).setFocus(); session.fireAllRules(); } 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 new file mode 100644 index 0000000..42b2127 --- /dev/null +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/JinjavaTemplateEngine.java @@ -0,0 +1,40 @@ +package io.trygvis.rules.engine; + +import ch.qos.logback.core.util.FileUtil; +import com.hubspot.jinjava.Jinjava; +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; + +public class JinjavaTemplateEngine implements TemplateEngine { + private final Jinjava jinjava = new Jinjava(); + + private final File basedir; + + public JinjavaTemplateEngine(File basedir) { + this.basedir = basedir; + } + + @Override + public void clean() { + try { + System.out.println("Cleaning gen!"); + FileUtils.deleteDirectory(basedir); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void template(String name, String output, Map params) throws IOException { + var template = Files.readString(Path.of("j2", name + ".j2")); + String renderedTemplate = jinjava.render(template, params); + var f = new File(basedir, output); + FileUtil.createMissingParentDirectories(f); + Files.writeString(f.toPath(), renderedTemplate); + } +} diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/KeyValue.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/KeyValue.java deleted file mode 100644 index 5046169..0000000 --- a/module/ri-engine/src/main/java/io/trygvis/rules/engine/KeyValue.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.trygvis.rules.engine; - -public class KeyValue { - public String key; - public String value; - - public KeyValue() { - } - - public KeyValue(String key, String value) { - this.key = key; - this.value = value; - } -} diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/Main.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/Main.java new file mode 100644 index 0000000..4f06091 --- /dev/null +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/Main.java @@ -0,0 +1,20 @@ +package io.trygvis.rules.engine; + +import io.trygvis.rules.engine.cli.DatabaseCommand; +import io.trygvis.rules.engine.cli.RunCommand; +import picocli.CommandLine; +import picocli.CommandLine.Command; + +@Command( + name = "engine", + subcommands = {RunCommand.class, DatabaseCommand.class}, + mixinStandardHelpOptions = true, + version = "UNSPECIFIED") +class Main { + + public static void main(String... args) { + //noinspection InstantiationOfUtilityClass + int exitCode = new CommandLine(new Main()).execute(args); + System.exit(exitCode); + } +} 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 cc085c0..eafa6e4 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,38 +1,10 @@ package io.trygvis.rules.engine; -import ch.qos.logback.core.util.FileUtil; -import com.hubspot.jinjava.Jinjava; -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; -public class TemplateEngine { - private final Jinjava jinjava = new Jinjava(); - - private final File basedir; - - public TemplateEngine(File basedir) { - this.basedir = basedir; - } - - public void clean() { - try { - System.out.println("Cleaning gen!"); - FileUtils.deleteDirectory(basedir); - } catch (IOException e) { - throw new RuntimeException(e); - } - } +public interface TemplateEngine { + void clean(); - public void template(String name, String output, Map params) throws IOException { - var template = Files.readString(Path.of("j2", name + ".j2")); - String renderedTemplate = jinjava.render(template, params); - var f = new File(basedir, output); - FileUtil.createMissingParentDirectories(f); - Files.writeString(f.toPath(), renderedTemplate); - } + void template(String name, String output, Map params) throws IOException; } diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/DatabaseCommand.java b/module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/DatabaseCommand.java new file mode 100644 index 0000000..03650b5 --- /dev/null +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/DatabaseCommand.java @@ -0,0 +1,20 @@ +package io.trygvis.rules.engine.cli; + +import picocli.CommandLine.Command; + +import java.util.concurrent.Callable; + +import static picocli.CommandLine.Option; + +@Command(name = "database") +public class DatabaseCommand implements Callable { + + @Option(names = {"-v", "--verbose"}) + private boolean verbose; + + @Override + public Integer call() { + System.out.println("DatabaseCommand.call"); + return 0; + } +} 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 new file mode 100644 index 0000000..345d8b8 --- /dev/null +++ b/module/ri-engine/src/main/java/io/trygvis/rules/engine/cli/RunCommand.java @@ -0,0 +1,55 @@ +package io.trygvis.rules.engine.cli; + +import io.trygvis.rules.engine.Engine; + +import java.io.File; +import java.util.concurrent.Callable; + +import static picocli.CommandLine.Command; +import static picocli.CommandLine.Option; + +@Command(name = "run") +public class RunCommand implements Callable { + + @Option(names = {"-n", "--name"}) + public String name; + + @Option(names = {"-i", "--input"}) + public File input; + + @Option(names = {"--output-state"}) + public File outputState; + + @Option(names = {"--generated-output"}) + public File generatedOutput; + + @Option(names = {"--agenda-groups"}) + public String[] agendaGroups; + + @Option(names = {"--modules"}, split = ",") + public File[] modules; + + @Override + public Integer call() throws Exception { + System.out.println("RunCommand.call"); + + if (agendaGroups == null || agendaGroups.length == 0) { + agendaGroups = new String[]{"init", "generate"}; + } + + try (var engine = new Engine(name, input, generatedOutput, agendaGroups, modules)) { + 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") + ); + System.out.println("RunCommand.call"); + } + + System.out.println("RunCommand.call"); + + return 0; + } +} diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/machine/Machine.java b/module/ri-engine/src/main/java/io/trygvis/rules/machine/Machine.java deleted file mode 100644 index 34c17ca..0000000 --- a/module/ri-engine/src/main/java/io/trygvis/rules/machine/Machine.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.trygvis.rules.machine; - -import com.fasterxml.jackson.annotation.JsonIdentityInfo; -import com.fasterxml.jackson.annotation.ObjectIdGenerators; - -@SuppressWarnings("unused") -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") -public class Machine { - public String name; - private String fqdn; - - public Machine() { - } - - public Machine(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public String getFqdn() { - return fqdn; - } - - public void setFqdn(String fqdn) { - this.fqdn = fqdn; - } -} diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/machine/MachineSpecification.java b/module/ri-engine/src/main/java/io/trygvis/rules/machine/MachineSpecification.java deleted file mode 100644 index 2e17ae5..0000000 --- a/module/ri-engine/src/main/java/io/trygvis/rules/machine/MachineSpecification.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.trygvis.rules.machine; - -public class MachineSpecification { - public final int cpu; - public final int memory; - - public MachineSpecification(int cpu, int memory) { - this.cpu = cpu; - this.memory = memory; - } - - public int getCpu() { - return cpu; - } - - public int getMemory() { - return memory; - } -} diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/network/IpCalc.java b/module/ri-engine/src/main/java/io/trygvis/rules/network/IpCalc.java deleted file mode 100644 index 7ec344c..0000000 --- a/module/ri-engine/src/main/java/io/trygvis/rules/network/IpCalc.java +++ /dev/null @@ -1,6 +0,0 @@ -package io.trygvis.rules.network; - -import java.util.regex.Pattern; - -public class IpCalc { -} diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/network/Ipv4Address.java b/module/ri-engine/src/main/java/io/trygvis/rules/network/Ipv4Address.java deleted file mode 100644 index 7ca9ca5..0000000 --- a/module/ri-engine/src/main/java/io/trygvis/rules/network/Ipv4Address.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.trygvis.rules.network; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; - -import java.io.IOException; -import java.util.Objects; - -@JsonSerialize(using = Ipv4Address.Serializer.class) -public class Ipv4Address implements Comparable { - public final int address; - - public Ipv4Address(int address) { - this.address = address; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - - if (o instanceof Ipv4Address other) { - return address == other.address; - } - - return false; - } - - @Override - public int hashCode() { - return Objects.hash(address); - } - - @Override - public int compareTo(Ipv4Address o) { - return address - o.address; - } - - @Override - public String toString() { - return "%d.%d.%d.%d".formatted( - address >> 24 & 0xff, - address >> 16 & 0xff, - address >> 8 & 0xff, - address & 0xff); - } - - public static class Serializer extends JsonSerializer { - @Override - public void serialize(Ipv4Address value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeStartObject(); - gen.writeObjectField("value", value.toString()); - gen.writeEndObject(); - } - } -} diff --git a/module/ri-engine/src/main/java/io/trygvis/rules/network/Ipv4Cidr.java b/module/ri-engine/src/main/java/io/trygvis/rules/network/Ipv4Cidr.java deleted file mode 100644 index 6362107..0000000 --- a/module/ri-engine/src/main/java/io/trygvis/rules/network/Ipv4Cidr.java +++ /dev/null @@ -1,152 +0,0 @@ -package io.trygvis.rules.network; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.checkerframework.checker.nullness.compatqual.NonNullType; - -import javax.annotation.Nonnull; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.regex.Pattern; - -@JsonSerialize(using = Ipv4Cidr.Serializer.class) -public class Ipv4Cidr implements Comparable { - public final int network; - public final int bits; - - public Ipv4Cidr(int network, int bits) { - if (bits < 0 || bits > 32) { - throw new IllegalArgumentException("bits must be [0, 32]"); - } - - int hostBits = 32 - bits; - int netmask = (-1 >> hostBits) << hostBits; - - int x = network & ~netmask; - - if (x != 0) { - throw new IllegalArgumentException("The host part of the address must be 0."); - } - - this.network = network; - this.bits = bits; - } - - @Override - public String toString() { - return "%d.%d.%d.%d/%d".formatted( - network >> 24 & 0xff, - network >> 16 & 0xff, - network >> 8 & 0xff, - network & 0xff, - bits); - } - - private String formatIpv4(int address) { - return "%d.%d.%d.%d".formatted(address >> 24 & 0xff, address >> 16 & 0xff, address >> 8 & 0xff, address & 0xff); - } - - public List partition(int bits) { - if (bits <= 0 || bits <= this.bits || bits > 32) { - throw new IllegalArgumentException("Invalid new network size"); - } - - var list = new ArrayList(); - - int count = 1 << (bits - this.bits); - for (int i = 0; i < count; i++) { - var network = this.network | (i << (32 - bits)); - - list.add(new Ipv4Cidr(network, bits)); - } - - return list; - } - - public List addresses() { - int size = 1 << 32 - bits; - var end = network + size; - var addresses = new ArrayList(size); - for (int address = network; address < end; address++) { - addresses.add(new Ipv4Address(address)); - } - - return addresses; - } - - @Override - public int compareTo(Ipv4Cidr o) { - if (this == o) { - return 0; - } - - var ret = network - o.network; - if (ret != 0) { - return ret; - } - - return bits - o.bits; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Ipv4Cidr ipv4Cidr = (Ipv4Cidr) o; - return network == ipv4Cidr.network && bits == ipv4Cidr.bits; - } - - @Override - public int hashCode() { - return Objects.hash(network, bits); - } - - private static final Pattern pattern = Pattern.compile("([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})/([0-9]{1,3})"); - - public static Ipv4Cidr parseCidr(String cidr) { - var matcher = pattern.matcher(cidr); - if (!matcher.matches()) { - throw new IllegalArgumentException("Not a CIDR: " + cidr); - } - - var b1 = matcher.group(1); - var b2 = matcher.group(2); - var b3 = matcher.group(3); - var b4 = matcher.group(4); - - int network = parse(b1) << 24 | - parse(b2) << 16 | - parse(b3) << 8 | - parse(b4); - -// System.out.printf("network = %x%n", network); - - var l = matcher.group(5); - var bits = Integer.parseInt(l); -// System.out.printf("netmask = %08x%n", netmask); - - return new Ipv4Cidr(network, bits); - } - - private static int parse(String s) { - var i = Integer.parseInt(s); - if (i > 255) { - throw new IllegalArgumentException("Not a CIDR"); - } - - return i; - } - - public static class Serializer extends JsonSerializer { - @Override - public void serialize(Ipv4Cidr value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeStartObject(); - gen.writeObjectField("value", value.toString()); - gen.writeEndObject(); - } - } -} diff --git a/module/ri-engine/src/main/resources/META-INF/kmodule.xml b/module/ri-engine/src/main/resources/META-INF/kmodule.xml deleted file mode 100644 index 79c5e79..0000000 --- a/module/ri-engine/src/main/resources/META-INF/kmodule.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - 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 deleted file mode 100644 index 0bee004..0000000 --- a/module/ri-engine/src/main/resources/io/trygvis/rules/dba/dba.drl +++ /dev/null @@ -1,69 +0,0 @@ -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 machine" -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/module/ri-engine/src/main/resources/io/trygvis/rules/engine/init.drl b/module/ri-engine/src/main/resources/io/trygvis/rules/engine/init.drl deleted file mode 100644 index 267cc4a..0000000 --- a/module/ri-engine/src/main/resources/io/trygvis/rules/engine/init.drl +++ /dev/null @@ -1,17 +0,0 @@ -package io.trygvis.rules.engine; - -import java.util.Map -import org.apache.commons.io.FileSystem -import org.apache.commons.io.FileUtils -import java.io.File - -global io.trygvis.rules.engine.TemplateEngine te; - -rule "Clean directories" - agenda-group "init" -when - not(KeyValue(key == "rm-gen")); -then - te.clean(); - insert(new KeyValue("rm-gen", null)); -end diff --git a/module/ri-engine/src/main/resources/io/trygvis/rules/terraform/terraform.drl b/module/ri-engine/src/main/resources/io/trygvis/rules/terraform/terraform.drl deleted file mode 100644 index 07a96e2..0000000 --- a/module/ri-engine/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 - var 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 - var a = DnsEntry.a($machine.fqdn); - insert(a); - - var 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 - var 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 - var 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 - var 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-engine/src/test/java/io/trygvis/rules/network/Ipv4CidrTest.java b/module/ri-engine/src/test/java/io/trygvis/rules/network/Ipv4CidrTest.java deleted file mode 100644 index 0d9f33e..0000000 --- a/module/ri-engine/src/test/java/io/trygvis/rules/network/Ipv4CidrTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.trygvis.rules.network; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -import static io.trygvis.rules.network.Ipv4Cidr.parseCidr; -import static org.junit.jupiter.api.Assertions.*; - -class Ipv4CidrTest { - - @Test - public void basic() { - assertThrows(IllegalArgumentException.class, () -> parseCidr("192.168.1.1/24").addresses()); - assertEquals(256, parseCidr("192.168.1.0/24").addresses().size()); - assertEquals(128, parseCidr("192.168.1.128/25").addresses().size()); - } - - @ParameterizedTest - @ValueSource(strings = { - "192.168.1.0/24", - "192.168.1.128/25", - }) - public void testParsing(String s) { - assertEquals(s, parseCidr(s).toString()); - } - - @Test - public void partition() { - var children = parseCidr("192.168.1.0/24").partition(26); - assertEquals(1 << 2, children.size()); - for (var cidr : children) { - assertEquals(26, cidr.bits); - } - } -} diff --git a/module/ri-module-parent/classpath.txt b/module/ri-module-parent/classpath.txt new file mode 100644 index 0000000..8624088 --- /dev/null +++ b/module/ri-module-parent/classpath.txt @@ -0,0 +1,23 @@ +io.trygvis.rules-sandbox.module:ri-module-parent:1.0-SNAPSHOT:pom +com.github.javaparser:javaparser-core:3.13.10:jar +com.thoughtworks.xstream:xstream:1.4.14:jar +commons-codec:commons-codec:1.14:jar +commons-io:commons-io:2.8.0:jar +org.antlr:antlr-runtime:3.5.2:jar +org.drools:drools-canonical-model:7.48.0.Final:jar +org.drools:drools-compiler:7.48.0.Final:jar +org.drools:drools-core:7.48.0.Final:jar +org.drools:drools-core-dynamic:7.48.0.Final:jar +org.drools:drools-core-reflective:7.48.0.Final:jar +org.drools:drools-ecj:7.48.0.Final:jar +org.drools:drools-model-compiler:7.48.0.Final:jar +org.drools:drools-mvel-compiler:7.48.0.Final:jar +org.drools:drools-mvel-parser:7.48.0.Final:jar +org.kie:kie-api:7.48.0.Final:jar +org.kie:kie-internal:7.48.0.Final:jar +org.kie:kie-memory-compiler:7.48.0.Final:jar +org.kie.soup:kie-soup-maven-support:7.48.0.Final:jar +org.kie.soup:kie-soup-xstream:7.48.0.Final:jar +org.slf4j:slf4j-api:1.7.30:jar +xmlpull:xmlpull:1.1.3.1:jar +xpp3:xpp3_min:1.1.4c:jar diff --git a/module/ri-module-parent/pom.xml b/module/ri-module-parent/pom.xml new file mode 100644 index 0000000..1c54527 --- /dev/null +++ b/module/ri-module-parent/pom.xml @@ -0,0 +1,83 @@ + + + 4.0.0 + + ri-module-parent + io.trygvis.rules-sandbox.module + 1.0-SNAPSHOT + pom + + + 7.48.0.Final + 13 + + + + + org.drools + drools-model-compiler + + + commons-io + commons-io + + + + + + + io.trygvis.rules-sandbox + ri-engine + ${project.version} + pom + import + + + + + + + + org.kie + kie-maven-plugin + ${version.drools} + true + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + UTF-8 + ${java.version} + ${java.version} + ${java.version} + + + + org.apache.maven.plugins + maven-resources-plugin + 3.2.0 + + UTF-8 + + + + eu.nets.oss.maven + classpath-maven-plugin + 1.0 + + + default + + export-classpath + + + + + + + + diff --git a/module/ri-wireguard/classpath.txt b/module/ri-wireguard/classpath.txt index 52ccd4d..567c91f 100644 --- a/module/ri-wireguard/classpath.txt +++ b/module/ri-wireguard/classpath.txt @@ -1 +1,27 @@ -io.trygvis.rules-sandbox:ri-wireguard:1.0-SNAPSHOT:jar +io.trygvis.rules-sandbox.module:ri-wireguard:1.0-SNAPSHOT:jar +com.fasterxml.jackson.core:jackson-annotations:2.12.0:jar +com.fasterxml.jackson.core:jackson-core:2.12.0:jar +com.fasterxml.jackson.core:jackson-databind:2.12.0:jar +com.github.javaparser:javaparser-core:3.13.10:jar +com.thoughtworks.xstream:xstream:1.4.14:jar +commons-codec:commons-codec:1.14:jar +commons-io:commons-io:2.8.0:jar +io.trygvis.rules-sandbox.module:ri-base:1.0-SNAPSHOT:jar +org.antlr:antlr-runtime:3.5.2:jar +org.drools:drools-canonical-model:7.48.0.Final:jar +org.drools:drools-compiler:7.48.0.Final:jar +org.drools:drools-core:7.48.0.Final:jar +org.drools:drools-core-dynamic:7.48.0.Final:jar +org.drools:drools-core-reflective:7.48.0.Final:jar +org.drools:drools-ecj:7.48.0.Final:jar +org.drools:drools-model-compiler:7.48.0.Final:jar +org.drools:drools-mvel-compiler:7.48.0.Final:jar +org.drools:drools-mvel-parser:7.48.0.Final:jar +org.kie:kie-api:7.48.0.Final:jar +org.kie:kie-internal:7.48.0.Final:jar +org.kie:kie-memory-compiler:7.48.0.Final:jar +org.kie.soup:kie-soup-maven-support:7.48.0.Final:jar +org.kie.soup:kie-soup-xstream:7.48.0.Final:jar +org.slf4j:slf4j-api:1.7.30:jar +xmlpull:xmlpull:1.1.3.1:jar +xpp3:xpp3_min:1.1.4c:jar diff --git a/module/ri-wireguard/pom.xml b/module/ri-wireguard/pom.xml index a6ca2b8..86c6faa 100644 --- a/module/ri-wireguard/pom.xml +++ b/module/ri-wireguard/pom.xml @@ -5,12 +5,20 @@ 4.0.0 - io.trygvis.rules-sandbox - rules-sandbox + io.trygvis.rules-sandbox.module + ri-module-parent 1.0-SNAPSHOT - ../../pom.xml + ../ri-module-parent/pom.xml ri-wireguard + + + ${project.groupId} + ri-base + 1.0-SNAPSHOT + + + diff --git a/module/ri-wireguard/src/main/resources/logback.xml b/module/ri-wireguard/src/main/resources/logback.xml new file mode 100644 index 0000000..354003d --- /dev/null +++ b/module/ri-wireguard/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + diff --git a/out/acme/wireguard.yaml b/out/acme/wireguard.yaml index 58572d9..6eff70e 100644 --- a/out/acme/wireguard.yaml +++ b/out/acme/wireguard.yaml @@ -39,6 +39,23 @@ data: fqdn: "ws-2.vpn.acme.com" type: "A" +- 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" diff --git a/pom.xml b/pom.xml index 03b371e..f84b3f6 100644 --- a/pom.xml +++ b/pom.xml @@ -12,10 +12,11 @@ io.trygvis.rules.sandbox 2.12.0 - 1.1.0.Final + 7.48.0.Final 2.3.1.RELEASE + 4.6.1 15 UTF-8 @@ -36,6 +37,7 @@ pom import + org.drools drools-bom @@ -68,7 +71,10 @@ module/acme + module/acme-planner + module/ri-base module/ri-engine + module/ri-module-parent module/ri-wireguard @@ -80,7 +86,9 @@ maven-compiler-plugin 3.8.1 - --enable-preview + + --enable-preview + UTF-8 ${java.version} ${java.version} @@ -95,6 +103,14 @@ --enable-preview + + org.apache.maven.plugins + maven-resources-plugin + 3.2.0 + + UTF-8 + + eu.nets.oss.maven classpath-maven-plugin -- cgit v1.2.3