diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ConfigMapDependentResource.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ConfigMapDependentResource.java index bba817436c..cfe0f79a0e 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ConfigMapDependentResource.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ConfigMapDependentResource.java @@ -19,7 +19,7 @@ // this annotation only activates when using managed dependents and is not otherwise needed @KubernetesDependent(labelSelector = SELECTOR) -class ConfigMapDependentResource extends CRUKubernetesDependentResource { +public class ConfigMapDependentResource extends CRUKubernetesDependentResource { private static final Logger log = LoggerFactory.getLogger(ConfigMapDependentResource.class); diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java index 80a41e24d8..4991171f12 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java @@ -16,7 +16,8 @@ // this annotation only activates when using managed dependents and is not otherwise needed @KubernetesDependent(labelSelector = WebPageManagedDependentsReconciler.SELECTOR) -class DeploymentDependentResource extends CRUKubernetesDependentResource { +public class DeploymentDependentResource + extends CRUKubernetesDependentResource { public DeploymentDependentResource() { super(Deployment.class); diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java index 84d670cfc5..a914aa5994 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java @@ -15,7 +15,7 @@ // this annotation only activates when using managed dependents and is not otherwise needed @KubernetesDependent(labelSelector = WebPageManagedDependentsReconciler.SELECTOR) -class ServiceDependentResource extends CRUKubernetesDependentResource { +public class ServiceDependentResource extends CRUKubernetesDependentResource { public ServiceDependentResource() { super(Service.class); diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPage.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPage.java index 52ef6a938b..f1e4a69e3b 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPage.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPage.java @@ -10,11 +10,6 @@ public class WebPage extends CustomResource implements Namespaced { - @Override - protected WebPageStatus initStatus() { - return new WebPageStatus(); - } - @Override public String toString() { return "WebPage{" + diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageManagedDependentsReconciler.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageManagedDependentsReconciler.java index 6441237b71..ac89ebd269 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageManagedDependentsReconciler.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageManagedDependentsReconciler.java @@ -12,13 +12,11 @@ import static io.javaoperatorsdk.operator.sample.Utils.createStatus; import static io.javaoperatorsdk.operator.sample.Utils.handleError; import static io.javaoperatorsdk.operator.sample.Utils.simulateErrorIfRequested; -import static io.javaoperatorsdk.operator.sample.WebPageManagedDependentsReconciler.SELECTOR; /** * Shows how to implement a reconciler with managed dependent resources. */ @ControllerConfiguration( - labelSelector = SELECTOR, dependents = { @Dependent(type = ConfigMapDependentResource.class), @Dependent(type = DeploymentDependentResource.class), @@ -27,7 +25,7 @@ public class WebPageManagedDependentsReconciler implements Reconciler, ErrorStatusHandler { - static final String SELECTOR = "managed"; + public static final String SELECTOR = "managed"; @Override public ErrorStatusUpdateControl updateErrorStatus(WebPage resource, diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageOperator.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageOperator.java index 30958dbc84..661f6f3ba8 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageOperator.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageOperator.java @@ -17,7 +17,8 @@ public class WebPageOperator { public static final String WEBPAGE_RECONCILER_ENV = "WEBPAGE_RECONCILER"; - public static final String WEBPAGE_RECONCILER_ENV_VALUE = "classic"; + public static final String WEBPAGE_CLASSIC_RECONCILER_ENV_VALUE = "classic"; + public static final String WEBPAGE_MANAGED_DEPENDENT_RESOURCE_ENV_VALUE = "managed"; private static final Logger log = LoggerFactory.getLogger(WebPageOperator.class); @@ -27,8 +28,12 @@ public static void main(String[] args) throws IOException { Config config = new ConfigBuilder().withNamespace(null).build(); KubernetesClient client = new DefaultKubernetesClient(config); Operator operator = new Operator(client); - if (WEBPAGE_RECONCILER_ENV_VALUE.equals(System.getenv(WEBPAGE_RECONCILER_ENV))) { + String reconcilerEnvVar = System.getenv(WEBPAGE_RECONCILER_ENV); + if (WEBPAGE_CLASSIC_RECONCILER_ENV_VALUE.equals(reconcilerEnvVar)) { operator.register(new WebPageReconciler(client)); + } else if (WEBPAGE_MANAGED_DEPENDENT_RESOURCE_ENV_VALUE + .equals(reconcilerEnvVar)) { + operator.register(new WebPageManagedDependentsReconciler()); } else { operator.register(new WebPageStandaloneDependentsReconciler(client)); } diff --git a/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorAbstractTest.java b/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorAbstractTest.java index 65a3084989..f80e681b7a 100644 --- a/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorAbstractTest.java +++ b/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorAbstractTest.java @@ -7,7 +7,6 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; -import java.util.Objects; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -27,10 +26,15 @@ public abstract class WebPageOperatorAbstractTest { - static final Logger log = LoggerFactory.getLogger(WebPageOperatorDependentResourcesE2E.class); + static final Logger log = + LoggerFactory.getLogger(WebPageOperatorStandaloneDependentResourcesE2E.class); static final KubernetesClient client = new DefaultKubernetesClient(); public static final String TEST_PAGE = "test-page"; + public static final String TITLE1 = "Hello Operator World"; + public static final String TITLE2 = "Hello Operator World Title 2"; + public static final int WAIT_SECONDS = 20; + public static final Duration POLL_INTERVAL = Duration.ofSeconds(1); boolean isLocal() { String deployment = System.getProperty("test.deployment"); @@ -42,24 +46,42 @@ boolean isLocal() { @Test void testAddingWebPage() { - var webPage = createWebPage(); + var webPage = createWebPage(TITLE1); operator().create(WebPage.class, webPage); await() - .atMost(Duration.ofSeconds(20)) - .pollInterval(Duration.ofSeconds(1)) - .until( + .atMost(Duration.ofSeconds(WAIT_SECONDS)) + .pollInterval(POLL_INTERVAL) + .untilAsserted( () -> { var actual = operator().get(WebPage.class, TEST_PAGE); var deployment = operator().get(Deployment.class, deploymentName(webPage)); - return Boolean.TRUE.equals(actual.getStatus().getAreWeGood()) - && Objects.equals(deployment.getSpec().getReplicas(), - deployment.getStatus().getReadyReplicas()); + assertThat(actual.getStatus().getAreWeGood()).isTrue(); + assertThat(deployment.getSpec().getReplicas()) + .isEqualTo(deployment.getStatus().getReadyReplicas()); }); - - String response = httpGetForWebPage(webPage); - assertThat(response).contains("Hello Operator World"); + assertThat(httpGetForWebPage(webPage)).contains(TITLE1); + + // update part: changing title + operator().replace(WebPage.class, createWebPage(TITLE2)); + + await().atMost(Duration.ofSeconds(WAIT_SECONDS)) + .pollInterval(POLL_INTERVAL) + .untilAsserted(() -> { + String page = httpGetForWebPage(webPage); + assertThat(page).isNotNull().contains(TITLE2); + }); + + // delete part: deleting webpage + operator().delete(WebPage.class, createWebPage(TITLE2)); + + await().atMost(Duration.ofSeconds(WAIT_SECONDS)) + .pollInterval(POLL_INTERVAL) + .untilAsserted(() -> { + Deployment deployment = operator().get(Deployment.class, deploymentName(webPage)); + assertThat(deployment).isNull(); + }); } String httpGetForWebPage(WebPage webPage) { @@ -75,7 +97,7 @@ String httpGetForWebPage(WebPage webPage) { .uri(new URI("http://localhost:" + portForward.getLocalPort())).build(); return httpClient.send(request, HttpResponse.BodyHandlers.ofString()).body(); } catch (URISyntaxException | IOException | InterruptedException e) { - throw new IllegalStateException(e); + return null; } finally { if (portForward != null) { try { @@ -87,7 +109,7 @@ String httpGetForWebPage(WebPage webPage) { } } - WebPage createWebPage() { + WebPage createWebPage(String title) { WebPage webPage = new WebPage(); webPage.setMetadata(new ObjectMeta()); webPage.getMetadata().setName(TEST_PAGE); @@ -98,7 +120,7 @@ WebPage createWebPage() { .setHtml( "\n" + " \n" - + " Hello Operator World\n" + + " " + title + "\n" + " \n" + " \n" + " Hello World! \n" diff --git a/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java b/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java index 1dda69d6be..2183fba43e 100644 --- a/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java +++ b/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java @@ -13,8 +13,8 @@ import io.javaoperatorsdk.operator.junit.ClusterOperatorExtension; import io.javaoperatorsdk.operator.junit.LocalOperatorExtension; +import static io.javaoperatorsdk.operator.sample.WebPageOperator.WEBPAGE_CLASSIC_RECONCILER_ENV_VALUE; import static io.javaoperatorsdk.operator.sample.WebPageOperator.WEBPAGE_RECONCILER_ENV; -import static io.javaoperatorsdk.operator.sample.WebPageOperator.WEBPAGE_RECONCILER_ENV_VALUE; import static io.javaoperatorsdk.operator.sample.WebPageReconciler.lowLevelLabel; class WebPageOperatorE2E extends WebPageOperatorAbstractTest { @@ -40,7 +40,8 @@ public WebPageOperatorE2E() throws FileNotFoundException {} container.setEnv(new ArrayList<>()); } container.getEnv().add( - new EnvVar(WEBPAGE_RECONCILER_ENV, WEBPAGE_RECONCILER_ENV_VALUE, null)); + new EnvVar(WEBPAGE_RECONCILER_ENV, WEBPAGE_CLASSIC_RECONCILER_ENV_VALUE, + null)); }) .build(); @@ -51,8 +52,8 @@ AbstractOperatorExtension operator() { } @Override - WebPage createWebPage() { - WebPage page = super.createWebPage(); + WebPage createWebPage(String title) { + WebPage page = super.createWebPage(title); page.getMetadata().setLabels(lowLevelLabel()); return page; } diff --git a/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorManagedDependentResourcesE2E.java b/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorManagedDependentResourcesE2E.java new file mode 100644 index 0000000000..1b40fccc80 --- /dev/null +++ b/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorManagedDependentResourcesE2E.java @@ -0,0 +1,50 @@ +package io.javaoperatorsdk.operator.sample; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.ArrayList; + +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.fabric8.kubernetes.api.model.Container; +import io.fabric8.kubernetes.api.model.EnvVar; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.javaoperatorsdk.operator.junit.AbstractOperatorExtension; +import io.javaoperatorsdk.operator.junit.ClusterOperatorExtension; +import io.javaoperatorsdk.operator.junit.LocalOperatorExtension; + +import static io.javaoperatorsdk.operator.sample.WebPageOperator.*; + +class WebPageOperatorManagedDependentResourcesE2E extends WebPageOperatorAbstractTest { + + public WebPageOperatorManagedDependentResourcesE2E() throws FileNotFoundException {} + + @RegisterExtension + AbstractOperatorExtension operator = + isLocal() + ? LocalOperatorExtension.builder() + .waitForNamespaceDeletion(false) + .withReconciler(new WebPageManagedDependentsReconciler()) + .build() + : ClusterOperatorExtension.builder() + .waitForNamespaceDeletion(false) + .withOperatorDeployment(client.load(new FileInputStream("k8s/operator.yaml")).get(), + resources -> { + Deployment deployment = (Deployment) resources.stream() + .filter(r -> r instanceof Deployment).findFirst().orElseThrow(); + Container container = + deployment.getSpec().getTemplate().getSpec().getContainers().get(0); + if (container.getEnv() == null) { + container.setEnv(new ArrayList<>()); + } + container.getEnv().add( + new EnvVar(WEBPAGE_RECONCILER_ENV, + WEBPAGE_MANAGED_DEPENDENT_RESOURCE_ENV_VALUE, null)); + }) + .build(); + + @Override + AbstractOperatorExtension operator() { + return operator; + } +} diff --git a/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorDependentResourcesE2E.java b/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorStandaloneDependentResourcesE2E.java similarity index 83% rename from sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorDependentResourcesE2E.java rename to sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorStandaloneDependentResourcesE2E.java index 8cbba764be..2175e33a41 100644 --- a/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorDependentResourcesE2E.java +++ b/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorStandaloneDependentResourcesE2E.java @@ -9,9 +9,9 @@ import io.javaoperatorsdk.operator.junit.ClusterOperatorExtension; import io.javaoperatorsdk.operator.junit.LocalOperatorExtension; -class WebPageOperatorDependentResourcesE2E extends WebPageOperatorAbstractTest { +class WebPageOperatorStandaloneDependentResourcesE2E extends WebPageOperatorAbstractTest { - public WebPageOperatorDependentResourcesE2E() throws FileNotFoundException {} + public WebPageOperatorStandaloneDependentResourcesE2E() throws FileNotFoundException {} @RegisterExtension AbstractOperatorExtension operator =