diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/SpecialResourcesDependentIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/SpecialResourcesDependentIT.java new file mode 100644 index 0000000000..a050417254 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/SpecialResourcesDependentIT.java @@ -0,0 +1,62 @@ +package io.javaoperatorsdk.operator; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.fabric8.kubernetes.api.model.ServiceAccount; +import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension; +import io.javaoperatorsdk.operator.sample.specialresourcesdependent.SpecialResourceCustomResource; +import io.javaoperatorsdk.operator.sample.specialresourcesdependent.SpecialResourceSpec; +import io.javaoperatorsdk.operator.sample.specialresourcesdependent.SpecialResourceTestReconciler; + +import static io.javaoperatorsdk.operator.sample.specialresourcesdependent.SpecialResourceSpec.CHANGED_VALUE; +import static io.javaoperatorsdk.operator.sample.specialresourcesdependent.SpecialResourceSpec.INITIAL_VALUE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +/* + * Test for resources that are somehow special, currently mostly to cover the approach to handle + * resources without spec. Not all the resources added here. + */ +public class SpecialResourcesDependentIT { + + public static final String RESOURCE_NAME = "test1"; + + @RegisterExtension + LocallyRunOperatorExtension extension = + LocallyRunOperatorExtension.builder().withReconciler(new SpecialResourceTestReconciler()) + .build(); + + @Test + void specialCRUDReconciler() { + var resource = extension.create(testResource()); + + await().untilAsserted(() -> { + var sa = extension.get(ServiceAccount.class, RESOURCE_NAME); + assertThat(sa).isNotNull(); + assertThat(sa.getAutomountServiceAccountToken()).isTrue(); + }); + + resource.getSpec().setValue(CHANGED_VALUE); + extension.replace(resource); + + await().untilAsserted(() -> { + var sa = extension.get(ServiceAccount.class, RESOURCE_NAME); + assertThat(sa).isNotNull(); + assertThat(sa.getAutomountServiceAccountToken()).isFalse(); + }); + + } + + SpecialResourceCustomResource testResource() { + SpecialResourceCustomResource res = new SpecialResourceCustomResource(); + res.setMetadata(new ObjectMetaBuilder() + .withName(RESOURCE_NAME) + .build()); + res.setSpec(new SpecialResourceSpec()); + res.getSpec().setValue(INITIAL_VALUE); + return res; + } + +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/specialresourcesdependent/ServiceAccountDependentResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/specialresourcesdependent/ServiceAccountDependentResource.java new file mode 100644 index 0000000000..6ab5695a84 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/specialresourcesdependent/ServiceAccountDependentResource.java @@ -0,0 +1,32 @@ +package io.javaoperatorsdk.operator.sample.specialresourcesdependent; + +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.fabric8.kubernetes.api.model.ServiceAccount; +import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; + +import static io.javaoperatorsdk.operator.sample.specialresourcesdependent.SpecialResourceSpec.INITIAL_VALUE; + +@KubernetesDependent +public class ServiceAccountDependentResource extends + CRUDKubernetesDependentResource { + + public ServiceAccountDependentResource() { + super(ServiceAccount.class); + } + + @Override + protected ServiceAccount desired(SpecialResourceCustomResource primary, + Context context) { + ServiceAccount res = new ServiceAccount(); + res.setMetadata(new ObjectMetaBuilder() + .withName(primary.getMetadata().getName()) + .withNamespace(primary.getMetadata().getNamespace()) + .build()); + res.setAutomountServiceAccountToken(INITIAL_VALUE.equals(primary.getSpec().getValue())); + + return res; + } + +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/specialresourcesdependent/SpecialResourceCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/specialresourcesdependent/SpecialResourceCustomResource.java new file mode 100644 index 0000000000..89ed0ca06e --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/specialresourcesdependent/SpecialResourceCustomResource.java @@ -0,0 +1,14 @@ +package io.javaoperatorsdk.operator.sample.specialresourcesdependent; + +import io.fabric8.kubernetes.api.model.Namespaced; +import io.fabric8.kubernetes.client.CustomResource; +import io.fabric8.kubernetes.model.annotation.Group; +import io.fabric8.kubernetes.model.annotation.ShortNames; +import io.fabric8.kubernetes.model.annotation.Version; + +@Group("sample.javaoperatorsdk") +@Version("v1") +@ShortNames("srd") +public class SpecialResourceCustomResource extends CustomResource + implements Namespaced { +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/specialresourcesdependent/SpecialResourceSpec.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/specialresourcesdependent/SpecialResourceSpec.java new file mode 100644 index 0000000000..69386d72dc --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/specialresourcesdependent/SpecialResourceSpec.java @@ -0,0 +1,18 @@ +package io.javaoperatorsdk.operator.sample.specialresourcesdependent; + +public class SpecialResourceSpec { + + public static final String INITIAL_VALUE = "initial_val"; + public static final String CHANGED_VALUE = "changed_val"; + + private String value; + + public String getValue() { + return value; + } + + public SpecialResourceSpec setValue(String value) { + this.value = value; + return this; + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/specialresourcesdependent/SpecialResourceTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/specialresourcesdependent/SpecialResourceTestReconciler.java new file mode 100644 index 0000000000..5fa7d778b3 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/specialresourcesdependent/SpecialResourceTestReconciler.java @@ -0,0 +1,32 @@ +package io.javaoperatorsdk.operator.sample.specialresourcesdependent; + +import java.util.concurrent.atomic.AtomicInteger; + +import io.javaoperatorsdk.operator.api.reconciler.*; +import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; +import io.javaoperatorsdk.operator.support.TestExecutionInfoProvider; + +@ControllerConfiguration( + namespaces = Constants.WATCH_CURRENT_NAMESPACE, + dependents = { + @Dependent(type = ServiceAccountDependentResource.class), + }) +public class SpecialResourceTestReconciler + implements Reconciler, + TestExecutionInfoProvider { + + private final AtomicInteger numberOfExecutions = new AtomicInteger(0); + + @Override + public UpdateControl reconcile( + SpecialResourceCustomResource resource, + Context context) { + numberOfExecutions.addAndGet(1); + return UpdateControl.noUpdate(); + } + + public int getNumberOfExecutions() { + return numberOfExecutions.get(); + } + +}