diff --git a/README.md b/README.md index 402e3fb..ff84fdd 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,9 @@ In other words, it also allows you to write **workflows** over resources in a ** ## Contact Us -Either in the discussion section here on GitHub or at [Kubernetes Slack Operator Channel](https://kubernetes.slack.com/archives/CAW0GV7A5). +Either in the discussion section here on GitHub or at [Kubernetes Slack Operator Channel](https://kubernetes.slack.com/archives/CAW0GV7A5). While +in "object" form only placeholder substitutions are possible, in string template you can use all the +features of qute. ## Quick Introduction @@ -61,6 +63,8 @@ spec: parent: apiVersion: glueoperator.sample/v1 # watches all the custom resource of type WebPage kind: WebPage + statusTemplate: | # update the status of the custom resource at the end of reconciliation + observedGeneration: {parent.metadata.generation} childResources: - name: htmlconfigmap resource: diff --git a/docs/reference.md b/docs/reference.md index 3f158f2..02aae7e 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -6,6 +6,10 @@ of [Java Operator SDK](https://github.com/operator-framework/java-operator-sdk) Although it is limited only to Kubernetes resources it makes it very easy to use in language-independent (DependentResources in JOSDK are also covering external resources) way. +## Generic Notes + +- All templates (both object and string based) uses [Qute templating engine](https://quarkus.io/guides/qute-reference). + ## [Glue resource](https://github.com/java-operator-sdk/kubernetes-glue-operator/releases/latest/download/glues.glue-v1.yml) `Glue` is the heart of the operator. Note that `GlueOperator` controller just creates a new `Glue` with a related resource, @@ -57,6 +61,9 @@ The following attributes can be defined for a related resource: - **`apiVersion`** - Kubernetes resource API Version of the resource - **`kind`** - Kubernetes kind property of the resource - **`resourceNames`** - list of string of the resource names within the same namespace as `Glue`. +- **`statusPatch`** - template object used to update status of the related resource at the end of the reconciliation. See [sample](https://github.com/java-operator-sdk/kubernetes-glue-operator/blob/main/src/test/resources/glue/PatchRelatedStatus.yaml#L20-L21). + All the available resources (child, related) are provided. +- **`statusPatchTemplate`** - same as `statusPatch` just as a string template. See [sample](https://github.com/java-operator-sdk/kubernetes-glue-operator/blob/main/src/test/resources/glue/PatchRelatedStatusWithTemplate.yaml#L20-L21). ### Referencing other resources @@ -91,6 +98,9 @@ The specs of `GlueOperator` are almost identical to `Glue`, it just adds some ad - **`apiVersion`** and **`kind`** - of the target custom resources. - **`labelSelector`** - optional label selector for the target resources. - **`clusterScoped`** - optional boolean value, if the parent resource is cluster scoped. Default is `false`. + - **`status`** - template object to update status of the related resource at the end of the reconciliation. + All the available resources (parent, child, related) are available. + - **`statusTemplate`** - same as `status` just as a string template. - **`glueMetadata`** - optionally, you can customize the `Glue` resource created for each parent resource. This is especially important when the parent is a cluster scoped resource - in that case it is mandatory to set. Using this you can specify the **`name`** and **`namespace`** of the created `Glue`. diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/customresource/glue/RelatedResourceSpec.java b/src/main/java/io/javaoperatorsdk/operator/glue/customresource/glue/RelatedResourceSpec.java index 8b04101..ae8c208 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/customresource/glue/RelatedResourceSpec.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/customresource/glue/RelatedResourceSpec.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Objects; +import io.fabric8.crd.generator.annotation.PreserveUnknownFields; import io.fabric8.generator.annotation.Required; public class RelatedResourceSpec { @@ -19,6 +20,9 @@ public class RelatedResourceSpec { private boolean clusterScoped = Boolean.FALSE; private List resourceNames; + @PreserveUnknownFields + private Object statusPatch; + private String statusPatchTemplate; public String getApiVersion() { return apiVersion; @@ -73,14 +77,16 @@ public boolean equals(Object o) { return false; RelatedResourceSpec that = (RelatedResourceSpec) o; return clusterScoped == that.clusterScoped && Objects.equals(name, that.name) - && Objects.equals(apiVersion, that.apiVersion) && Objects.equals(kind, that.kind) - && Objects.equals(namespace, that.namespace) - && Objects.equals(resourceNames, that.resourceNames); + && Objects.equals(namespace, that.namespace) && Objects.equals(apiVersion, that.apiVersion) + && Objects.equals(kind, that.kind) && Objects.equals(resourceNames, that.resourceNames) + && Objects.equals(statusPatch, that.statusPatch) + && Objects.equals(statusPatchTemplate, that.statusPatchTemplate); } @Override public int hashCode() { - return Objects.hash(name, apiVersion, kind, clusterScoped, namespace, resourceNames); + return Objects.hash(name, namespace, apiVersion, kind, clusterScoped, resourceNames, + statusPatch, statusPatchTemplate); } public boolean isClusterScoped() { @@ -90,4 +96,20 @@ public boolean isClusterScoped() { public void setClusterScoped(boolean clusterScoped) { this.clusterScoped = clusterScoped; } + + public Object getStatusPatch() { + return statusPatch; + } + + public void setStatusPatch(Object statusPatch) { + this.statusPatch = statusPatch; + } + + public String getStatusPatchTemplate() { + return statusPatchTemplate; + } + + public void setStatusPatchTemplate(String statusPatchTemplate) { + this.statusPatchTemplate = statusPatchTemplate; + } } diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/customresource/operator/Parent.java b/src/main/java/io/javaoperatorsdk/operator/glue/customresource/operator/Parent.java index b8c110a..1e40b42 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/customresource/operator/Parent.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/customresource/operator/Parent.java @@ -2,6 +2,8 @@ import java.util.Objects; +import io.fabric8.crd.generator.annotation.PreserveUnknownFields; + public class Parent { private String apiVersion; @@ -9,6 +11,9 @@ public class Parent { private boolean clusterScoped = false; private String labelSelector; + @PreserveUnknownFields + private Object status; + private String statusTemplate; public Parent() {} @@ -51,6 +56,22 @@ public void setClusterScoped(boolean clusterScoped) { this.clusterScoped = clusterScoped; } + public Object getStatus() { + return status; + } + + public void setStatus(Object status) { + this.status = status; + } + + public String getStatusTemplate() { + return statusTemplate; + } + + public void setStatusTemplate(String statusTemplate) { + this.statusTemplate = statusTemplate; + } + @Override public boolean equals(Object o) { if (this == o) @@ -59,11 +80,13 @@ public boolean equals(Object o) { return false; Parent parent = (Parent) o; return clusterScoped == parent.clusterScoped && Objects.equals(apiVersion, parent.apiVersion) - && Objects.equals(kind, parent.kind) && Objects.equals(labelSelector, parent.labelSelector); + && Objects.equals(kind, parent.kind) && Objects.equals(labelSelector, parent.labelSelector) + && Objects.equals(status, parent.status) + && Objects.equals(statusTemplate, parent.statusTemplate); } @Override public int hashCode() { - return Objects.hash(apiVersion, kind, clusterScoped, labelSelector); + return Objects.hash(apiVersion, kind, clusterScoped, labelSelector, status, statusTemplate); } } diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/GlueReconciler.java b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/GlueReconciler.java index 3e88d67..fd292af 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/GlueReconciler.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/GlueReconciler.java @@ -10,6 +10,7 @@ import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.dsl.base.PatchContext; import io.fabric8.kubernetes.client.dsl.base.PatchType; +import io.fabric8.kubernetes.client.utils.Serialization; import io.javaoperatorsdk.operator.api.reconciler.*; import io.javaoperatorsdk.operator.glue.Utils; import io.javaoperatorsdk.operator.glue.conditions.JavaScripCondition; @@ -89,6 +90,7 @@ public UpdateControl reconcile(Glue primary, cleanupRemovedResourcesFromWorkflow(context, primary); informerRegister.deRegisterInformerOnResourceFlowChange(context, primary); result.throwAggregateExceptionIfErrorsPresent(); + patchRelatedResourcesStatus(context, primary); return UpdateControl.noUpdate(); } @@ -222,6 +224,35 @@ private GenericDependentResource createDependentResource(DependentResourceSpec s } } + // todo add workflow result? + private void patchRelatedResourcesStatus(Context context, + Glue primary) { + + var targetRelatedResources = primary.getSpec().getRelatedResources().stream() + .filter(r -> r.getStatusPatch() != null || r.getStatusPatchTemplate() != null) + .toList(); + + if (targetRelatedResources.isEmpty()) { + return; + } + var actualData = genericTemplateHandler.createDataWithResources(primary, context); + + targetRelatedResources.forEach(r -> { + var relatedResources = Utils.getRelatedResources(primary, r, context); + + var template = r.getStatusPatchTemplate() != null ? r.getStatusPatchTemplate() + : Serialization.asYaml(r.getStatusPatch()); + var resultTemplate = + genericTemplateHandler.processTemplate(actualData, template); + var statusObjectMap = GenericTemplateHandler.parseTemplateToMapObject(resultTemplate); + relatedResources.forEach((n, kr) -> { + kr.setAdditionalProperty("status", statusObjectMap); + context.getClient().resource(kr).patchStatus(); + }); + }); + + } + @SuppressWarnings({"rawtypes"}) private Condition toCondition(ConditionSpec condition) { if (condition instanceof ReadyConditionSpec readyConditionSpec) { diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/operator/GlueOperatorReconciler.java b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/operator/GlueOperatorReconciler.java index 965a91c..6c18137 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/operator/GlueOperatorReconciler.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/operator/GlueOperatorReconciler.java @@ -19,6 +19,7 @@ import io.javaoperatorsdk.operator.glue.customresource.glue.RelatedResourceSpec; import io.javaoperatorsdk.operator.glue.customresource.operator.GlueOperator; import io.javaoperatorsdk.operator.glue.customresource.operator.GlueOperatorSpec; +import io.javaoperatorsdk.operator.glue.customresource.operator.Parent; import io.javaoperatorsdk.operator.glue.customresource.operator.ResourceFlowOperatorStatus; import io.javaoperatorsdk.operator.glue.reconciler.ValidationAndErrorHandler; import io.javaoperatorsdk.operator.glue.reconciler.glue.GlueReconciler; @@ -103,7 +104,6 @@ private Glue createGlue(GenericKubernetesResource targetParentResource, ObjectMeta glueMetadata = glueMetadata(glueOperator, targetParentResource); - glue.setMetadata(glueMetadata); glue.setSpec(toWorkflowSpec(glueOperator.getSpec())); @@ -112,6 +112,16 @@ private Glue createGlue(GenericKubernetesResource targetParentResource, } var parent = glueOperator.getSpec().getParent(); + RelatedResourceSpec parentRelatedSpec = + parentRelatedResourceSpec(targetParentResource, glueOperator, parent); + + glue.getSpec().getRelatedResources().add(parentRelatedSpec); + glue.addOwnerReference(targetParentResource); + return glue; + } + + private static RelatedResourceSpec parentRelatedResourceSpec( + GenericKubernetesResource targetParentResource, GlueOperator glueOperator, Parent parent) { RelatedResourceSpec parentRelatedSpec = new RelatedResourceSpec(); parentRelatedSpec.setName(PARENT_RELATED_RESOURCE_NAME); parentRelatedSpec.setApiVersion(parent.getApiVersion()); @@ -119,10 +129,10 @@ private Glue createGlue(GenericKubernetesResource targetParentResource, parentRelatedSpec.setResourceNames(List.of(targetParentResource.getMetadata().getName())); parentRelatedSpec.setNamespace(targetParentResource.getMetadata().getNamespace()); parentRelatedSpec.setClusterScoped(glueOperator.getSpec().getParent().isClusterScoped()); - - glue.getSpec().getRelatedResources().add(parentRelatedSpec); - glue.addOwnerReference(targetParentResource); - return glue; + parentRelatedSpec + .setStatusPatchTemplate(glueOperator.getSpec().getParent().getStatusTemplate()); + parentRelatedSpec.setStatusPatch(glueOperator.getSpec().getParent().getStatus()); + return parentRelatedSpec; } private ObjectMeta glueMetadata(GlueOperator glueOperator, diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/templating/GenericTemplateHandler.java b/src/main/java/io/javaoperatorsdk/operator/glue/templating/GenericTemplateHandler.java index b7c77cc..c938aea 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/templating/GenericTemplateHandler.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/templating/GenericTemplateHandler.java @@ -4,6 +4,7 @@ import java.util.Map; import io.fabric8.kubernetes.api.model.GenericKubernetesResource; +import io.fabric8.kubernetes.client.utils.Serialization; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.glue.Utils; import io.javaoperatorsdk.operator.glue.customresource.glue.Glue; @@ -29,20 +30,26 @@ public String processTemplate(Map> data, String template) { public String processInputAndTemplate(Map data, String template) { - Map> res = new HashMap<>(); - data.forEach((key, value) -> res.put(key, - value == null ? null : objectMapper.convertValue(value, Map.class))); + Map> res = + genericKubernetesResourceDataToGenericData(data); return processTemplate(res, template); } public String processTemplate(String template, Glue primary, Context context) { - var data = createDataWithResources(primary, context); return processTemplate(data, template); } - private static Map> createDataWithResources(Glue primary, + private static Map> genericKubernetesResourceDataToGenericData( + Map data) { + Map> res = new HashMap<>(); + data.forEach((key, value) -> res.put(key, + value == null ? null : objectMapper.convertValue(value, Map.class))); + return res; + } + + public static Map> createDataWithResources(Glue primary, Context context) { Map> res = new HashMap<>(); var actualResourcesByName = Utils.getActualResourcesByNameInWorkflow(context, primary); @@ -55,4 +62,10 @@ public String processTemplate(String template, Glue primary, return res; } + + @SuppressWarnings("unchecked") + public static Map parseTemplateToMapObject(String template) { + return Serialization.unmarshal(template, Map.class); + } + } diff --git a/src/test/java/io/javaoperatorsdk/operator/glue/GlueTest.java b/src/test/java/io/javaoperatorsdk/operator/glue/GlueTest.java index 8c5e123..808171b 100644 --- a/src/test/java/io/javaoperatorsdk/operator/glue/GlueTest.java +++ b/src/test/java/io/javaoperatorsdk/operator/glue/GlueTest.java @@ -8,12 +8,15 @@ import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.ConfigMapBuilder; import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.fabric8.kubernetes.api.model.Secret; import io.fabric8.kubernetes.client.dsl.NonDeletingOperation; +import io.javaoperatorsdk.operator.glue.customresource.TestCustomResource; import io.javaoperatorsdk.operator.glue.customresource.glue.DependentResourceSpec; import io.javaoperatorsdk.operator.glue.customresource.glue.Glue; import io.javaoperatorsdk.operator.glue.reconciler.ValidationAndErrorHandler; @@ -324,6 +327,33 @@ void clusterScopedRelatedResource() { }); } + @ParameterizedTest + @ValueSource(strings = {"PatchRelatedStatus.yaml", "PatchRelatedStatusWithTemplate.yaml"}) + void pathRelatedResourceStatus(String glueFileName) { + TestUtils.applyTestCrd(client, TestCustomResource.class); + + var customResource = create(TestData.testCustomResource()); + var glue = createGlue("/glue/" + glueFileName); + + await().untilAsserted(() -> { + var cm = get(ConfigMap.class, "configmap1"); + assertThat(cm).isNotNull(); + var cr = get(TestCustomResource.class, "testcr1"); + assertThat(cr.getStatus()).isNotNull(); + assertThat(cr.getStatus().getValue()).isEqualTo(cm.getMetadata().getResourceVersion()); + }); + delete(glue); + await().timeout(TestUtils.GC_WAIT_TIMEOUT).untilAsserted(() -> { + var cm = get(ConfigMap.class, "configmap1"); + assertThat(cm).isNull(); + }); + delete(customResource); + await().untilAsserted(() -> { + var cr = get(TestCustomResource.class, "testcr1"); + assertThat(cr).isNull(); + }); + } + private List testWorkflowList(int num) { List res = new ArrayList<>(); IntStream.range(0, num).forEach(index -> { diff --git a/src/test/java/io/javaoperatorsdk/operator/glue/TestBase.java b/src/test/java/io/javaoperatorsdk/operator/glue/TestBase.java index db9b10f..06b02de 100644 --- a/src/test/java/io/javaoperatorsdk/operator/glue/TestBase.java +++ b/src/test/java/io/javaoperatorsdk/operator/glue/TestBase.java @@ -13,9 +13,11 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.dsl.NonDeletingOperation; import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil; +import io.javaoperatorsdk.operator.glue.customresource.glue.Glue; import jakarta.inject.Inject; +import static io.javaoperatorsdk.operator.glue.TestUtils.loadGlue; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; @@ -51,6 +53,10 @@ protected Namespace testNamespace(String name) { .build()).build(); } + protected Glue createGlue(String path) { + return create(loadGlue(path)); + } + protected T create(T resource) { return client.resource(resource).inNamespace(testNamespace).create(); } diff --git a/src/test/java/io/javaoperatorsdk/operator/glue/customresource/TestCustomResource.java b/src/test/java/io/javaoperatorsdk/operator/glue/customresource/TestCustomResource.java index bb661c2..fe72216 100644 --- a/src/test/java/io/javaoperatorsdk/operator/glue/customresource/TestCustomResource.java +++ b/src/test/java/io/javaoperatorsdk/operator/glue/customresource/TestCustomResource.java @@ -9,7 +9,8 @@ @Group(TestCustomResource.CR_GROUP) @Version("v1") @ShortNames("tcr") -public class TestCustomResource extends CustomResource +public class TestCustomResource + extends CustomResource implements Namespaced { public static final String CR_GROUP = "io.javaoperatorsdk.operator.glue"; diff --git a/src/test/java/io/javaoperatorsdk/operator/glue/customresource/TestCustomResourceStatus.java b/src/test/java/io/javaoperatorsdk/operator/glue/customresource/TestCustomResourceStatus.java new file mode 100644 index 0000000..28ecc02 --- /dev/null +++ b/src/test/java/io/javaoperatorsdk/operator/glue/customresource/TestCustomResourceStatus.java @@ -0,0 +1,17 @@ +package io.javaoperatorsdk.operator.glue.customresource; + + + +public class TestCustomResourceStatus { + + private String value; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageE2E.java b/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageE2E.java index 479c7f0..c4763ba 100644 --- a/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageE2E.java +++ b/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageE2E.java @@ -59,6 +59,9 @@ void testWebPageCRUDOperations() { assertThat(ingress).isNotNull(); }); + var wp = client.resources(WebPage.class).withName("webpage1").get(); + assertThat(wp.getStatus().getObservedGeneration()).isNotNull(); + client.resource(createdWebPage).delete(); await().timeout(TestUtils.GC_WAIT_TIMEOUT).untilAsserted(() -> { @@ -73,6 +76,7 @@ void testWebPageCRUDOperations() { assertThat(configMap).isNull(); assertThat(service).isNull(); assertThat(ingress).isNull(); + }); } diff --git a/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageSampleTest.java b/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageSampleTest.java index 9eee921..ebe61f9 100644 --- a/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageSampleTest.java +++ b/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageSampleTest.java @@ -53,9 +53,12 @@ void webPageCRUD() { await().untilAsserted(() -> { var ingress = get(Ingress.class, webPage.getMetadata().getName()); var configMap = get(ConfigMap.class, webPage.getMetadata().getName()); + var wp = get(WebPage.class, webPage.getMetadata().getName()); assertThat(configMap.getData().get("index.html")).contains("Hello World 2!"); assertThat(ingress).isNotNull(); + assertThat(wp.getStatus()).isNotNull(); + assertThat(wp.getStatus().getObservedGeneration()).isNotNull(); }); delete(webPage); diff --git a/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageStatus.java b/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageStatus.java index dad7837..30aec42 100644 --- a/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageStatus.java +++ b/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageStatus.java @@ -1,11 +1,15 @@ package io.javaoperatorsdk.operator.glue.sample.webpage; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -@JsonInclude(com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL) -@JsonPropertyOrder({}) -@JsonDeserialize(using = com.fasterxml.jackson.databind.JsonDeserializer.None.class) public class WebPageStatus { + + private Long observedGeneration; + + public Long getObservedGeneration() { + return observedGeneration; + } + + public void setObservedGeneration(Long observedGeneration) { + this.observedGeneration = observedGeneration; + } } diff --git a/src/test/resources/glue/PatchRelatedStatus.yaml b/src/test/resources/glue/PatchRelatedStatus.yaml new file mode 100644 index 0000000..c40cb6d --- /dev/null +++ b/src/test/resources/glue/PatchRelatedStatus.yaml @@ -0,0 +1,21 @@ +apiVersion: io.javaoperatorsdk.operator.glue/v1beta1 +kind: Glue +metadata: + name: related-resource-status-patch +spec: + childResources: + - name: configMap1 + resource: + apiVersion: v1 + kind: ConfigMap + metadata: + name: configmap1 + data: + key: "value" + relatedResources: + - name: related + apiVersion: "io.javaoperatorsdk.operator.glue/v1" + kind: TestCustomResource + resourceNames: ["testcr1"] + statusPatch: + value: "{configMap1.metadata.resourceVersion}" diff --git a/src/test/resources/glue/PatchRelatedStatusWithTemplate.yaml b/src/test/resources/glue/PatchRelatedStatusWithTemplate.yaml new file mode 100644 index 0000000..ac4c7e8 --- /dev/null +++ b/src/test/resources/glue/PatchRelatedStatusWithTemplate.yaml @@ -0,0 +1,21 @@ +apiVersion: io.javaoperatorsdk.operator.glue/v1beta1 +kind: Glue +metadata: + name: related-resource-status-patch +spec: + childResources: + - name: configMap1 + resource: + apiVersion: v1 + kind: ConfigMap + metadata: + name: configmap1 + data: + key: "value" + relatedResources: + - name: related + apiVersion: "io.javaoperatorsdk.operator.glue/v1" + kind: TestCustomResource + resourceNames: ["testcr1"] + statusPatchTemplate: | + value: "{configMap1.metadata.resourceVersion}" diff --git a/src/test/resources/sample/webpage/webpage.crd.yaml b/src/test/resources/sample/webpage/webpage.crd.yaml index a0025f3..8aeca13 100644 --- a/src/test/resources/sample/webpage/webpage.crd.yaml +++ b/src/test/resources/sample/webpage/webpage.crd.yaml @@ -24,6 +24,9 @@ spec: type: object status: type: object + properties: + observedGeneration: + type: integer type: object served: true storage: true diff --git a/src/test/resources/sample/webpage/webpage.operator.yaml b/src/test/resources/sample/webpage/webpage.operator.yaml index 87ef529..53606fe 100644 --- a/src/test/resources/sample/webpage/webpage.operator.yaml +++ b/src/test/resources/sample/webpage/webpage.operator.yaml @@ -6,6 +6,8 @@ spec: parent: apiVersion: glueoperator.sample/v1 kind: WebPage + statusTemplate: | + observedGeneration: {parent.metadata.generation} childResources: - name: htmlconfigmap resource: