diff --git a/.github/workflows/TomcatIntegrationTest.yml b/.github/workflows/TomcatIntegrationTest.yml new file mode 100644 index 0000000..4221783 --- /dev/null +++ b/.github/workflows/TomcatIntegrationTest.yml @@ -0,0 +1,40 @@ +name: Tomcat integration test +on: + push: + branches: + - "*" +jobs: + tomcat_integration_test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up Helm + uses: azure/setup-helm@v1 + with: + version: v3.4.0 + + - uses: actions/setup-python@v2 + with: + python-version: 3.7 + + - name: Create kind cluster + uses: helm/kind-action@v1.2.0 + + - name: Apply CRDs + run: kubectl apply -f tomcat/k8s/crd.yaml + + - name: Set up Java and Maven + uses: actions/setup-java@v1 + with: + # java-version: ${{ matrix.java }} + java-version: 15 + - uses: actions/cache@v2 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + - name: Run unit tests + run: mvn -B test --file tomcat/pom.xml \ No newline at end of file diff --git a/tomcat/pom.xml b/tomcat/pom.xml index 987a3c5..5f3069d 100644 --- a/tomcat/pom.xml +++ b/tomcat/pom.xml @@ -38,6 +38,18 @@ takes 1.19 + + junit + junit + 4.13.1 + test + + + org.awaitility + awaitility + 4.1.0 + test + diff --git a/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/Webapp.java b/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/Webapp.java index b496a05..75e7a64 100644 --- a/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/Webapp.java +++ b/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/Webapp.java @@ -1,9 +1,10 @@ package io.javaoperatorsdk.operator.sample; +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.Version; @Group("tomcatoperator.io") @Version("v1") -public class Webapp extends CustomResource {} +public class Webapp extends CustomResource implements Namespaced {} diff --git a/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/WebappController.java b/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/WebappController.java index 4220302..c94dbb8 100644 --- a/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/WebappController.java +++ b/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/WebappController.java @@ -24,7 +24,7 @@ public WebappController(KubernetesClient kubernetesClient) { @Override public UpdateControl createOrUpdateResource(Webapp webapp, Context context) { - if (Objects.equals(webapp.getSpec().getUrl(), webapp.getStatus().getDeployedArtifact())) { + if (webapp.getStatus() != null && Objects.equals(webapp.getSpec().getUrl(), webapp.getStatus().getDeployedArtifact())) { return UpdateControl.noUpdate(); } @@ -32,7 +32,7 @@ public UpdateControl createOrUpdateResource(Webapp webapp, Context - + diff --git a/tomcat/src/test/java/sample/IntegrationTest.java b/tomcat/src/test/java/sample/IntegrationTest.java new file mode 100644 index 0000000..3af8cd0 --- /dev/null +++ b/tomcat/src/test/java/sample/IntegrationTest.java @@ -0,0 +1,71 @@ +package sample; + +import io.fabric8.kubernetes.api.model.KubernetesResourceList; +import io.fabric8.kubernetes.api.model.Namespace; +import io.fabric8.kubernetes.api.model.NamespaceBuilder; +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.ConfigBuilder; +import io.fabric8.kubernetes.client.DefaultKubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.dsl.MixedOperation; +import io.fabric8.kubernetes.client.dsl.Resource; +import io.fabric8.kubernetes.client.utils.Serialization; +import io.javaoperatorsdk.operator.Operator; +import io.javaoperatorsdk.operator.config.runtime.DefaultConfigurationService; +import io.javaoperatorsdk.operator.sample.Tomcat; +import io.javaoperatorsdk.operator.sample.TomcatController; +import io.javaoperatorsdk.operator.sample.WebappController; +import org.junit.Test; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; +import static org.junit.Assert.*; + +public class IntegrationTest { + @Test + public void test() throws InterruptedException { + Config config = new ConfigBuilder().withNamespace(null).build(); + KubernetesClient client = new DefaultKubernetesClient(config); + Operator operator = new Operator(client, DefaultConfigurationService.instance()); + + TomcatController tomcatController = new TomcatController(client); + operator.register(tomcatController); + + operator.register(new WebappController(client)); + + Tomcat tomcat = loadYaml(Tomcat.class, "tomcat-sample1.yaml"); + + tomcat.getSpec().setReplicas(3); + tomcat.getMetadata().setNamespace("tomcat-test"); + + MixedOperation, Resource> tomcatClient = client.customResources(Tomcat.class); + + Namespace tt_ns = new NamespaceBuilder().withMetadata(new ObjectMetaBuilder().withName("tomcat-test").build()).build(); + + client.namespaces().delete(tt_ns); + + await().atMost(300, SECONDS).until(() -> client.namespaces().withName("tomcat-test").get() == null); + + client.namespaces().createOrReplace(tt_ns); + + tomcatClient.inNamespace("tomcat-test").create(tomcat); + + await().atMost(60, SECONDS).until(() -> { + Tomcat updatedTomcat = tomcatClient.inNamespace("tomcat-test").withName("test-tomcat1").get(); + return updatedTomcat.getStatus() != null && (int) updatedTomcat.getStatus().getReadyReplicas() == 3; + }); + } + + private T loadYaml(Class clazz, String yaml) { + try (InputStream is = new FileInputStream("k8s/" + yaml)) { + return Serialization.unmarshal(is, clazz); + } catch (IOException ex) { + throw new IllegalStateException("Cannot find yaml on classpath: " + yaml); + } + } +}