From 7ee55ca4a83c0e566b7370f5107c1493267e520e Mon Sep 17 00:00:00 2001 From: Sander Hautvast Date: Mon, 12 Jul 2021 14:19:53 +0200 Subject: [PATCH] first code commit --- .gitignore | 3 + README.md | 2 + pom.xml | 55 +++ src/main/java/nl/sander/Cleaner.java | 64 +++ src/main/java/nl/sander/Union.java | 79 ++++ src/main/java/nl/sander/YamlObject.java | 128 ++++++ src/test/java/nl/sander/UnionTest.java | 34 ++ src/test/java/nl/sander/YamlObjectTest.java | 127 ++++++ src/test/resources/dc.yaml | 468 ++++++++++++++++++++ src/test/resources/dc.yaml_cleaned | 138 ++++++ src/test/resources/dc.yaml_cleaned_orig | 130 ++++++ src/test/resources/is.yaml | 86 ++++ src/test/resources/svc.yaml | 134 ++++++ 13 files changed, 1448 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 pom.xml create mode 100644 src/main/java/nl/sander/Cleaner.java create mode 100644 src/main/java/nl/sander/Union.java create mode 100644 src/main/java/nl/sander/YamlObject.java create mode 100644 src/test/java/nl/sander/UnionTest.java create mode 100644 src/test/java/nl/sander/YamlObjectTest.java create mode 100644 src/test/resources/dc.yaml create mode 100644 src/test/resources/dc.yaml_cleaned create mode 100644 src/test/resources/dc.yaml_cleaned_orig create mode 100644 src/test/resources/is.yaml create mode 100644 src/test/resources/svc.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..db84685 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +target/ +*.iml +.idea/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c5212ad --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +Cleaner for yaml files that openshift has created using oc get [resource] -o yaml. +NB. Work in progress: it works fine, but it might need adding more remove actions for certain outputs. diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..c3e9028 --- /dev/null +++ b/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + nl.sander + yaml-cleaner + 0.1-SNAPSHOT + yaml-cleaner + + + 2.10.4 + + + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + ${jackson.version} + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} + + + org.projectlombok + lombok + 1.18.14 + + + + org.junit.jupiter + junit-jupiter-engine + 5.6.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + + + + + + \ No newline at end of file diff --git a/src/main/java/nl/sander/Cleaner.java b/src/main/java/nl/sander/Cleaner.java new file mode 100644 index 0000000..0d2cd40 --- /dev/null +++ b/src/main/java/nl/sander/Cleaner.java @@ -0,0 +1,64 @@ +package nl.sander; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; + +import java.io.File; +import java.io.IOException; +import java.util.Map; + +public class Cleaner { + private final String yamlFile; + private final ObjectMapper objectMapper; + + public Cleaner(String filename) { + this.yamlFile = filename; + objectMapper = new ObjectMapper(new YAMLFactory()); + objectMapper.findAndRegisterModules(); + } + + public static void main(String[] args) { + if (args.length != 1) { + System.out.println("usage: nl.sander.Cleaner "); + System.exit(-1); + } + + String filename = args[0]; + new Cleaner(filename).run(); + } + + private void run() { + try { + Object resource = objectMapper.readValue(new File(yamlFile), Object.class); + Map cleaned = clean(YamlObject.of(resource)); + objectMapper.writeValue(new File(yamlFile + "_cleaned"), cleaned); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + private Map clean(YamlObject resource) { + resource.get("items") + .forEach(item -> { + YamlObject metadata = item.get("metadata"); + metadata.remove("managedFields"); + metadata.clear("annotations"); + metadata.remove("creationTimestamp"); + metadata.get("labels").removeIf("_key!=app"); + metadata.remove("selfLink"); + metadata.remove("namespace"); + metadata.remove("resourceVersion"); + metadata.remove("uid"); + YamlObject spec = item.get("spec"); + spec.clear("template/metadata/annotations"); + spec.remove("template/spec/containers/0/image"); + spec.remove("template/metadata/creationTimestamp"); + spec.remove("triggers/1/imageChangeParams/lastTriggeredImage"); + spec.removeIf("triggers/1/imageChangeParams/from/namespace != openshift"); + item.remove("status"); + }); + + return resource.asMap(); + } +} diff --git a/src/main/java/nl/sander/Union.java b/src/main/java/nl/sander/Union.java new file mode 100644 index 0000000..03e62a2 --- /dev/null +++ b/src/main/java/nl/sander/Union.java @@ -0,0 +1,79 @@ +package nl.sander; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Function; + +@SuppressWarnings("unchecked") +public class Union { + + private final List> types = new ArrayList<>(); + private Object value; + + + public Union(Class... types) { + if (Arrays.stream(types).distinct().count() != types.length) { + throw new IllegalArgumentException("types must be unique"); + } else { + for (Class left : types) { + for (Class right : types) { + if (left != right && (left.isAssignableFrom(right) || right.isAssignableFrom(left))) { + throw new IllegalArgumentException("types must not belong to same class hierarchy"); + } + } + } + this.types.addAll(Arrays.asList(types)); + } + } + + + public void set(Object newValue) { + if (newValue == null) { + throw new NullPointerException(); + } + checkType(newValue.getClass()); + this.value = newValue; + } + + + public T get() { + return (T) this.value; + } + + public void when(Class type, Consumer consumer) { + checkType(type); + if (type.isAssignableFrom(value.getClass())) { + consumer.accept((T) value); + } + } + + public Optional map(Class type, Function function) { + checkType(type); + + if (type.isAssignableFrom(value.getClass())) { + return Optional.ofNullable(function.apply((T) value)); + } else { + return Optional.empty(); + } + } + + private void checkType(Class someType) { + Class selectedType = null; + for (Class type : types) { + if (type.isAssignableFrom(someType)) { + selectedType = type; + } + } + if (selectedType == null) { + throw new IllegalArgumentException("unknown type for this union: " + someType.getName()); + } + } + + @Override + public String toString() { + return "Union{ value=" + value.getClass() + '}'; + } +} diff --git a/src/main/java/nl/sander/YamlObject.java b/src/main/java/nl/sander/YamlObject.java new file mode 100644 index 0000000..3edbd5e --- /dev/null +++ b/src/main/java/nl/sander/YamlObject.java @@ -0,0 +1,128 @@ +package nl.sander; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +//this is almost exactly unlike xpath +public class YamlObject { + private final Union union = new Union(Map.class, List.class, String.class); + + public static YamlObject of(Object value) { + YamlObject yamlObject = new YamlObject(); + yamlObject.union.set(value); + return yamlObject; + } + + public YamlObject get(String path) { + YamlObject result = this; + for (String element : path.split("/")) { + result = result.doGget(element); + } + return result; + } + + private YamlObject doGget(String key) { + Optional optionalYamlObject = union.map(List.class, l -> YamlObject.of(l.get(Integer.parseInt(key)))); + return optionalYamlObject + .orElseGet(() -> union.map(Map.class, m -> YamlObject.of(m.get(key))) + .orElseThrow(() -> new IllegalArgumentException("Not a collection object: " + union))); + } + + public void clear(String path) { + get(path).clear(); + } + + public void clear() { + union.when(Map.class, Map::clear); + union.when(List.class, List::clear); + } + + public void remove(String path) { + executeOn(path, (fetchedObject, lastPathElement) -> { + fetchedObject.union.when(Map.class, m -> m.remove(lastPathElement)); + fetchedObject.union.when(List.class, l -> l.remove(Integer.parseInt(lastPathElement))); + }); + } + + private void executeOn(String path, BiConsumer consumer) { + if (path.contains("/")) { + while (path.endsWith("/")) { + path = path.substring(0, path.length() - 1); + } + int lastSlash = path.lastIndexOf('/'); + String head = path.substring(0, lastSlash); + YamlObject object = get(head); + + String tail = path.substring(lastSlash + 1); + consumer.accept(object, tail); + } else { + consumer.accept(this, path); + } + } + + public void remove(int index) { + union.when(List.class, l -> l.remove(index)); + } + + public YamlObject retain(String... keys) { + List keyList = Arrays.asList(keys); + union.when(Map.class, m -> m.keySet().removeIf(key -> !keyList.contains(key))); + return this; + } + + public Map asMap() { + return union.map(Map.class, m -> (Map) m).orElseThrow(() -> new RuntimeException("Not a map")); + } + + public void removeIf(String path) { + executeOn(path, this::removeIf); + } + + private void removeIf(YamlObject fetchedYamlObject, String expression) { + boolean opEquals; + if (expression.contains("==")) { + opEquals = true; + } else if (expression.contains("!=")) { + opEquals = false; + } else { + throw new IllegalArgumentException("syntax exception"); + } + + String[] tokens = expression.split("[!=]="); + String key = tokens[0].trim(); + String operand = tokens[1].trim(); + + if (key.equals("_key") || key.equals("_value")) { + fetchedYamlObject.union.when(Map.class, m -> { + for (Iterator> iterator = m.entrySet().iterator(); iterator.hasNext(); ) { + Map.Entry entry = iterator.next(); + Object selector; + if (key.equals("_key")) { + selector = entry.getKey(); + } else { + selector = entry.getValue(); + } + if ((opEquals && selector.equals(operand)) || (!opEquals && !selector.equals(operand))) { + iterator.remove(); + } + } + }); + } else { + String value = fetchedYamlObject.get(key).toString(); + boolean remove = (operand.equals(value) && opEquals) || (!operand.equals(value) && !opEquals); + if (remove) { + fetchedYamlObject.union.when(Map.class, m -> m.remove(key)); + } + } + } + + public void forEach(Consumer consumer) { + union.when(List.class, list -> list.forEach(item -> consumer.accept(YamlObject.of(item)))); + } + + @Override + public String toString() { + return union.map(String.class, m -> m).orElse(super.toString()); + } +} diff --git a/src/test/java/nl/sander/UnionTest.java b/src/test/java/nl/sander/UnionTest.java new file mode 100644 index 0000000..7159531 --- /dev/null +++ b/src/test/java/nl/sander/UnionTest.java @@ -0,0 +1,34 @@ +package nl.sander; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class UnionTest { + + @Test + public void testGet() { + Union stringIntegerUnion = new Union(String.class, Integer.class, Long.class); + stringIntegerUnion.set("2"); + + assertEquals("2", stringIntegerUnion.get()); + } + + @Test + public void testGet2() { + Union stringIntegerUnion = new Union(String.class, Integer.class, Long.class); + stringIntegerUnion.set(1); + int value = stringIntegerUnion.get(); + assertEquals(1, value); + } + + @Test + public void testMap() { + Union union = new Union(String.class, Integer.class); + union.set(1); + StringBuilder result = new StringBuilder(); + union.when(Integer.class, v -> result.append("int ").append(v)); + union.when(String.class, v -> result.append("string ").append(v)); + assertEquals("int 1", result.toString()); + } +} \ No newline at end of file diff --git a/src/test/java/nl/sander/YamlObjectTest.java b/src/test/java/nl/sander/YamlObjectTest.java new file mode 100644 index 0000000..210eb20 --- /dev/null +++ b/src/test/java/nl/sander/YamlObjectTest.java @@ -0,0 +1,127 @@ +package nl.sander; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class YamlObjectTest { + + @Test + public void testSimpleRemove() { + Map mapValue = new HashMap<>(); + mapValue.put("app", "simple"); + mapValue.put("app.name", "noname"); + YamlObject yamlObject = YamlObject.of(mapValue); + + yamlObject.remove("app.name"); + assertEquals(1, mapValue.size()); + assertTrue(mapValue.containsKey("app")); + } + + @Test + public void testRemoveIf_notremoved() { + Map mapValue = new HashMap<>(); + mapValue.put("app", "simple"); + mapValue.put("app.name", "noname"); + YamlObject yamlObject = YamlObject.of(mapValue); + + yamlObject.removeIf("app.name == somename"); + assertEquals(2, mapValue.size()); + assertTrue(mapValue.containsKey("app")); + assertTrue(mapValue.containsKey("app.name")); + } + + @Test + public void testRemoveIf_removed() { + Map mapValue = new HashMap<>(); + mapValue.put("app", "simple"); + mapValue.put("app.name", "noname"); + YamlObject yamlObject = YamlObject.of(mapValue); + + yamlObject.removeIf("app.name == noname"); + assertEquals(1, mapValue.size()); + assertTrue(mapValue.containsKey("app")); + } + + @Test + public void testRemoveIf_lookForKey() { + Map mapValue = new HashMap<>(); + mapValue.put("app", "simple"); + mapValue.put("app.name", "noname"); + YamlObject yamlObject = YamlObject.of(mapValue); + + yamlObject.removeIf("_key==app.name"); + assertEquals(1, mapValue.size()); + assertTrue(mapValue.containsKey("app")); + } + + @Test + public void testRemoveIf_lookForKey_negative() { + Map mapValue = new HashMap<>(); + mapValue.put("app", "simple"); + mapValue.put("app.name", "noname"); + YamlObject yamlObject = YamlObject.of(mapValue); + + yamlObject.removeIf("_key!=app"); + assertEquals(1, mapValue.size()); + assertTrue(mapValue.containsKey("app")); + } + + @Test + public void testRemoveIf_lookForValue() { + Map mapValue = new HashMap<>(); + mapValue.put("app", "simple"); + mapValue.put("app.name", "noname"); + YamlObject yamlObject = YamlObject.of(mapValue); + + yamlObject.removeIf("_value==noname"); + assertEquals(1, mapValue.size()); + assertTrue(mapValue.containsKey("app")); + } + + @Test + public void testRemoveIf_lookForValue_negative() { + Map mapValue = new HashMap<>(); + mapValue.put("app", "simple"); + mapValue.put("app.name", "noname"); + YamlObject yamlObject = YamlObject.of(mapValue); + + yamlObject.removeIf("_value != simple"); + assertEquals(1, mapValue.size()); + assertTrue(mapValue.containsKey("app")); + } + + @Test + public void testCompoundRemove() { + Map spec = new HashMap<>(); + spec.put("app", "simple"); + spec.put("app.name", "noname"); + + Map item = new HashMap<>(); + item.put("spec", spec); + YamlObject yamlObject = YamlObject.of(item); + + yamlObject.remove("spec/app.name"); + assertEquals(1, spec.size()); + assertTrue(spec.containsKey("app")); + } + + @Test + public void testCompoundRemoveIf_lookForValue_negative() { + Map labels = new HashMap<>(); + labels.put("app", "simple"); + labels.put("app.name", "noname"); + + Map item = new HashMap<>(); + item.put("labels", labels); + YamlObject yamlObject = YamlObject.of(item); + + yamlObject.removeIf("labels/_value != simple"); + assertEquals(1, labels.size()); + assertTrue(labels.containsKey("app")); + } +} diff --git a/src/test/resources/dc.yaml b/src/test/resources/dc.yaml new file mode 100644 index 0000000..727e5a9 --- /dev/null +++ b/src/test/resources/dc.yaml @@ -0,0 +1,468 @@ +apiVersion: v1 +items: + - apiVersion: apps.openshift.io/v1 + kind: DeploymentConfig + metadata: + annotations: + openshift.io/generated-by: OpenShiftNewApp + creationTimestamp: "2021-07-07T13:42:16Z" + generation: 2 + labels: + app: quotesapi + app.kubernetes.io/component: quotesapi + app.kubernetes.io/instance: quotesapi + managedFields: + - apiVersion: apps.openshift.io/v1 + fieldsType: FieldsV1 + fieldsV1: + f:metadata: + f:annotations: + .: {} + f:openshift.io/generated-by: {} + f:labels: + .: {} + f:app: {} + f:app.kubernetes.io/component: {} + f:app.kubernetes.io/instance: {} + f:spec: + f:replicas: {} + f:selector: + .: {} + f:deploymentconfig: {} + f:strategy: + f:activeDeadlineSeconds: {} + f:rollingParams: + .: {} + f:intervalSeconds: {} + f:maxSurge: {} + f:maxUnavailable: {} + f:timeoutSeconds: {} + f:updatePeriodSeconds: {} + f:type: {} + f:template: + .: {} + f:metadata: + .: {} + f:annotations: + .: {} + f:openshift.io/generated-by: {} + f:creationTimestamp: {} + f:labels: + .: {} + f:deploymentconfig: {} + f:spec: + .: {} + f:containers: + .: {} + k:{"name":"quotesapi"}: + .: {} + f:env: + .: {} + k:{"name":"DATABASE_NAME"}: + .: {} + f:name: {} + f:value: {} + k:{"name":"DATABASE_PASSWORD"}: + .: {} + f:name: {} + f:value: {} + k:{"name":"DATABASE_SERVICE_NAME"}: + .: {} + f:name: {} + f:value: {} + k:{"name":"DATABASE_USER"}: + .: {} + f:name: {} + f:value: {} + f:imagePullPolicy: {} + f:name: {} + f:ports: + .: {} + k:{"containerPort":8080,"protocol":"TCP"}: + .: {} + f:containerPort: {} + f:protocol: {} + k:{"containerPort":8443,"protocol":"TCP"}: + .: {} + f:containerPort: {} + f:protocol: {} + f:resources: {} + f:terminationMessagePath: {} + f:terminationMessagePolicy: {} + f:dnsPolicy: {} + f:restartPolicy: {} + f:schedulerName: {} + f:securityContext: {} + f:terminationGracePeriodSeconds: {} + manager: oc + operation: Update + time: "2021-07-07T13:42:16Z" + - apiVersion: apps.openshift.io/v1 + fieldsType: FieldsV1 + fieldsV1: + f:spec: + f:template: + f:spec: + f:containers: + k:{"name":"quotesapi"}: + f:image: {} + f:triggers: {} + f:status: + f:availableReplicas: {} + f:conditions: + .: {} + k:{"type":"Available"}: + .: {} + f:lastTransitionTime: {} + f:lastUpdateTime: {} + f:message: {} + f:status: {} + f:type: {} + k:{"type":"Progressing"}: + .: {} + f:lastTransitionTime: {} + f:lastUpdateTime: {} + f:message: {} + f:reason: {} + f:status: {} + f:type: {} + f:details: + .: {} + f:causes: {} + f:message: {} + f:latestVersion: {} + f:observedGeneration: {} + f:readyReplicas: {} + f:replicas: {} + f:unavailableReplicas: {} + f:updatedReplicas: {} + manager: openshift-controller-manager + operation: Update + time: "2021-07-07T13:42:57Z" + name: quotesapi + namespace: zqjsga-quotes-dev + resourceVersion: "80364062" + selfLink: /apis/apps.openshift.io/v1/namespaces/zqjsga-quotes-dev/deploymentconfigs/quotesapi + uid: 7f381c32-7b5b-4b5c-83ef-b0ec0bf4f35e + spec: + replicas: 1 + revisionHistoryLimit: 10 + selector: + deploymentconfig: quotesapi + strategy: + activeDeadlineSeconds: 21600 + resources: {} + rollingParams: + intervalSeconds: 1 + maxSurge: 25% + maxUnavailable: 25% + timeoutSeconds: 600 + updatePeriodSeconds: 1 + type: Rolling + template: + metadata: + annotations: + openshift.io/generated-by: OpenShiftNewApp + creationTimestamp: null + labels: + deploymentconfig: quotesapi + spec: + containers: + - env: + - name: DATABASE_NAME + value: quotesdb + - name: DATABASE_PASSWORD + value: redhat + - name: DATABASE_SERVICE_NAME + value: quotesdb + - name: DATABASE_USER + value: quoteapp + image: image-registry.openshift-image-registry.svc:5000/zqjsga-quotes-dev/quotesapi@sha256:680b28722da34dc9a3749f9055877291d7613f576926b253626b8056db6934e9 + imagePullPolicy: Always + name: quotesapi + ports: + - containerPort: 8080 + protocol: TCP + - containerPort: 8443 + protocol: TCP + resources: {} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + test: false + triggers: + - type: ConfigChange + - imageChangeParams: + automatic: true + containerNames: + - quotesapi + from: + kind: ImageStreamTag + name: quotesapi:latest + namespace: zqjsga-quotes-dev + lastTriggeredImage: image-registry.openshift-image-registry.svc:5000/zqjsga-quotes-dev/quotesapi@sha256:680b28722da34dc9a3749f9055877291d7613f576926b253626b8056db6934e9 + type: ImageChange + status: + availableReplicas: 1 + conditions: + - lastTransitionTime: "2021-07-07T13:42:57Z" + lastUpdateTime: "2021-07-07T13:42:57Z" + message: Deployment config has minimum availability. + status: "True" + type: Available + - lastTransitionTime: "2021-07-07T13:42:54Z" + lastUpdateTime: "2021-07-07T13:42:57Z" + message: replication controller "quotesapi-1" successfully rolled out + reason: NewReplicationControllerAvailable + status: "True" + type: Progressing + details: + causes: + - type: ConfigChange + message: config change + latestVersion: 1 + observedGeneration: 2 + readyReplicas: 1 + replicas: 1 + unavailableReplicas: 0 + updatedReplicas: 1 + - apiVersion: apps.openshift.io/v1 + kind: DeploymentConfig + metadata: + annotations: + openshift.io/generated-by: OpenShiftNewApp + creationTimestamp: "2021-07-07T13:42:06Z" + generation: 3 + labels: + app: quotesdb + app.kubernetes.io/component: quotesdb + app.kubernetes.io/instance: quotesdb + app.kubernetes.io/name: mysql + managedFields: + - apiVersion: apps.openshift.io/v1 + fieldsType: FieldsV1 + fieldsV1: + f:metadata: + f:annotations: + .: {} + f:openshift.io/generated-by: {} + f:labels: + .: {} + f:app: {} + f:app.kubernetes.io/component: {} + f:app.kubernetes.io/instance: {} + f:app.kubernetes.io/name: {} + f:spec: + f:replicas: {} + f:selector: + .: {} + f:deploymentconfig: {} + f:strategy: + f:activeDeadlineSeconds: {} + f:rollingParams: + .: {} + f:intervalSeconds: {} + f:maxSurge: {} + f:maxUnavailable: {} + f:timeoutSeconds: {} + f:updatePeriodSeconds: {} + f:type: {} + f:template: + .: {} + f:metadata: + .: {} + f:annotations: + .: {} + f:openshift.io/generated-by: {} + f:creationTimestamp: {} + f:labels: + .: {} + f:deploymentconfig: {} + f:spec: + .: {} + f:containers: + .: {} + k:{"name":"quotesdb"}: + .: {} + f:env: + .: {} + k:{"name":"MYSQL_DATABASE"}: + .: {} + f:name: {} + f:value: {} + k:{"name":"MYSQL_PASSWORD"}: + .: {} + f:name: {} + f:value: {} + k:{"name":"MYSQL_USER"}: + .: {} + f:name: {} + f:value: {} + f:imagePullPolicy: {} + f:name: {} + f:ports: + .: {} + k:{"containerPort":3306,"protocol":"TCP"}: + .: {} + f:containerPort: {} + f:protocol: {} + f:resources: {} + f:terminationMessagePath: {} + f:terminationMessagePolicy: {} + f:dnsPolicy: {} + f:restartPolicy: {} + f:schedulerName: {} + f:securityContext: {} + f:terminationGracePeriodSeconds: {} + f:volumes: + .: {} + k:{"name":"quotesdb-volume-1"}: + .: {} + f:name: {} + f:persistentVolumeClaim: + .: {} + f:claimName: {} + manager: oc + operation: Update + time: "2021-07-07T13:42:07Z" + - apiVersion: apps.openshift.io/v1 + fieldsType: FieldsV1 + fieldsV1: + f:spec: + f:template: + f:spec: + f:containers: + k:{"name":"quotesdb"}: + f:image: {} + f:triggers: {} + f:status: + f:availableReplicas: {} + f:conditions: + .: {} + k:{"type":"Available"}: + .: {} + f:lastTransitionTime: {} + f:lastUpdateTime: {} + f:message: {} + f:status: {} + f:type: {} + k:{"type":"Progressing"}: + .: {} + f:lastTransitionTime: {} + f:lastUpdateTime: {} + f:message: {} + f:reason: {} + f:status: {} + f:type: {} + f:details: + .: {} + f:causes: {} + f:message: {} + f:latestVersion: {} + f:observedGeneration: {} + f:readyReplicas: {} + f:replicas: {} + f:unavailableReplicas: {} + f:updatedReplicas: {} + manager: openshift-controller-manager + operation: Update + time: "2021-07-07T13:42:15Z" + name: quotesdb + namespace: zqjsga-quotes-dev + resourceVersion: "80363661" + selfLink: /apis/apps.openshift.io/v1/namespaces/zqjsga-quotes-dev/deploymentconfigs/quotesdb + uid: 14d73674-2626-4f0f-ac65-683b72e62acd + spec: + replicas: 1 + revisionHistoryLimit: 10 + selector: + deploymentconfig: quotesdb + strategy: + activeDeadlineSeconds: 21600 + resources: {} + rollingParams: + intervalSeconds: 1 + maxSurge: 25% + maxUnavailable: 25% + timeoutSeconds: 600 + updatePeriodSeconds: 1 + type: Rolling + template: + metadata: + annotations: + openshift.io/generated-by: OpenShiftNewApp + creationTimestamp: null + labels: + deploymentconfig: quotesdb + spec: + containers: + - env: + - name: MYSQL_DATABASE + value: quotesdb + - name: MYSQL_PASSWORD + value: redhat + - name: MYSQL_USER + value: quoteapp + image: image-registry.openshift-image-registry.svc:5000/openshift/mysql@sha256:9a781abe7581cc141e14a7e404ec34125b3e89c008b14f4e7b41e094fd3049fe + imagePullPolicy: IfNotPresent + name: quotesdb + ports: + - containerPort: 3306 + protocol: TCP + resources: {} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: quotesdb-volume-1 + persistentVolumeClaim: + claimName: quotesdb-claim + test: false + triggers: + - type: ConfigChange + - imageChangeParams: + automatic: true + containerNames: + - quotesdb + from: + kind: ImageStreamTag + name: mysql:5.7 + namespace: openshift + lastTriggeredImage: image-registry.openshift-image-registry.svc:5000/openshift/mysql@sha256:9a781abe7581cc141e14a7e404ec34125b3e89c008b14f4e7b41e094fd3049fe + type: ImageChange + status: + availableReplicas: 1 + conditions: + - lastTransitionTime: "2021-07-07T13:42:14Z" + lastUpdateTime: "2021-07-07T13:42:14Z" + message: Deployment config has minimum availability. + status: "True" + type: Available + - lastTransitionTime: "2021-07-07T13:42:15Z" + lastUpdateTime: "2021-07-07T13:42:15Z" + message: replication controller "quotesdb-1" successfully rolled out + reason: NewReplicationControllerAvailable + status: "True" + type: Progressing + details: + causes: + - type: ConfigChange + message: config change + latestVersion: 1 + observedGeneration: 3 + readyReplicas: 1 + replicas: 1 + unavailableReplicas: 0 + updatedReplicas: 1 +kind: List +metadata: + resourceVersion: "" + selfLink: "" \ No newline at end of file diff --git a/src/test/resources/dc.yaml_cleaned b/src/test/resources/dc.yaml_cleaned new file mode 100644 index 0000000..5b05ef9 --- /dev/null +++ b/src/test/resources/dc.yaml_cleaned @@ -0,0 +1,138 @@ +--- +apiVersion: "v1" +items: +- apiVersion: "apps.openshift.io/v1" + kind: "DeploymentConfig" + metadata: + annotations: {} + generation: 2 + labels: + app: "quotesapi" + name: "quotesapi" + spec: + replicas: 1 + revisionHistoryLimit: 10 + selector: + deploymentconfig: "quotesapi" + strategy: + activeDeadlineSeconds: 21600 + resources: {} + rollingParams: + intervalSeconds: 1 + maxSurge: "25%" + maxUnavailable: "25%" + timeoutSeconds: 600 + updatePeriodSeconds: 1 + type: "Rolling" + template: + metadata: + annotations: {} + labels: + deploymentconfig: "quotesapi" + spec: + containers: + - env: + - name: "DATABASE_NAME" + value: "quotesdb" + - name: "DATABASE_PASSWORD" + value: "redhat" + - name: "DATABASE_SERVICE_NAME" + value: "quotesdb" + - name: "DATABASE_USER" + value: "quoteapp" + imagePullPolicy: "Always" + name: "quotesapi" + ports: + - containerPort: 8080 + protocol: "TCP" + - containerPort: 8443 + protocol: "TCP" + resources: {} + terminationMessagePath: "/dev/termination-log" + terminationMessagePolicy: "File" + dnsPolicy: "ClusterFirst" + restartPolicy: "Always" + schedulerName: "default-scheduler" + securityContext: {} + terminationGracePeriodSeconds: 30 + test: false + triggers: + - type: "ConfigChange" + - imageChangeParams: + automatic: true + containerNames: + - "quotesapi" + from: + kind: "ImageStreamTag" + name: "quotesapi:latest" + type: "ImageChange" +- apiVersion: "apps.openshift.io/v1" + kind: "DeploymentConfig" + metadata: + annotations: {} + generation: 3 + labels: + app: "quotesdb" + name: "quotesdb" + spec: + replicas: 1 + revisionHistoryLimit: 10 + selector: + deploymentconfig: "quotesdb" + strategy: + activeDeadlineSeconds: 21600 + resources: {} + rollingParams: + intervalSeconds: 1 + maxSurge: "25%" + maxUnavailable: "25%" + timeoutSeconds: 600 + updatePeriodSeconds: 1 + type: "Rolling" + template: + metadata: + annotations: {} + labels: + deploymentconfig: "quotesdb" + spec: + containers: + - env: + - name: "MYSQL_DATABASE" + value: "quotesdb" + - name: "MYSQL_PASSWORD" + value: "redhat" + - name: "MYSQL_USER" + value: "quoteapp" + imagePullPolicy: "IfNotPresent" + name: "quotesdb" + ports: + - containerPort: 3306 + protocol: "TCP" + resources: {} + terminationMessagePath: "/dev/termination-log" + terminationMessagePolicy: "File" + dnsPolicy: "ClusterFirst" + restartPolicy: "Always" + schedulerName: "default-scheduler" + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: "quotesdb-volume-1" + persistentVolumeClaim: + claimName: "quotesdb-claim" + test: false + triggers: + - type: "ConfigChange" + - imageChangeParams: + automatic: true + containerNames: + - "quotesdb" + from: + kind: "ImageStreamTag" + name: "mysql:5.7" + namespace: "openshift" + type: "ImageChange" +kind: "List" +metadata: + resourceVersion: "" + selfLink: "" diff --git a/src/test/resources/dc.yaml_cleaned_orig b/src/test/resources/dc.yaml_cleaned_orig new file mode 100644 index 0000000..7aba2b7 --- /dev/null +++ b/src/test/resources/dc.yaml_cleaned_orig @@ -0,0 +1,130 @@ +--- +apiVersion: "v1" +items: +- apiVersion: "apps.openshift.io/v1" + kind: "DeploymentConfig" + metadata: + labels: + app: "quotesapi" + name: "quotesapi" + spec: + replicas: 1 + revisionHistoryLimit: 10 + selector: + deploymentconfig: "quotesapi" + strategy: + activeDeadlineSeconds: 21600 + resources: {} + rollingParams: + intervalSeconds: 1 + maxSurge: "25%" + maxUnavailable: "25%" + timeoutSeconds: 600 + updatePeriodSeconds: 1 + type: "Rolling" + template: + metadata: + annotations: {} + labels: + deploymentconfig: "quotesapi" + spec: + containers: + - env: + - name: "DATABASE_NAME" + value: "quotesdb" + - name: "DATABASE_PASSWORD" + value: "redhat" + - name: "DATABASE_SERVICE_NAME" + value: "quotesdb" + - name: "DATABASE_USER" + value: "quoteapp" + imagePullPolicy: "Always" + name: "quotesapi" + ports: + - containerPort: 8080 + protocol: "TCP" + - containerPort: 8443 + protocol: "TCP" + resources: {} + terminationMessagePath: "/dev/termination-log" + terminationMessagePolicy: "File" + dnsPolicy: "ClusterFirst" + restartPolicy: "Always" + schedulerName: "default-scheduler" + securityContext: {} + terminationGracePeriodSeconds: 30 + test: false + triggers: + - type: "ConfigChange" + - imageChangeParams: + automatic: true + containerNames: + - "quotesapi" + from: + kind: "ImageStreamTag" + name: "quotesapi:latest" + type: "ImageChange" +- apiVersion: "apps.openshift.io/v1" + kind: "DeploymentConfig" + metadata: + labels: + app: "quotesdb" + name: "quotesdb" + spec: + replicas: 1 + revisionHistoryLimit: 10 + selector: + deploymentconfig: "quotesdb" + strategy: + activeDeadlineSeconds: 21600 + resources: {} + rollingParams: + intervalSeconds: 1 + maxSurge: "25%" + maxUnavailable: "25%" + timeoutSeconds: 600 + updatePeriodSeconds: 1 + type: "Rolling" + template: + metadata: + annotations: {} + labels: + deploymentconfig: "quotesdb" + spec: + containers: + - env: + - name: "MYSQL_DATABASE" + value: "quotesdb" + - name: "MYSQL_PASSWORD" + value: "redhat" + - name: "MYSQL_USER" + value: "quoteapp" + imagePullPolicy: "IfNotPresent" + name: "quotesdb" + ports: + - containerPort: 3306 + protocol: "TCP" + resources: {} + terminationMessagePath: "/dev/termination-log" + terminationMessagePolicy: "File" + dnsPolicy: "ClusterFirst" + restartPolicy: "Always" + schedulerName: "default-scheduler" + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: "quotesdb-volume-1" + persistentVolumeClaim: + claimName: "quotesdb-claim" + test: false + triggers: + - type: "ConfigChange" + - imageChangeParams: + automatic: true + containerNames: + - "quotesdb" + from: + kind: "ImageStreamTag" + name: "mysql:5.7" + namespace: "openshift" + type: "ImageChange" diff --git a/src/test/resources/is.yaml b/src/test/resources/is.yaml new file mode 100644 index 0000000..f6242ba --- /dev/null +++ b/src/test/resources/is.yaml @@ -0,0 +1,86 @@ +apiVersion: v1 +items: + - apiVersion: image.openshift.io/v1 + kind: ImageStream + metadata: + annotations: + openshift.io/generated-by: OpenShiftNewApp + creationTimestamp: "2021-07-07T13:42:16Z" + generation: 1 + labels: + app: quotesapi + app.kubernetes.io/component: quotesapi + app.kubernetes.io/instance: quotesapi + managedFields: + - apiVersion: image.openshift.io/v1 + fieldsType: FieldsV1 + fieldsV1: + f:metadata: + f:annotations: + .: {} + f:openshift.io/generated-by: {} + f:labels: + .: {} + f:app: {} + f:app.kubernetes.io/component: {} + f:app.kubernetes.io/instance: {} + manager: oc + operation: Update + time: "2021-07-07T13:42:16Z" + name: quotesapi + namespace: zqjsga-quotes-dev + resourceVersion: "80363950" + selfLink: /apis/image.openshift.io/v1/namespaces/zqjsga-quotes-dev/imagestreams/quotesapi + uid: 93275b73-9ccd-437d-8a7c-ab4c18824ea5 + spec: + lookupPolicy: + local: false + status: + dockerImageRepository: image-registry.openshift-image-registry.svc:5000/zqjsga-quotes-dev/quotesapi + publicDockerImageRepository: default-route-openshift-image-registry.apps.eu45.prod.nextcle.com/zqjsga-quotes-dev/quotesapi + tags: + - items: + - created: "2021-07-07T13:42:50Z" + dockerImageReference: image-registry.openshift-image-registry.svc:5000/zqjsga-quotes-dev/quotesapi@sha256:680b28722da34dc9a3749f9055877291d7613f576926b253626b8056db6934e9 + generation: 1 + image: sha256:680b28722da34dc9a3749f9055877291d7613f576926b253626b8056db6934e9 + tag: latest + - apiVersion: image.openshift.io/v1 + kind: ImageStream + metadata: + annotations: + openshift.io/image.dockerRepositoryCheck: "2021-07-07T13:42:07Z" + creationTimestamp: "2021-07-07T13:42:06Z" + generation: 2 + name: quotesdb + namespace: zqjsga-quotes-dev + resourceVersion: "80363561" + selfLink: /apis/image.openshift.io/v1/namespaces/zqjsga-quotes-dev/imagestreams/quotesdb + uid: 7d8a7e6a-4254-4e9b-bbbf-63244dbf9304 + spec: + lookupPolicy: + local: false + tags: + - annotations: null + from: + kind: DockerImage + name: image-registry.openshift-image-registry.svc:5000/openshift/mysql:5.7 + generation: 2 + importPolicy: {} + name: "5.7" + referencePolicy: + type: Source + status: + dockerImageRepository: image-registry.openshift-image-registry.svc:5000/zqjsga-quotes-dev/quotesdb + publicDockerImageRepository: default-route-openshift-image-registry.apps.eu45.prod.nextcle.com/zqjsga-quotes-dev/quotesdb + tags: + - items: + - created: "2021-07-07T13:42:07Z" + dockerImageReference: image-registry.openshift-image-registry.svc:5000/openshift/mysql@sha256:9a781abe7581cc141e14a7e404ec34125b3e89c008b14f4e7b41e094fd3049fe + generation: 2 + image: sha256:9a781abe7581cc141e14a7e404ec34125b3e89c008b14f4e7b41e094fd3049fe + tag: "5.7" +kind: List +metadata: + resourceVersion: "" + selfLink: "" diff --git a/src/test/resources/svc.yaml b/src/test/resources/svc.yaml new file mode 100644 index 0000000..785bf18 --- /dev/null +++ b/src/test/resources/svc.yaml @@ -0,0 +1,134 @@ +apiVersion: v1 +items: + - apiVersion: v1 + kind: Service + metadata: + annotations: + openshift.io/generated-by: OpenShiftNewApp + creationTimestamp: "2021-07-07T13:42:16Z" + labels: + app: quotesapi + app.kubernetes.io/component: quotesapi + app.kubernetes.io/instance: quotesapi + managedFields: + - apiVersion: v1 + fieldsType: FieldsV1 + fieldsV1: + f:metadata: + f:annotations: + .: {} + f:openshift.io/generated-by: {} + f:labels: + .: {} + f:app: {} + f:app.kubernetes.io/component: {} + f:app.kubernetes.io/instance: {} + f:spec: + f:ports: + .: {} + k:{"port":8080,"protocol":"TCP"}: + .: {} + f:name: {} + f:port: {} + f:protocol: {} + f:targetPort: {} + k:{"port":8443,"protocol":"TCP"}: + .: {} + f:name: {} + f:port: {} + f:protocol: {} + f:targetPort: {} + f:selector: + .: {} + f:deploymentconfig: {} + f:sessionAffinity: {} + f:type: {} + manager: oc + operation: Update + time: "2021-07-07T13:42:16Z" + name: quotesapi + namespace: zqjsga-quotes-dev + resourceVersion: "80363671" + selfLink: /api/v1/namespaces/zqjsga-quotes-dev/services/quotesapi + uid: 79787337-8ab1-4427-bca3-615ea74d8322 + spec: + clusterIP: 172.30.129.174 + ports: + - name: 8080-tcp + port: 8080 + protocol: TCP + targetPort: 8080 + - name: 8443-tcp + port: 8443 + protocol: TCP + targetPort: 8443 + selector: + deploymentconfig: quotesapi + sessionAffinity: None + type: ClusterIP + status: + loadBalancer: {} + - apiVersion: v1 + kind: Service + metadata: + annotations: + openshift.io/generated-by: OpenShiftNewApp + creationTimestamp: "2021-07-07T13:42:06Z" + labels: + app: quotesdb + app.kubernetes.io/component: quotesdb + app.kubernetes.io/instance: quotesdb + app.kubernetes.io/name: mysql + managedFields: + - apiVersion: v1 + fieldsType: FieldsV1 + fieldsV1: + f:metadata: + f:annotations: + .: {} + f:openshift.io/generated-by: {} + f:labels: + .: {} + f:app: {} + f:app.kubernetes.io/component: {} + f:app.kubernetes.io/instance: {} + f:app.kubernetes.io/name: {} + f:spec: + f:ports: + .: {} + k:{"port":3306,"protocol":"TCP"}: + .: {} + f:name: {} + f:port: {} + f:protocol: {} + f:targetPort: {} + f:selector: + .: {} + f:deploymentconfig: {} + f:sessionAffinity: {} + f:type: {} + manager: oc + operation: Update + time: "2021-07-07T13:42:06Z" + name: quotesdb + namespace: zqjsga-quotes-dev + resourceVersion: "80363551" + selfLink: /api/v1/namespaces/zqjsga-quotes-dev/services/quotesdb + uid: cf3fbd0a-aa1e-4f4e-b1c3-193713867475 + spec: + clusterIP: 172.30.126.53 + ports: + - name: 3306-tcp + port: 3306 + protocol: TCP + targetPort: 3306 + selector: + deploymentconfig: quotesdb + sessionAffinity: None + type: ClusterIP + status: + loadBalancer: {} +kind: List +metadata: + resourceVersion: "" + selfLink: "" \ No newline at end of file