From 2c108c5171f8d1f10e048f65fcd195a8126cd5c6 Mon Sep 17 00:00:00 2001 From: Jesus Zazueta Date: Sun, 25 Aug 2024 07:05:46 -0400 Subject: [PATCH] - Initial API server based implementation. --- bl-k8s-rt/build.gradle.kts | 1 - .../java/io/vacco/beleth/rt/BlKubeRt.java | 11 ++-- .../io/vacco/beleth/rt/impl/BlKubeApi.java | 10 ++- .../io/vacco/beleth/rt/schema/BlResource.java | 10 +-- .../beleth/rt/schema/BlResourcePair.java | 11 +--- .../java/io/vacco/beleth/rt/util/BlIo.java | 65 ------------------- .../io/vacco/beleth/rt/util/BlResources.java | 41 ++++-------- 7 files changed, 33 insertions(+), 116 deletions(-) diff --git a/bl-k8s-rt/build.gradle.kts b/bl-k8s-rt/build.gradle.kts index 84a5279..df72d30 100644 --- a/bl-k8s-rt/build.gradle.kts +++ b/bl-k8s-rt/build.gradle.kts @@ -2,7 +2,6 @@ val api by configurations val k8s129 = ":bl-k8s129" dependencies { - api("io.github.java-diff-utils:java-diff-utils:4.12") api(project(":bl-codegen")) compileOnly(project(k8s129)) testImplementation(project(k8s129)) diff --git a/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/BlKubeRt.java b/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/BlKubeRt.java index 2038700..b8a6b05 100644 --- a/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/BlKubeRt.java +++ b/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/BlKubeRt.java @@ -31,12 +31,15 @@ public Set buildResourceSet(String packageName) { for (var manifest : manifests) { var objCopy = ctx.fromJson(ctx.toJson(manifest), manifest.getClass()); var objCopyMeta = pointerOnObject(objCopy, format("/%s", kMetadata)); - var blId = String.format("%s.%s", packageName, Integer.toHexString(ctx.toJson(objCopyMeta).hashCode())); + var blId = format("%s.%s", packageName, Integer.toHexString(ctx.toJson(objCopyMeta).hashCode())); + var blHash = Integer.toHexString(ctx.toJson(objCopy).hashCode()); var kind = requireNonNull(pointerOnObject(manifest, "/kind")).toString().toLowerCase() + "s"; var rType = BlResourceType.of("", kind, false); injectMeta(objCopy, kBl, Boolean.TRUE.toString()); injectMeta(objCopy, kBlId, blId); - idx.add(resourceOf(blId, objCopy).withType(rType)); + injectMeta(objCopy, kBlHash, blHash); + var res = resourceOf(blId, objCopy).withType(rType); + idx.add(res); } return idx; } @@ -59,8 +62,8 @@ public void commit(String packageName) { kubeApi.create(res); } for (var res : chg.toUpdate) { - var p = resourcePairOf(res.blId, local, cluster, kubeApi.ctx); - if (!p.patch.getDeltas().isEmpty()) { + var p = resourcePairOf(res.blId, local, cluster); + if (!p.manifest0.blHash.equals(p.manifest1.blHash)) { kubeApi.update(p.manifest0); } } diff --git a/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/impl/BlKubeApi.java b/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/impl/BlKubeApi.java index 52398a6..a787072 100644 --- a/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/impl/BlKubeApi.java +++ b/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/impl/BlKubeApi.java @@ -130,7 +130,10 @@ public String createUrlFor(BlResourceType type, String namespace) { } return String.format("%s/%s", type.apiPath, type.name); } else { - return String.format("%snamespaces/%s/%s", type.apiPath.replace(type.name, ""), namespace, type.name); + return String.format( + "%s/namespaces/%s/%s", type.apiPath.replace(type.name, ""), + namespace != null ? namespace : "default", type.name + ).replace("//", "/"); } } @@ -141,7 +144,10 @@ public String updateUrlFor(BlResourceType type, String namespace, String resourc } return String.format("%s/%s/%s", type.apiPath, type.name, resourceName); } else { - return String.format("%snamespaces/%s/%s/%s", type.apiPath.replace(type.name, ""), namespace, type.name, resourceName); + return String.format( + "%s/namespaces/%s/%s/%s", type.apiPath.replace(type.name, ""), + namespace != null ? namespace : "default", type.name, resourceName + ).replace("//", "/"); } } diff --git a/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/schema/BlResource.java b/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/schema/BlResource.java index 3b3036e..a385409 100644 --- a/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/schema/BlResource.java +++ b/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/schema/BlResource.java @@ -5,7 +5,7 @@ public class BlResource implements Comparable { public Object manifest; - public String blId, name, nameSpace; + public String blId, blHash, name, nameSpace; public BlResourceType type; public BlResource withType(BlResourceType type) { @@ -19,17 +19,17 @@ public BlResource withType(BlResourceType type) { @Override public boolean equals(Object obj) { return obj instanceof BlResource - && ((BlResource) obj).blId.equals(this.blId); + && ((BlResource) obj).blHash.equals(this.blHash); } @Override public int hashCode() { - return this.blId.hashCode(); + return this.blHash.hashCode(); } @Override public String toString() { return String.format( - "[%s, %s, %s, %s, %s]", - blId, + "[%s, %s, %s, %s, %s, %s]", + blId, blHash, manifest != null ? manifest.getClass().getSimpleName() : "?", type != null ? type.name : "?", name, diff --git a/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/schema/BlResourcePair.java b/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/schema/BlResourcePair.java index 7f9018a..97ba86b 100644 --- a/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/schema/BlResourcePair.java +++ b/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/schema/BlResourcePair.java @@ -1,24 +1,15 @@ package io.vacco.beleth.rt.schema; -import com.github.difflib.patch.Patch; -import java.util.List; import java.util.Objects; public class BlResourcePair { public BlResource manifest0, manifest1; - public List diff0, diff1; - public Patch patch; - public static BlResourcePair of(BlResource manifest0, BlResource manifest1, - List diff0, List diff1, - Patch patch) { + public static BlResourcePair of(BlResource manifest0, BlResource manifest1) { var p = new BlResourcePair(); p.manifest0 = Objects.requireNonNull(manifest0); p.manifest1 = Objects.requireNonNull(manifest1); - p.diff0 = Objects.requireNonNull(diff0); - p.diff1 = Objects.requireNonNull(diff1); - p.patch = Objects.requireNonNull(patch); return p; } diff --git a/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/util/BlIo.java b/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/util/BlIo.java index 3a98a44..15448f5 100644 --- a/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/util/BlIo.java +++ b/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/util/BlIo.java @@ -1,6 +1,5 @@ package io.vacco.beleth.rt.util; -import com.google.gson.JsonElement; import java.net.*; import javax.net.ssl.*; import java.net.http.*; @@ -104,45 +103,6 @@ public static Object pointerOnMap(Map root, String pointer) { } } - @SuppressWarnings("rawtypes") - public static boolean deleteFromMap(Map root, String pointer) { - var tokens = pointer.split("/"); - Object current = root; - try { - for (int i = 0; i < tokens.length; i++) { - var token = tokens[i]; - if (token.isEmpty()) continue; - if (current instanceof Map) { - @SuppressWarnings("unchecked") - var currentMap = (Map) current; - if (i == tokens.length - 1) { - currentMap.remove(token); - return true; // Deletion successful - } else { - current = currentMap.get(token); - } - } else if (current instanceof List) { - int index = Integer.parseInt(token); - var currentList = (List) current; - if (i == tokens.length - 1) { - currentList.remove(index); - return true; // Deletion successful - } else { - current = currentList.get(index); - } - } else { - return false; // Path does not lead to a valid Map or List - } - if (current == null) { - return false; // Path doesn't exist - } - } - } catch (Exception e) { - return false; - } - return false; // deletion did not happen - } - public static Object pointerOnObject(Object root, String pointer) { var tokens = pointer.split("/"); Object current = root; @@ -162,29 +122,4 @@ public static Object pointerOnObject(Object root, String pointer) { } } - private static void extractPathsTail(JsonElement element, String currentPath, Set paths) { - if (element.isJsonObject()) { - var obj = element.getAsJsonObject(); - for (var key : obj.keySet()) { - extractPathsTail(obj.get(key), currentPath.isEmpty() ? key : currentPath + "." + key, paths); - } - } else if (element.isJsonArray()) { - var arr = element.getAsJsonArray(); - for (int i = 0; i < arr.size(); i++) { - extractPathsTail(arr.get(i), currentPath + "[" + i + "]", paths); - } - } else if (element.isJsonPrimitive()) { - var prim = element.getAsJsonPrimitive(); - paths.add(currentPath + " = " + prim.toString()); - } else if (element.isJsonNull()) { - paths.add(currentPath + " = null"); - } - } - - public static List extractPaths(JsonElement root) { - var paths = new TreeSet(); - extractPathsTail(root, "", paths); - return new ArrayList<>(paths); - } - } diff --git a/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/util/BlResources.java b/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/util/BlResources.java index 47b9ffc..c591ab0 100644 --- a/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/util/BlResources.java +++ b/bl-k8s-rt/src/main/java/io/vacco/beleth/rt/util/BlResources.java @@ -1,10 +1,8 @@ package io.vacco.beleth.rt.util; -import com.github.difflib.DiffUtils; import io.k8s.apimachinery.pkg.apis.meta.v1.objectmeta.Labels; import io.vacco.beleth.rt.schema.BlResource; import io.vacco.beleth.rt.schema.BlResourcePair; -import io.vacco.beleth.xform.BlDocumentContext; import java.util.*; import static java.lang.String.format; @@ -17,7 +15,8 @@ public class BlResources { kMetadata = "metadata", kLabels = "labels", kBl = "beleth.io", - kBlId = "beleth.io/id"; + kBlId = "beleth.io.id", + kBlHash = "beleth.io.hash"; @SuppressWarnings({"rawtypes"}) public static String idOf(Map m) { @@ -80,22 +79,25 @@ public static boolean isValidPackageName(String packageName) { return true; } + @SuppressWarnings("rawtypes") public static BlResource resourceOf(String blId, Object manifest) { var r = new BlResource(); r.blId = Objects.requireNonNull(blId); r.manifest = Objects.requireNonNull(manifest); if (manifest instanceof Map) { - @SuppressWarnings("rawtypes") var m = (Map) manifest; var ns = pointerOnMap(m, "metadata/namespace"); - r.name = requireNonNull(pointerOnMap(m, "metadata/name")).toString(); + r.blHash = requireNonNull(pointerOnMap(m, format("/metadata/labels/%s", kBlHash))).toString(); + r.name = requireNonNull(pointerOnMap(m, "/metadata/name")).toString(); if (ns != null) { r.nameSpace = ns.toString(); } } else { - var ns = pointerOnObject(manifest, "metadata/namespace"); - r.name = requireNonNull(pointerOnObject(manifest, "metadata/name")).toString(); + var ns = pointerOnObject(manifest, "/metadata/namespace"); + var labels = (Map) requireNonNull(pointerOnObject(manifest, "/metadata/labels")); + r.blHash = labels.get(kBlHash).toString(); + r.name = requireNonNull(pointerOnObject(manifest, "/metadata/name")).toString(); if (ns != null) { r.nameSpace = ns.toString(); } @@ -104,30 +106,11 @@ public static BlResource resourceOf(String blId, Object manifest) { return r; } - public static BlResourcePair resourcePairOf(String blId, Set local, Set cluster, - BlDocumentContext ctx) { + @SuppressWarnings("rawtypes") + public static BlResourcePair resourcePairOf(String blId, Set local, Set cluster) { var r0 = local.stream().filter(r -> r.blId.equals(blId)).findFirst().orElseThrow(); var r1 = cluster.stream().filter(r -> r.blId.equals(blId)).findFirst().orElseThrow(); - - @SuppressWarnings("rawtypes") - var m1 = (Map) r1.manifest; - deleteFromMap(m1, "/metadata/uid"); - deleteFromMap(m1, "/metadata/resourceVersion"); - deleteFromMap(m1, "/metadata/creationTimestamp"); - deleteFromMap(m1, "/metadata/managedFields"); - deleteFromMap(m1, "/spec/finalizers"); - deleteFromMap(m1, "/status"); - - var d0 = extractPaths(ctx.toJsonElement(r0.manifest)); - var d1 = extractPaths(ctx.toJsonElement(r1.manifest)); - - d1.add(0, d0.get(1)); // kind - d1.add(0, d0.get(0)); // apiVersion - d1.stream() - .filter(t -> t.startsWith("metadata.labels.kubernetes.io/metadata.name")) - .findFirst().ifPresent(d1::remove); - - return BlResourcePair.of(r0, r1, d0, d1, DiffUtils.diff(d0, d1)); + return BlResourcePair.of(r0, r1); } }