diff --git a/.circleci/config.yml b/.circleci/config.yml index d0a42abc..491847cf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -20,8 +20,7 @@ jobs: branches: ignore: - gh-pages - docker: - - image: circleci/openjdk:8-jdk-node-browsers + machine: true environment: _JAVA_OPTIONS: "-Xms1024m -Xmx2048m" _SERVICE_OCCURENCE: 5 @@ -41,13 +40,57 @@ jobs: - ~/.m2 key: spring-cloud-kubernetes-{{ .Branch }}-{{ checksum "pom.xml" }} - run: - name: test + name: Run regular tests command: | ./mvnw -s .settings.xml clean install -Dservice.occurence=${_SERVICE_OCCURENCE} #org.jacoco:jacoco-maven-plugin:prepare-agent install -U -P sonar -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn mkdir -p $HOME/artifacts/junit/ find . -type f -regex ".*/spring-cloud-*.*/target/*.*" -exec cp {} $HOME/artifacts/ \; find . -type f -regex ".*/target/.*-reports/.*" -exec cp {} $HOME/artifacts/junit/ \; bash <(curl -s https://codecov.io/bash) + - run: + name: Install Snap + command: | + sudo apt update + sudo apt install snapd + - run: + name: Launch Kubernetes with microk8s + command: | + sudo snap install microk8s --classic --channel=1.11/stable + + # wait until a k8s node is ready + sleep 10 + n=0 + until [ $n -ge 10 ] + do + (/snap/bin/microk8s.kubectl get no | grep -z "Ready") && break + n=$[$n+1] + sleep 20 + done + + echo "Kubernetes cluster launched" + + # Allow intra-pod communication + sudo iptables -P FORWARD ACCEPT + + /snap/bin/microk8s.enable dns registry + + # wait until the registry is up and running + sleep 10 + n=0 + until [ $n -ge 10 ] + do + (/snap/bin/microk8s.kubectl get pod --namespace=container-registry | grep -z "Running") && break + n=$[$n+1] + sleep 10 + done + + echo "Kubernetes Container Registry enabled" + - run: + name: Run integration tests + command: | + cd spring-cloud-kubernetes-integration-tests + /snap/bin/microk8s.kubectl config view --raw > /tmp/kubeconfig + ./deploy_test_undeploy_all.sh - store_test_results: path: $HOME/artifacts/junit/ - store_artifacts: @@ -55,4 +98,3 @@ jobs: notify: webhooks: - url: https://webhooks.gitter.im/e/22e6bb4eb945dd61ba54 - diff --git a/pom.xml b/pom.xml index 19028baa..b7b44a04 100644 --- a/pom.xml +++ b/pom.xml @@ -71,6 +71,7 @@ 3.5.37 1.6 2.4.12 + 3.0.2 1.1-groovy-2.4 @@ -86,12 +87,13 @@ spring-cloud-starter-kubernetes-all spring-cloud-kubernetes-examples spring-cloud-kubernetes-leader + spring-cloud-kubernetes-integration-tests docs - + org.springframework.cloud spring-cloud-kubernetes-dependencies diff --git a/spring-cloud-kubernetes-integration-tests/README.md b/spring-cloud-kubernetes-integration-tests/README.md new file mode 100644 index 00000000..aa1cf45e --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/README.md @@ -0,0 +1,108 @@ +# Purpose + +Demonstrate how integration tests can be run against a local cluster setup with [microk8s](https://microk8s.io/) +The Kubernetes resources necessary to get the test application +onto the cluster are created using the [Fabric8 Maven Plugin](https://maven.fabric8.io/) + +# Instructions + +## Install microk8s + +```bash +sudo snap install microk8s --classic --channel=1.11/stable +sleep 10 +microk8s.enable dns registry +``` + +Ensure everything is running by inspecting the output of: + +```bash +microk8s.kubectl get all --all-namespaces +``` + +It should look something like: + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +container-registry pod/registry-6bc95dfd76-274lc 1/1 Running 0 40s +kube-system pod/hostpath-provisioner-9979c7f64-f96tw 1/1 Running 0 41s +kube-system pod/kube-dns-864b8bdc77-68kmn 2/3 Running 0 41s + +NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +container-registry service/registry NodePort 10.152.183.175 5000:32000/TCP 50s +default service/kubernetes ClusterIP 10.152.183.1 443/TCP 1m +kube-system service/kube-dns ClusterIP 10.152.183.10 53/UDP,53/TCP 56s + +NAMESPACE NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE +container-registry deployment.apps/registry 1 1 1 1 50s +kube-system deployment.apps/hostpath-provisioner 1 1 1 1 51s +kube-system deployment.apps/kube-dns 1 1 1 0 56s + +NAMESPACE NAME DESIRED CURRENT READY AGE +container-registry replicaset.apps/registry-6bc95dfd76 1 1 1 41s +kube-system replicaset.apps/hostpath-provisioner-9979c7f64 1 1 1 41s +kube-system replicaset.apps/kube-dns-864b8bdc77 1 1 0 41s +``` + +## Setup environment for FMP to work + +One premise for the Fabric8 Maven Plugin to work is that is can read the proper Kubernetes Config file. +We export the corresponding config file for the cluster microk8s sets up to temp file which will +be used later + +```bash +microk8s.kubectl config view --raw > /tmp/kubeconfig +``` + +## Deploy application + +**The following commands assume that they are executed inside the maven module of each specific test** + +Since FMP is based on the Fabric8 Kubernetes Client, we can leverage the `KUBECONFIG` environment variable +to make FMP aware of the Kubernetes Config file we created above + +```bash +export KUBECONFIG=/tmp/kubeconfig +../../mvnw clean package fabric8:build fabric8:push fabric8:deploy -Pfmp +``` + +Make sure the application was deployed be executing: + +```bash +microk8s.kubectl get pod -l app=sb-fmp-microk8s +``` + +It should look something like: + +``` +NAME READY STATUS RESTARTS AGE +simple-core-5fbb7646dc-66t7b 1/1 Running 0 57s +``` + +The integration tests can be run against the service which is deployed inside the cluster by executing: + +```bash +../../mvnw verify -Pfmp,it -Dfabric8.skip +``` + +This integration tests runs locally (making it easily debuggable), and interacts with the deployed service +using the exposed port. +By leveraging [Aquillian Cube Kubernetes](http://arquillian.org/arquillian-cube/#_kubernetes), it's able to setup and teardown resources needed for each test + +To undeploy the application from the cluster simply execute: + +```bash +../../mvnw fabric8:undeploy -Pfmp +``` + +## Run all tests + +By executing + +```bash +deploy_test_undeploy_all.sh +``` + +each one of the test applications will be deployed to the cluster and the integration tests will be executed + + diff --git a/spring-cloud-kubernetes-integration-tests/deploy_test_undeploy_all.sh b/spring-cloud-kubernetes-integration-tests/deploy_test_undeploy_all.sh new file mode 100755 index 00000000..f68d1444 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/deploy_test_undeploy_all.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -e + +# The script launches and tests each test application - one at a time + +for D in $(find . -maxdepth 1 -mindepth 1 -not -path '*/\.*' -type d); do + pushd ${D} > /dev/null + ../deploy_test_undeploy_single.sh + /snap/bin/microk8s.kubectl wait --for=delete pod -l group=org.springframework.cloud --timeout=60s > /dev/null + popd > /dev/null +done + diff --git a/spring-cloud-kubernetes-integration-tests/deploy_test_undeploy_single.sh b/spring-cloud-kubernetes-integration-tests/deploy_test_undeploy_single.sh new file mode 100755 index 00000000..b20076c3 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/deploy_test_undeploy_single.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +set -e + +# The script assumes that there is only one application deployed by FMP running at a time + +SCRIPT_ABSOLUTE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +mvnCmd="${SCRIPT_ABSOLUTE_DIR}"/../mvnw +kubectlCmd=/snap/bin/microk8s.kubectl + +export KUBECONFIG=/tmp/kubeconfig + +echo "Starting application deployment to cluster" +$mvnCmd clean package fabric8:build fabric8:push fabric8:deploy -Pfmp +echo "Finished deployment" + +echo "Waiting for pod to become Ready" +# We are leveraging the fact the fact that FMP adds the group label and the fact that only one +# application can be running at a time +$kubectlCmd wait --for=condition=Ready pod -l group=org.springframework.cloud --timeout=60s > /dev/null + +echo "Starting the integration tests" +$mvnCmd verify -Pfmp,it -Dfabric8.skip + +echo "Successfully executed integration tests" +echo "Undeploying application" +$mvnCmd fabric8:undeploy -Pfmp diff --git a/spring-cloud-kubernetes-integration-tests/pom.xml b/spring-cloud-kubernetes-integration-tests/pom.xml new file mode 100644 index 00000000..f1600c9c --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/pom.xml @@ -0,0 +1,140 @@ + + + 4.0.0 + + org.springframework.cloud + spring-cloud-kubernetes + 1.0.0.BUILD-SNAPSHOT + + + spring-cloud-kubernetes-integration-tests + pom + + Spring Cloud Kubernetes :: Integration Tests + Integration tests where SCK applications are run inside a Kubernetes cluster + + + + 1.8 + 3.5.42 + 1.18.2 + 1.4.0.Final + 3.2.0 + + + unix:///var/snap/microk8s/current/docker.sock + + + localhost:32000 + + + 32222 + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.apache.maven.plugins + maven-deploy-plugin + ${maven-deploy-plugin.version} + + true + + + + + + + + + fmp + + + + io.fabric8 + fabric8-maven-plugin + ${fmp.version} + + + docker + kubernetes + ${microk8s.registry} + + + + fabric8 + + resource + build + + + + + + + + + it + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + localhost + ${nodeport.value} + + ${project.build.outputDirectory} + + + + + integration-test + verify + + + + + + + + + + + + + org.jboss.arquillian + arquillian-bom + ${arquillian.version} + pom + import + + + io.rest-assured + rest-assured + ${rest-assured.version} + + + + + + simple-core + simple-configmap + + + + diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml b/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml new file mode 100644 index 00000000..b09ae0af --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + + + org.springframework.cloud + spring-cloud-kubernetes-integration-tests + 1.0.0.BUILD-SNAPSHOT + + + Spring Cloud Kubernetes :: Integration Tests :: Simple Configmap + simple-configmap + jar + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.cloud + spring-cloud-starter-kubernetes-config + + + org.springframework.boot + spring-boot-actuator + + + org.springframework.boot + spring-boot-actuator-autoconfigure + + + org.springframework.boot + spring-boot-starter-test + test + + + org.arquillian.cube + arquillian-cube-kubernetes + ${arquillian-cube.version} + test + + + undertow-core + io.undertow + + + + + org.jboss.arquillian.junit + arquillian-junit-standalone + test + + + io.rest-assured + rest-assured + test + + + + + diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/fabric8/deployment.yml b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/fabric8/deployment.yml new file mode 100644 index 00000000..3c8b53a3 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/fabric8/deployment.yml @@ -0,0 +1,10 @@ +# We need this fragment in order for the kubernetes client to talk to +# the Kubernetes API without caring about proper certificates +spec: + template: + spec: + containers: + - env: + - name: KUBERNETES_TRUST_CERTIFICATES + value: true + diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/fabric8/svc.yml b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/fabric8/svc.yml new file mode 100644 index 00000000..aa6fbd53 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/fabric8/svc.yml @@ -0,0 +1,7 @@ +# We are using an FMP fragment to ensure that NodePort is used correctly +spec: + ports: + - protocol: TCP + port: 8080 + nodePort: ${nodeport.value} + type: NodePort diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/java/org/springframework/cloud/kubernetes/it/DummyConfig.java b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/java/org/springframework/cloud/kubernetes/it/DummyConfig.java new file mode 100644 index 00000000..1aec26a2 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/java/org/springframework/cloud/kubernetes/it/DummyConfig.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.springframework.cloud.kubernetes.it; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "config") +public class DummyConfig { + + private String message = "This is a dummy message"; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + +} diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/java/org/springframework/cloud/kubernetes/it/SimpleConfigMapApplication.java b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/java/org/springframework/cloud/kubernetes/it/SimpleConfigMapApplication.java new file mode 100644 index 00000000..62a29a85 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/java/org/springframework/cloud/kubernetes/it/SimpleConfigMapApplication.java @@ -0,0 +1,40 @@ +package org.springframework.cloud.kubernetes.it; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@SpringBootApplication +@RestController +@EnableConfigurationProperties(DummyConfig.class) +public class SimpleConfigMapApplication { + + @Autowired + private DummyConfig dummyConfig; + + @GetMapping("/greeting") + public Greeting greeting() { + return new Greeting(dummyConfig.getMessage()); + } + + public static void main(String[] args) { + SpringApplication.run(SimpleConfigMapApplication.class, args); + } + + public static class Greeting { + + private final String message; + + public Greeting(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + } + +} diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/resources/application.yml b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/resources/application.yml new file mode 100644 index 00000000..fbd3eb93 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/resources/application.yml @@ -0,0 +1,12 @@ +server: + port: 8080 + +# we enable some of the management endpoints to make it possible to restart the application +management: + endpoint: + restart: + enabled: true + health: + enabled: true + info: + enabled: true diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/resources/bootstrap.yaml b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/resources/bootstrap.yaml new file mode 100644 index 00000000..643b34b8 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/main/resources/bootstrap.yaml @@ -0,0 +1,14 @@ +spring: + application: + name: sck-example + cloud: + kubernetes: + # enable reloading of the application when on the property sources has changed + reload: + enabled: true + mode: polling + period: 5000 + config: + sources: + - name: ${spring.application.name} + namespace: default diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/java/org/springframework/cloud/kubernetes/it/GreetingIT.java b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/java/org/springframework/cloud/kubernetes/it/GreetingIT.java new file mode 100644 index 00000000..e56f16d2 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/java/org/springframework/cloud/kubernetes/it/GreetingIT.java @@ -0,0 +1,52 @@ +package org.springframework.cloud.kubernetes.it; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.core.Is.is; + +import org.arquillian.cube.kubernetes.annotations.KubernetesResource; +import org.arquillian.cube.kubernetes.impl.requirement.RequiresKubernetes; +import org.jboss.arquillian.junit.Arquillian; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; + +@RequiresKubernetes +@RunWith(Arquillian.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class GreetingIT { + + private static final String HOST = System.getProperty("service.host"); + private static final Integer PORT = Integer.valueOf(System.getProperty("service.port")); + + @Test + public void firstTestThatTheDefaultMessageIsReturned() { + given() + .baseUri(String.format("http://%s:%d", HOST, PORT)) + .get("greeting") + .then() + .statusCode(200) + .body("message", is("This is a dummy message")); + } + + @Test + @KubernetesResource("classpath:config-map.yml") + public void thenApplyAConfigMapAndEnsureThatTheMessageIsUpdated() { + waitForApplicationToReload(); + + given() + .baseUri(String.format("http://%s:%d", HOST, PORT)) + .get("greeting") + .then() + .statusCode(200) + .body("message", is("Hello from Spring Cloud Kubernetes!")); + } + + private void waitForApplicationToReload() { + try { + Thread.sleep(15000); + } catch (InterruptedException e) { + } + } + +} diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/resources/arquillian.xml b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/resources/arquillian.xml new file mode 100644 index 00000000..37d03d62 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/resources/arquillian.xml @@ -0,0 +1,13 @@ + + + + default + + + false + false + + + diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/resources/bootstrap.yaml b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/resources/bootstrap.yaml new file mode 100644 index 00000000..fdc5a905 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/resources/bootstrap.yaml @@ -0,0 +1,6 @@ +spring: + application: + name: sck-example + cloud: + kubernetes: + enabled: false diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/resources/config-map.yml b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/resources/config-map.yml new file mode 100644 index 00000000..15343af7 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/resources/config-map.yml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: sck-example +data: + application.properties: |- + config.message=Hello from Spring Cloud Kubernetes! + another.property=value diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/resources/logback-test.xml new file mode 100644 index 00000000..9f754ed5 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/resources/logback-test.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml b/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml new file mode 100644 index 00000000..133c48cb --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + + + org.springframework.cloud + spring-cloud-kubernetes-integration-tests + 1.0.0.BUILD-SNAPSHOT + + + Spring Cloud Kubernetes :: Integration Tests :: Simple Core + simple-core + jar + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-actuator + + + org.springframework.boot + spring-boot-actuator-autoconfigure + + + org.springframework.cloud + spring-cloud-kubernetes-core + + + org.springframework.boot + spring-boot-starter-test + test + + + org.arquillian.cube + arquillian-cube-kubernetes + ${arquillian-cube.version} + test + + + undertow-core + io.undertow + + + + + org.jboss.arquillian.junit + arquillian-junit-standalone + test + + + io.rest-assured + rest-assured + test + + + + + diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/src/main/fabric8/deployment.yml b/spring-cloud-kubernetes-integration-tests/simple-core/src/main/fabric8/deployment.yml new file mode 100644 index 00000000..3c8b53a3 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-core/src/main/fabric8/deployment.yml @@ -0,0 +1,10 @@ +# We need this fragment in order for the kubernetes client to talk to +# the Kubernetes API without caring about proper certificates +spec: + template: + spec: + containers: + - env: + - name: KUBERNETES_TRUST_CERTIFICATES + value: true + diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/src/main/fabric8/svc.yml b/spring-cloud-kubernetes-integration-tests/simple-core/src/main/fabric8/svc.yml new file mode 100644 index 00000000..945f430d --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-core/src/main/fabric8/svc.yml @@ -0,0 +1,15 @@ +# we are using an FMP fragment to ensure that NodePort is used correctly +kind: Service +apiVersion: v1 +metadata: + name: ${project.artifactId} + labels: + app: ${project.artifactId} +spec: + selector: + app: ${project.artifactId} + ports: + - protocol: TCP + port: 8080 + nodePort: ${nodeport.value} + type: NodePort diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/src/main/java/org/springframework/cloud/kubernetes/it/SimpleCoreApplication.java b/spring-cloud-kubernetes-integration-tests/simple-core/src/main/java/org/springframework/cloud/kubernetes/it/SimpleCoreApplication.java new file mode 100644 index 00000000..0e4a9bea --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-core/src/main/java/org/springframework/cloud/kubernetes/it/SimpleCoreApplication.java @@ -0,0 +1,34 @@ +package org.springframework.cloud.kubernetes.it; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@SpringBootApplication +@RestController +public class SimpleCoreApplication { + + @GetMapping("/greeting") + public Greeting home() { + return new Greeting("Hello Spring Boot"); + } + + public static void main(String[] args) { + SpringApplication.run(SimpleCoreApplication.class, args); + } + + public static class Greeting { + + private final String message; + + public Greeting(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + } + +} diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/src/main/resources/application.yml b/spring-cloud-kubernetes-integration-tests/simple-core/src/main/resources/application.yml new file mode 100644 index 00000000..86f053fc --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-core/src/main/resources/application.yml @@ -0,0 +1,9 @@ +server: + port: 8080 + +# we enable some of the management endpoints to make it possible to restart the application +management: + endpoint: + health: + enabled: true + show-details: always diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/src/test/java/org/springframework/cloud/kubernetes/it/GreetingAndHealthIT.java b/spring-cloud-kubernetes-integration-tests/simple-core/src/test/java/org/springframework/cloud/kubernetes/it/GreetingAndHealthIT.java new file mode 100644 index 00000000..8dc3da57 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-core/src/test/java/org/springframework/cloud/kubernetes/it/GreetingAndHealthIT.java @@ -0,0 +1,39 @@ +package org.springframework.cloud.kubernetes.it; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.core.Is.is; + +import org.arquillian.cube.kubernetes.impl.requirement.RequiresKubernetes; +import org.jboss.arquillian.junit.Arquillian; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RequiresKubernetes +@RunWith(Arquillian.class) +public class GreetingAndHealthIT { + + private static final String HOST = System.getProperty("service.host"); + private static final Integer PORT = Integer.valueOf(System.getProperty("service.port")); + + @Test + public void testGreetingEndpoint() { + given() + .baseUri(String.format("http://%s:%d", HOST, PORT)) + .get("greeting") + .then() + .statusCode(200) + .body("message", is("Hello Spring Boot")); + } + + @Test + public void testHealthEndpoint() { + given() + .baseUri(String.format("http://%s:%d", HOST, PORT)) + .contentType("application/json") + .get("actuator/health") + .then() + .statusCode(200) + .body("details.kubernetes.details.inside", is(true)); + } + +} diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/src/test/resources/arquillian.xml b/spring-cloud-kubernetes-integration-tests/simple-core/src/test/resources/arquillian.xml new file mode 100644 index 00000000..4694db07 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-core/src/test/resources/arquillian.xml @@ -0,0 +1,13 @@ + + + + default + + + false + false + + + diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/simple-core/src/test/resources/logback-test.xml new file mode 100644 index 00000000..9f754ed5 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-core/src/test/resources/logback-test.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file