diff --git a/src/main/java/io/csviri/operator/glue/reconciler/operator/GlueOperatorReconciler.java b/src/main/java/io/csviri/operator/glue/reconciler/operator/GlueOperatorReconciler.java index a3a440b..76bedde 100644 --- a/src/main/java/io/csviri/operator/glue/reconciler/operator/GlueOperatorReconciler.java +++ b/src/main/java/io/csviri/operator/glue/reconciler/operator/GlueOperatorReconciler.java @@ -53,7 +53,7 @@ public class GlueOperatorReconciler private Map defaultGlueLabels; - private InformerEventSource resourceFlowEventSource; + private InformerEventSource glueEventSource; @PostConstruct void init() { @@ -71,8 +71,9 @@ public UpdateControl reconcile(GlueOperator glueOperator, var targetCREventSource = getOrRegisterCustomResourceEventSource(glueOperator, context); targetCREventSource.list().forEach(cr -> { - var actualResourceFlow = resourceFlowEventSource - .get(new ResourceID(glueName(cr), cr.getMetadata().getNamespace())); + var actualResourceFlow = glueEventSource + .get(new ResourceID(glueName(cr.getMetadata().getName(), cr.getKind()), + cr.getMetadata().getNamespace())); var desiredResourceFlow = createGlue(cr, glueOperator); if (actualResourceFlow.isEmpty()) { context.getClient().resource(desiredResourceFlow).serverSideApply(); @@ -94,7 +95,8 @@ private Glue createGlue(GenericKubernetesResource targetParentResource, var glue = new Glue(); glue.setMetadata(new ObjectMetaBuilder() - .withName(glueName(targetParentResource)) + .withName( + glueName(targetParentResource.getMetadata().getName(), targetParentResource.getKind())) .withNamespace(targetParentResource.getMetadata().getNamespace()) .withLabels(Map.of(GLUE_LABEL_KEY, GLUE_LABEL_VALUE)) .build()); @@ -150,12 +152,12 @@ private InformerEventSource getOrRegist @Override public Map prepareEventSources( EventSourceContext eventSourceContext) { - resourceFlowEventSource = new InformerEventSource<>( + glueEventSource = new InformerEventSource<>( InformerConfiguration.from(Glue.class, eventSourceContext) .withLabelSelector(GLUE_LABEL_KEY + "=" + GLUE_LABEL_VALUE) .build(), eventSourceContext); - return EventSourceInitializer.nameEventSources(resourceFlowEventSource); + return EventSourceInitializer.nameEventSources(glueEventSource); } @Override @@ -176,8 +178,8 @@ public DeleteControl cleanup(GlueOperator glueOperator, return DeleteControl.defaultDelete(); } - private static String glueName(GenericKubernetesResource cr) { - return KubernetesResourceUtil.sanitizeName(cr.getMetadata().getName() + "-" + cr.getKind()); + public static String glueName(String name, String kind) { + return KubernetesResourceUtil.sanitizeName(name + "-" + kind); } private Map initDefaultLabelsToAddToGlue() { diff --git a/src/test/java/io/csviri/operator/glue/GlueLabelSelectorTest.java b/src/test/java/io/csviri/operator/glue/GlueLabelSelectorTest.java new file mode 100644 index 0000000..27728f1 --- /dev/null +++ b/src/test/java/io/csviri/operator/glue/GlueLabelSelectorTest.java @@ -0,0 +1,54 @@ +package io.csviri.operator.glue; + + +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import io.csviri.operator.glue.customresource.glue.Glue; +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.QuarkusTestProfile; +import io.quarkus.test.junit.TestProfile; + +import static io.csviri.operator.glue.TestUtils.INITIAL_RECONCILE_WAIT_TIMEOUT; +import static io.csviri.operator.glue.reconciler.glue.GlueReconciler.GLUE_RECONCILER_NAME; +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +@QuarkusTest +@TestProfile(GlueLabelSelectorTest.LabelSelectorTestProfile.class) +public class GlueLabelSelectorTest extends TestBase { + + + public static final String LABEL_KEY = "test-glue"; + public static final String LABEL_VALUE = "true"; + + @Test + void testLabelSelectorHandling() { + Glue glue = + TestUtils.loadResoureFlow("/glue/SimpleGlue.yaml"); + glue = create(glue); + + await().pollDelay(INITIAL_RECONCILE_WAIT_TIMEOUT).untilAsserted(() -> { + assertThat(get(ConfigMap.class, "simple-glue-configmap")).isNull(); + }); + + glue.getMetadata().getLabels().put(LABEL_KEY, LABEL_VALUE); + update(glue); + + await().untilAsserted(() -> { + assertThat(get(ConfigMap.class, "simple-glue-configmap")).isNotNull(); + }); + } + + public static class LabelSelectorTestProfile implements QuarkusTestProfile { + + @Override + public Map getConfigOverrides() { + return Map.of("quarkus.operator-sdk.controllers." + GLUE_RECONCILER_NAME + ".selector", + LABEL_KEY + "=" + LABEL_VALUE); + } + } + +} diff --git a/src/test/java/io/csviri/operator/glue/GlueOperatorLabelSelectorTest.java b/src/test/java/io/csviri/operator/glue/GlueOperatorLabelSelectorTest.java new file mode 100644 index 0000000..6ad918a --- /dev/null +++ b/src/test/java/io/csviri/operator/glue/GlueOperatorLabelSelectorTest.java @@ -0,0 +1,80 @@ +package io.csviri.operator.glue; + +import java.util.Map; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.csviri.operator.glue.customresource.TestCustomResource; +import io.csviri.operator.glue.customresource.TestCustomResource2; +import io.csviri.operator.glue.customresource.glue.Glue; +import io.csviri.operator.glue.reconciler.operator.GlueOperatorReconciler; +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.QuarkusTestProfile; +import io.quarkus.test.junit.TestProfile; + +import static io.csviri.operator.glue.TestUtils.INITIAL_RECONCILE_WAIT_TIMEOUT; +import static io.csviri.operator.glue.reconciler.glue.GlueReconciler.GLUE_RECONCILER_NAME; +import static io.csviri.operator.glue.reconciler.operator.GlueOperatorReconciler.GLUE_OPERATOR_RECONCILER_NAME; +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +@QuarkusTest +@TestProfile(GlueOperatorLabelSelectorTest.GlueOperatorLabelSelectorTestProfile.class) +public class GlueOperatorLabelSelectorTest extends TestBase { + + public static final String GLUE_OPERATOR_LABEL_KEY = "test-glue-operator"; + public static final String GLUE_LABEL_KEY = "test-glue"; + public static final String LABEL_VALUE = "true"; + + @BeforeEach + void applyCRD() { + TestUtils.applyTestCrd(client, TestCustomResource.class, TestCustomResource2.class); + } + + @Test + void testGlueOperatorLabelSelector() { + var go = create(TestUtils + .loadResourceFlowOperator("/glueoperator/SimpleGlueOperator.yaml")); + + var testCR = create(TestData.testCustomResource()); + + await().pollDelay(INITIAL_RECONCILE_WAIT_TIMEOUT).untilAsserted(() -> { + assertThat(get(ConfigMap.class, testCR.getMetadata().getName())).isNull(); + }); + + go.getMetadata().getLabels().put(GLUE_OPERATOR_LABEL_KEY, LABEL_VALUE); + update(go); + + await().untilAsserted(() -> { + assertThat(get(ConfigMap.class, testCR.getMetadata().getName())).isNotNull(); + var glue = get(Glue.class, GlueOperatorReconciler.glueName(testCR.getMetadata().getName(), + testCR.getKind())); + assertThat(glue).isNotNull(); + assertThat(glue.getMetadata().getLabels()).containsEntry(GLUE_LABEL_KEY, LABEL_VALUE); + }); + + // explicit cleanup, so there are no exception in the logs because of namespace marked for + // deletion + delete(testCR); + await().untilAsserted(() -> { + var glue = get(Glue.class, GlueOperatorReconciler.glueName(testCR.getMetadata().getName(), + testCR.getKind())); + assertThat(glue).isNull(); + }); + delete(go); + } + + public static class GlueOperatorLabelSelectorTestProfile implements QuarkusTestProfile { + + @Override + public Map getConfigOverrides() { + return Map.of("quarkus.operator-sdk.controllers." + GLUE_RECONCILER_NAME + ".selector", + GLUE_LABEL_KEY + "=" + LABEL_VALUE, + "quarkus.operator-sdk.controllers." + GLUE_OPERATOR_RECONCILER_NAME + ".selector", + GLUE_OPERATOR_LABEL_KEY + "=" + LABEL_VALUE); + } + } + +} diff --git a/src/test/java/io/csviri/operator/glue/GlueOperatorTest.java b/src/test/java/io/csviri/operator/glue/GlueOperatorTest.java index 1a8731f..fbd08ed 100644 --- a/src/test/java/io/csviri/operator/glue/GlueOperatorTest.java +++ b/src/test/java/io/csviri/operator/glue/GlueOperatorTest.java @@ -9,7 +9,6 @@ import io.csviri.operator.glue.customresource.TestCustomResource; import io.csviri.operator.glue.customresource.TestCustomResource2; -import io.csviri.operator.glue.customresource.TestCustomResourceSpec; import io.csviri.operator.glue.customresource.glue.DependentResourceSpec; import io.csviri.operator.glue.customresource.operator.GlueOperator; import io.csviri.operator.glue.customresource.operator.GlueOperatorSpec; @@ -19,6 +18,7 @@ import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.quarkus.test.junit.QuarkusTest; +import static io.csviri.operator.glue.TestData.*; import static io.csviri.operator.glue.TestUtils.GC_WAIT_TIMEOUT_SECOND; import static io.csviri.operator.glue.customresource.TestCustomResource.CR_GROUP; import static org.assertj.core.api.Assertions.assertThat; @@ -27,9 +27,7 @@ @QuarkusTest class GlueOperatorTest extends TestBase { - public static final String TEST_RESOURCE_VALUE = "val"; - public static final String TEST_RESOURCE_PREFIX = "testcr"; - public static final String TEST_RESOURCE2_PREFIX = "testcr2"; + @BeforeEach void applyCRD() { @@ -58,9 +56,9 @@ void smokeTest() { @Test void templating() { - var wo = TestUtils - .loadResourceFlowOperator("/glueoperator/Templating.yaml"); - create(wo); + create(TestUtils + .loadResourceFlowOperator("/glueoperator/SimpleGlueOperator.yaml")); + var cr = create(testCustomResource()); String initialValue = cr.getSpec().getValue(); String name = cr.getMetadata().getName(); @@ -164,29 +162,7 @@ void nonUniqueNameTest() { }); } - TestCustomResource testCustomResource() { - return testCustomResource(1); - } - TestCustomResource testCustomResource(int index) { - var res = new TestCustomResource(); - res.setMetadata(new ObjectMetaBuilder() - .withName(TEST_RESOURCE_PREFIX + index) - .build()); - res.setSpec(new TestCustomResourceSpec()); - res.getSpec().setValue(TEST_RESOURCE_VALUE + index); - return res; - } - - TestCustomResource2 testCustomResource2(int index) { - var res = new TestCustomResource2(); - res.setMetadata(new ObjectMetaBuilder() - .withName(TEST_RESOURCE2_PREFIX + index) - .build()); - res.setSpec(new TestCustomResourceSpec()); - res.getSpec().setValue(TEST_RESOURCE_VALUE + index); - return res; - } GlueOperator testWorkflowOperator() { var wo = new GlueOperator(); diff --git a/src/test/java/io/csviri/operator/glue/TestData.java b/src/test/java/io/csviri/operator/glue/TestData.java new file mode 100644 index 0000000..6396d71 --- /dev/null +++ b/src/test/java/io/csviri/operator/glue/TestData.java @@ -0,0 +1,38 @@ +package io.csviri.operator.glue; + +import io.csviri.operator.glue.customresource.TestCustomResource; +import io.csviri.operator.glue.customresource.TestCustomResource2; +import io.csviri.operator.glue.customresource.TestCustomResourceSpec; +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; + +public class TestData { + + public static final String TEST_RESOURCE_VALUE = "val"; + public static final String TEST_RESOURCE_PREFIX = "testcr"; + public static final String TEST_RESOURCE2_PREFIX = "testcr2"; + + public static TestCustomResource testCustomResource() { + return testCustomResource(1); + } + + public static TestCustomResource testCustomResource(int index) { + var res = new TestCustomResource(); + res.setMetadata(new ObjectMetaBuilder() + .withName(TEST_RESOURCE_PREFIX + index) + .build()); + res.setSpec(new TestCustomResourceSpec()); + res.getSpec().setValue(TEST_RESOURCE_VALUE + index); + return res; + } + + public static TestCustomResource2 testCustomResource2(int index) { + var res = new TestCustomResource2(); + res.setMetadata(new ObjectMetaBuilder() + .withName(TEST_RESOURCE2_PREFIX + index) + .build()); + res.setSpec(new TestCustomResourceSpec()); + res.getSpec().setValue(TEST_RESOURCE_VALUE + index); + return res; + } + +} diff --git a/src/test/java/io/csviri/operator/glue/TestUtils.java b/src/test/java/io/csviri/operator/glue/TestUtils.java index 6d93c65..3c2d9ed 100644 --- a/src/test/java/io/csviri/operator/glue/TestUtils.java +++ b/src/test/java/io/csviri/operator/glue/TestUtils.java @@ -25,9 +25,11 @@ public class TestUtils { public static final Duration GC_WAIT_TIMEOUT_SECOND = Duration.ofSeconds(45); + public static final Duration INITIAL_RECONCILE_WAIT_TIMEOUT = Duration.ofMillis(150); public static final int CRD_READY_WAIT = 1000; + private static final Logger log = LoggerFactory.getLogger(TestUtils.class); public static Glue loadResoureFlow(String path) { diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index 8db8542..cea0042 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -1,2 +1,3 @@ quarkus.log.category."io.csviri.operator.glue".level=DEBUG -quarkus.kubernetes-client.devservices.flavor=kind \ No newline at end of file +quarkus.kubernetes-client.devservices.flavor=kind +#quarkus.operator-sdk.controllers.glue.selector=testglue=true \ No newline at end of file diff --git a/src/test/resources/glue/SimpleGlue.yaml b/src/test/resources/glue/SimpleGlue.yaml new file mode 100644 index 0000000..24cc79a --- /dev/null +++ b/src/test/resources/glue/SimpleGlue.yaml @@ -0,0 +1,15 @@ +# Invalid GLUE, presents resources with non-unique name +apiVersion: io.csviri.operator.glue/v1beta1 +kind: Glue +metadata: + name: simple-glue +spec: + childResources: + - name: configMap + resource: + apiVersion: v1 + kind: ConfigMap + metadata: + name: simple-glue-configmap + data: + key: "value1" diff --git a/src/test/resources/glueoperator/Templating.yaml b/src/test/resources/glueoperator/SimpleGlueOperator.yaml similarity index 100% rename from src/test/resources/glueoperator/Templating.yaml rename to src/test/resources/glueoperator/SimpleGlueOperator.yaml