diff --git a/.circleci/config.yml b/.circleci/config.yml
index 3a3b866c..5867c49e 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -22,9 +22,12 @@ workflows:
build-then-test:
jobs:
- build
- - test:
+ - fabric8_istio:
requires:
- build
+ - test:
+ requires:
+ - fabric8_istio
jobs:
test:
parallelism: 5 # parallel containers to split the tests among
@@ -34,11 +37,35 @@ jobs:
_JAVA_OPTIONS: "-Xms1024m -Xmx2048m"
_SERVICE_OCCURENCE: 5
steps:
+ - run:
+ name: testcontainers reuse support
+ command: |
+ # needed for .withReuse(true) to work
+ echo "testcontainers.reuse.enable=true" > ~/.testcontainers.properties
- checkout
+ - attach_workspace:
+ at: /tmp/docker
+ - run:
+ name: Load Controller Images From Workspace
+ command: |
+ VIEW=$(ls -l /tmp/docker/images)
+ echo "${VIEW}"
+ docker load -i /tmp/docker/images/spring-cloud-kubernetes-configuration-watcher.tar
+ docker load -i /tmp/docker/images/spring-cloud-kubernetes-discoveryserver.tar
+ docker load -i /tmp/docker/images/spring-cloud-kubernetes-configserver.tar
- run:
name: Run regular tests
command: |
- CLASSNAMES=$(circleci tests glob "**/src/test/**/**.java" | grep -v 'spring-cloud-kubernetes-integration-tests' \
+
+ ###########################################################################################################################
+ ################################################# Build test support dependency ###########################################
+ cd spring-cloud-kubernetes-test-support
+ .././mvnw clean install
+ cd ..
+
+ ###########################################################################################################################
+ ##################################################### Split and run tests #################################################
+ CLASSNAMES=$(circleci tests glob "**/src/test/**/**.java" | grep -v 'Fabric8IstioIT' \
| xargs grep -l '@Test' \
| sed 's/.*src.test.java.//g' | sed 's@/@.@g' \
| sed 's/.\{5\}$//' \
@@ -46,25 +73,14 @@ jobs:
echo $CLASSNAMES
TEST_ARG=$(echo $CLASSNAMES | sed 's/ /,/g')
echo $TEST_ARG
- ./mvnw -s .settings.xml -DfailIfNoTests=false -DtestsToRun=$TEST_ARG -e clean org.jacoco:jacoco-maven-plugin:prepare-agent test -U -P sonar -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
+ ./mvnw -s .settings.xml -DfailIfNoTests=false -DtestsToRun=$TEST_ARG -e clean 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)
- kube-orb/install-kubectl
- - attach_workspace:
- at: ./
- - run:
- name: Load Controller Images From Workspace
- command: |
- docker load -i ./docker-images/spring-cloud-kubernetes-configuration-watcher.tar
- docker load -i ./docker-images/spring-cloud-kubernetes-discoveryserver.tar
- docker load -i ./docker-images/spring-cloud-kubernetes-configserver.tar
- - run:
- name: Run Kind Integration Tests
- command: |
- cd spring-cloud-kubernetes-integration-tests
- ./run.sh
- run:
name: "Aggregate test results"
when: always
@@ -104,17 +120,56 @@ jobs:
command: |
TAG=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)
echo $TAG
- mkdir docker-images
- docker save -o docker-images/spring-cloud-kubernetes-configuration-watcher.tar docker.io/springcloud/spring-cloud-kubernetes-configuration-watcher:${TAG}
- docker save -o docker-images/spring-cloud-kubernetes-discoveryserver.tar docker.io/springcloud/spring-cloud-kubernetes-discoveryserver:${TAG}
- docker save -o docker-images/spring-cloud-kubernetes-configserver.tar docker.io/springcloud/spring-cloud-kubernetes-configserver:${TAG}
+ mkdir -p /tmp/docker/images/
+ docker save -o /tmp/docker/images/spring-cloud-kubernetes-configuration-watcher.tar docker.io/springcloud/spring-cloud-kubernetes-configuration-watcher:${TAG}
+ docker save -o /tmp/docker/images/spring-cloud-kubernetes-discoveryserver.tar docker.io/springcloud/spring-cloud-kubernetes-discoveryserver:${TAG}
+ docker save -o /tmp/docker/images/spring-cloud-kubernetes-configserver.tar docker.io/springcloud/spring-cloud-kubernetes-configserver:${TAG}
+ VIEW=$(ls -l /tmp/docker/images)
+ echo "${VIEW}"
- persist_to_workspace:
- root: ./
- paths: docker-images
+ root: /tmp/docker/
+ paths:
+ - images
- save_cache:
paths:
- ~/.m2
key: spring-cloud-kubernetes-{{ .Branch }}-{{ checksum "pom.xml" }}
+ fabric8_istio:
+ machine:
+ image: ubuntu-2004:202201-02
+ steps:
+ - run:
+ name: Install OpenJDK 17
+ command: |
+ wget -qO - https://adoptium.jfrog.io/adoptium/api/gpg/key/public | sudo apt-key add -
+ sudo add-apt-repository --yes https://adoptium.jfrog.io/adoptium/deb/
+ sudo apt-get update && sudo apt-get install temurin-17-jdk
+ sudo update-alternatives --set java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java
+ sudo update-alternatives --set javac /usr/lib/jvm/temurin-17-jdk-amd64/bin/javac
+ java -version
+ - checkout
+ - restore_cache:
+ keys:
+ - spring-cloud-kubernetes-{{ .Branch }}-{{ checksum "pom.xml" }}
+ - spring-cloud-kubernetes-{{ .Branch }}
+ - spring-cloud-kubernetes
+ - run:
+ name: Run fabric8 istio test
+ command: |
+
+ # we need to run some test, so that K3s container is started and then all other instances will re-use this one.
+ # otherwise (since we use static ports) there might be two instances starting at the same time, and ports might conflict
+ # this also deals with a slightly more involved istio set-up that is needed for this test
+
+ ###########################################################################################################################
+ ######################################## Build test support dependency and Run test #######################################
+ cd spring-cloud-kubernetes-test-support
+ .././mvnw clean install
+ cd ..
+
+ cd spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/
+ ../.././mvnw clean install
+ cd ../..
notify:
webhooks:
- url: https://webhooks.gitter.im/e/22e6bb4eb945dd61ba54
diff --git a/.circleci/istio-test-namespace.yml b/.circleci/istio-test-namespace.yml
deleted file mode 100644
index a9421811..00000000
--- a/.circleci/istio-test-namespace.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-apiVersion: v1
-kind: Namespace
-metadata:
- name: istio-test
- labels:
- istio-injection: enabled
\ No newline at end of file
diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml
new file mode 100644
index 00000000..f1fe0c26
--- /dev/null
+++ b/.github/workflows/maven.yaml
@@ -0,0 +1,42 @@
+# This workflow will build a Java project with Maven
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+
+name: Build
+
+on:
+ push:
+ branches: [ main ]
+ pull_request:
+ branches: [ main ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up JDK
+ uses: actions/setup-java@v2
+ with:
+ distribution: 'temurin'
+ java-version: '17'
+ - name: Cache local Maven repository
+ uses: actions/cache@v2
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+ - name: Build with Maven
+ run: ./mvnw -s .settings.xml clean 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
+ - name: Publish Test Report
+ uses: mikepenz/action-junit-report@v2
+ if: always() # always run even if the previous step fails
+ with:
+ report_paths: '**/surefire-reports/TEST-*.xml'
+ - name: Archive code coverage results
+ uses: actions/upload-artifact@v2
+ with:
+ name: surefire-reports
+ path: '**/surefire-reports/*'
diff --git a/istio-cli/istio-1.13.3/bin/istioctl b/istio-cli/istio-1.13.3/bin/istioctl
new file mode 100755
index 00000000..0319896a
Binary files /dev/null and b/istio-cli/istio-1.13.3/bin/istioctl differ
diff --git a/pom.xml b/pom.xml
index 6b558734..ced5fbc1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -76,14 +76,11 @@
2.4.12
3.0.2
- **/*IT.java
-
true
true
true
- **/*IT.java
@@ -199,14 +196,9 @@
all
false
-
-
${testsToRun}
-
- ${excludeITTests}
-
@@ -359,16 +351,6 @@
all
false
-
-
-
- ${testsToRun}
-
-
- ${surefireArgLine}
-
- ${excludeITTests}
-
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/resources/application-bus-amqp.yaml b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/resources/application-bus-amqp.yaml
index eed3c25d..f8da3850 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/resources/application-bus-amqp.yaml
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/resources/application-bus-amqp.yaml
@@ -8,3 +8,4 @@ management:
health:
rabbit:
enabled: true
+
diff --git a/spring-cloud-kubernetes-integration-tests/kind-config.yaml b/spring-cloud-kubernetes-integration-tests/kind-config.yaml
deleted file mode 100644
index 93efbb38..00000000
--- a/spring-cloud-kubernetes-integration-tests/kind-config.yaml
+++ /dev/null
@@ -1,28 +0,0 @@
-# this config file contains all config fields with comments
-# NOTE: this is not a particularly useful config file
-kind: Cluster
-apiVersion: kind.x-k8s.io/v1alpha4
-containerdConfigPatches:
-- |-
- [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:5000"]
- endpoint = ["http://kind-registry:5000"]
-
-# 1 control plane node and 3 workers
-nodes:
- - role: control-plane
- image: kindest/node:v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6
- kubeadmConfigPatches:
- - |
- kind: InitConfiguration
- nodeRegistration:
- kubeletExtraArgs:
- node-labels: "ingress-ready=true"
- extraPortMappings:
- - containerPort: 80
- hostPort: 80
- protocol: TCP
- - containerPort: 443
- hostPort: 443
- protocol: TCP
- - role: worker
- image: kindest/node:v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6
diff --git a/spring-cloud-kubernetes-integration-tests/permissions.yaml b/spring-cloud-kubernetes-integration-tests/permissions.yaml
deleted file mode 100644
index 89f99255..00000000
--- a/spring-cloud-kubernetes-integration-tests/permissions.yaml
+++ /dev/null
@@ -1,68 +0,0 @@
----
-apiVersion: v1
-kind: List
-items:
- - apiVersion: v1
- kind: ServiceAccount
- metadata:
- labels:
- app: integration-test
- name: spring-cloud-kubernetes-serviceaccount
- - apiVersion: rbac.authorization.k8s.io/v1
- kind: RoleBinding
- metadata:
- labels:
- app: spring-cloud-kubernetes-core-k8s-client-it
- name: spring-cloud-kubernetes-core-k8s-client-it:view
- roleRef:
- kind: Role
- apiGroup: rbac.authorization.k8s.io
- name: namespace-reader
- subjects:
- - kind: ServiceAccount
- name: spring-cloud-kubernetes-serviceaccount
- namespace: default
- - apiVersion: rbac.authorization.k8s.io/v1
- kind: Role
- metadata:
- namespace: default
- name: namespace-reader
- rules:
- - apiGroups: ["", "extensions", "apps"]
- resources: ["configmaps", "pods", "services", "endpoints", "secrets"]
- verbs: ["get", "list", "watch"]
-
- # needed for istio
-
- - apiVersion: v1
- kind: ServiceAccount
- metadata:
- labels:
- app: istio-integration-test
- name: spring-cloud-kubernetes-istio-serviceaccount
- namespace: istio-test
-
- - apiVersion: rbac.authorization.k8s.io/v1
- kind: Role
- metadata:
- namespace: istio-test
- name: istio-test
- rules:
- - apiGroups: [ "", "extensions", "apps" ]
- resources: [ "configmaps", "pods", "services", "endpoints", "secrets" ]
- verbs: [ "get", "list", "watch" ]
-
- - apiVersion: rbac.authorization.k8s.io/v1
- kind: RoleBinding
- metadata:
- labels:
- app: spring-cloud-kubernetes-core-k8s-client-it
- name: istio-test-rb
- roleRef:
- kind: Role
- apiGroup: rbac.authorization.k8s.io
- name: istio-test
- subjects:
- - kind: ServiceAccount
- name: spring-cloud-kubernetes-istio-serviceaccount
- namespace: istio-test
diff --git a/spring-cloud-kubernetes-integration-tests/pom.xml b/spring-cloud-kubernetes-integration-tests/pom.xml
index be9bc23f..f2cc8862 100644
--- a/spring-cloud-kubernetes-integration-tests/pom.xml
+++ b/spring-cloud-kubernetes-integration-tests/pom.xml
@@ -13,31 +13,16 @@
pom
Spring Cloud Kubernetes :: Integration Tests
- Integration tests where SCK applications are run inside a Kubernetes
- cluster
-
+ Integration tests where SCK applications are run inside a Kubernetes cluster
17
- 1.18.2
- 1.4.0.Final
- 3.12.12
- 3.2.2
-
-
- 32222
+ 3.2.13
+ 1.16.3
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
org.apache.maven.plugins
maven-deploy-plugin
@@ -46,7 +31,6 @@
true
-
@@ -79,34 +63,6 @@
-
- it
-
-
-
- org.apache.maven.plugins
- maven-failsafe-plugin
-
-
- localhost
- ${nodeport.value}
- false
-
- ${project.build.outputDirectory}
-
-
-
-
-
- integration-test
- verify
-
-
-
-
-
-
-
@@ -123,6 +79,24 @@
${docker-java.version}
test
+
+ org.testcontainers
+ testcontainers
+ ${testcontainers.version}
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ ${testcontainers.version}
+ test
+
+
+ org.testcontainers
+ k3s
+ ${testcontainers.version}
+ test
+
@@ -134,11 +108,10 @@
spring-cloud-kubernetes-fabric8-client-discovery
spring-cloud-kubernetes-fabric8-client-loadbalancer
- spring-cloud-kubernetes-discovery-client-it
- spring-cloud-kubernetes-reactive-discovery-client-it
+ spring-cloud-kubernetes-discoveryclient-it
spring-cloud-kubernetes-client-config-it
spring-cloud-kubernetes-client-loadbalancer-it
- spring-cloud-kubernetes-client-reactive-discovery-client-it
+ spring-cloud-kubernetes-client-reactive-discoveryclient-it
spring-cloud-kubernetes-configuration-watcher-it
spring-cloud-kubernetes-core-k8s-client-it
diff --git a/spring-cloud-kubernetes-integration-tests/run.sh b/spring-cloud-kubernetes-integration-tests/run.sh
deleted file mode 100755
index 7e4cf3e2..00000000
--- a/spring-cloud-kubernetes-integration-tests/run.sh
+++ /dev/null
@@ -1,199 +0,0 @@
-#!/bin/bash
-
-# standard bash error handling
-set -o errexit;
-set -o pipefail;
-set -o nounset;
-# debug commands
-set -x;
-
-# working dir to install binaries etc, cleaned up on exit
-BIN_DIR="$(mktemp -d)"
-# kind binary will be here
-KIND="${BIN_DIR}/kind"
-
-ISTIO="${BIN_DIR}/istio"
-
-CURRENT_DIR="$(pwd)"
-
-MVN="${CURRENT_DIR}/../mvnw"
-
-PROJECT_VERSION=$($MVN help:evaluate -Dexpression=project.version -q -DforceStdout)
-
-ISTIO_VERSION="1.12.0"
-
-ALL_INTEGRATION_PROJECTS=(
- "spring-cloud-kubernetes-core-k8s-client-it"
- "spring-cloud-kubernetes-client-config-it"
- "spring-cloud-kubernetes-configuration-watcher-it"
- "spring-cloud-kubernetes-client-loadbalancer-it"
- "spring-cloud-kubernetes-client-reactive-discovery-client-it"
- "spring-cloud-kubernetes-discovery-client-it"
- "spring-cloud-kubernetes-reactive-discovery-client-it"
- "spring-cloud-kubernetes-fabric8-client-simple-core"
- "spring-cloud-kubernetes-fabric8-client-configmap"
- "spring-cloud-kubernetes-fabric8-istio-it"
- "spring-cloud-kubernetes-fabric8-client-discovery"
- "spring-cloud-kubernetes-fabric8-client-loadbalancer"
-)
-INTEGRATION_PROJECTS=(${INTEGRATION_PROJECTS:-${ALL_INTEGRATION_PROJECTS[@]}})
-
-DEFAULT_PULLING_IMAGES=(
- "jettech/kube-webhook-certgen:v1.2.2"
- "rabbitmq:3-management"
- "zookeeper:3.6.2"
- "rodolpheche/wiremock:2.27.2"
- "wurstmeister/kafka:2.13-2.6.0"
- "istio/proxyv2:${ISTIO_VERSION}"
- "istio/pilot:${ISTIO_VERSION}"
-)
-PULLING_IMAGES=(${PULLING_IMAGES:-${DEFAULT_PULLING_IMAGES[@]}})
-
-LOADING_IMAGES=(${LOADING_IMAGES:-${DEFAULT_PULLING_IMAGES[@]}} "docker.io/springcloud/spring-cloud-kubernetes-configuration-watcher:${PROJECT_VERSION}"
- "docker.io/springcloud/spring-cloud-kubernetes-discoveryserver:${PROJECT_VERSION}")
-# cleanup on exit (useful for running locally)
-
-cleanup() {
- "${KIND}" delete cluster || true
- rm -rf "${BIN_DIR}"
-}
-trap cleanup EXIT
-
-# util to install the latest kind version into ${BIN_DIR}
-install_latest_kind() {
- # clone kind into a tempdir within BIN_DIR
- local tmp_dir
- tmp_dir="$(TMPDIR="${BIN_DIR}" mktemp -d "${BIN_DIR}/kind-source.XXXXX")"
- cd "${tmp_dir}" || exit
- git clone https://github.com/kubernetes-sigs/kind && cd ./kind
- make install INSTALL_DIR="${BIN_DIR}"
-}
-
-# util to install a released kind version into ${BIN_DIR}
-install_kind_release() {
- VERSION="v0.11.1"
- KIND_BINARY_URL="https://github.com/kubernetes-sigs/kind/releases/download/${VERSION}/kind-linux-amd64"
- if [[ "$OSTYPE" == "darwin"* ]]; then
- KIND_BINARY_URL="https://github.com/kubernetes-sigs/kind/releases/download/${VERSION}/kind-darwin-amd64"
- elif [[ "$OSTYPE" == "cygwin" ]]; then
- KIND_BINARY_URL="https://github.com/kubernetes-sigs/kind/releases/download/${VERSION}/kind-windows-amd64"
- elif [[ "$OSTYPE" == "msys" ]]; then
- KIND_BINARY_URL="https://github.com/kubernetes-sigs/kind/releases/download/${VERSION}/kind-windows-amd64"
- elif [[ "$OSTYPE" == "win32" ]]; then
- KIND_BINARY_URL="https://github.com/kubernetes-sigs/kind/releases/download/${VERSION}/kind-windows-amd64"
- else
- echo "Unknown OS, using linux binary"
- fi
- wget -O "${KIND}" "${KIND_BINARY_URL}"
- chmod +x "${KIND}"
-}
-
-# util to install a released istio version into ${BIN_DIR}
-install_istio_release() {
- ISTIO_BINARY_URL="https://github.com/istio/istio/releases/download/$ISTIO_VERSION/istio-$ISTIO_VERSION-linux-amd64.tar.gz"
- if [[ "$OSTYPE" == "darwin"* ]]; then
- ISTIO_BINARY_URL="https://github.com/istio/istio/releases/download/$ISTIO_VERSION/istio-$ISTIO_VERSION-osx-arm64.tar.gz"
- else
- echo "Unknown OS, using linux binary"
- fi
- # seems like wget can't do both --output-document and --directory-prefix? At least on my Mac
- # this is the case. To be on the safe side, download, then rename
- wget --directory-prefix "${ISTIO}" "${ISTIO_BINARY_URL}"
- find "${ISTIO}" -type f -name "istio-*.tar.gz" -exec mv "{}" "${ISTIO}/istio.tar.gz" \;
- tar -xf "$BIN_DIR/istio/istio.tar.gz" -C "$BIN_DIR/istio"
- chmod +x "${ISTIO}/istio-$ISTIO_VERSION/bin/istioctl"
- export PATH=$PATH:"$ISTIO/istio-$ISTIO_VERSION/bin"
-
- if ! [ -x "$(command -v istioctl)" ]; then
- echo 'Problem installing istioctl, check the script'
- exit 1
- fi
-}
-
-enable_istio() {
- kubectl create namespace istio-test
- kubectl label namespace istio-test istio-injection=enabled
- install_istio_release
- # remove taint, otherwise istio will not start
- kubectl taint node kind-control-plane node-role.kubernetes.io/master:NoSchedule-
-
- # for Mac M1 : https://github.com/istio/istio/issues/21094#issuecomment-956117650
- istioctl install --set profile=demo -y
-}
-
-main() {
- # get kind
- install_kind_release
-
- # create a cluster
- cd $CURRENT_DIR
-
- #TODO what happens if cluster is already there????
- "${KIND}" create cluster --config=kind-config.yaml -v 2147483647
-
- # set KUBECONFIG to point to the cluster
- kubectl cluster-info --context kind-kind
-
- # pulling necessary images for setting up the integration test environment
- for i in "${PULLING_IMAGES[@]}"; do
- echo "Pull images for prepping testing environment: $i"
- docker pull $i
- done
- for i in "${LOADING_IMAGES[@]}"; do
- echo "Loading images into Kind: $i"
- "${KIND}" load docker-image $i
- done
-
- # istio
- install_istio_release
- enable_istio
-
- #setup nginx ingress
- kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
- sleep 5 # hold 5 sec so that the pods can be created
- kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=420s
-
-
-
- # This creates the service account, role, and role binding necessary for Spring Cloud k8s apps
- kubectl apply -f ./permissions.yaml
-
- # cd ${BIN_DIR}
- # curl -L https://istio.io/downloadIstio | sh -
- #"${ISTIOCTL}" install --set profile=demo
-
- # running tests..
- if [[ -z ${CIRCLECI+x} ]]; then
- run_tests "${INTEGRATION_PROJECTS[@]}"
- else
- #This splits projects across all circleci instances, it returns a list of projects separated by a space
- SPLIT_PROJECTS=$(printf "%s\n" "${INTEGRATION_PROJECTS[@]}" | circleci tests split)
- SPLIT_PROJECTS=$(echo $SPLIT_PROJECTS | sed 's/ /,/g')
- echo "split tests $SPLIT_PROJECTS"
- #This splits the projects back into an array so we can iterate over them
- IFS=',' read -ra PROJECTS <<< "$SPLIT_PROJECTS"
- echo "${PROJECTS[@]}"
- run_tests "${PROJECTS[@]}"
- fi
-
- # teardown will happen automatically on exit
-}
-
-run_tests() {
- arr=("$@")
- cd ../spring-cloud-kubernetes-test-support
- ${MVN} clean install
- cd ../spring-cloud-kubernetes-integration-tests
- for p in "${arr[@]}"; do
- echo "Running test: $p"
- cd $p
- ${MVN} spring-boot:build-image \
- -Dspring-boot.build-image.imageName=docker.io/springcloud/$p:${PROJECT_VERSION} -Dspring-boot.build-image.builder=paketobuildpacks/builder
- "${KIND}" load docker-image docker.io/springcloud/$p:${PROJECT_VERSION}
- # empty excludeITTests, so that integration tests will run
- ${MVN} clean install -DexcludeITTests=
- cd ..
- done
-}
-
-main
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/pom.xml
index 3007530d..0d255972 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/pom.xml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/pom.xml
@@ -5,8 +5,9 @@
org.springframework.cloud
spring-cloud-kubernetes-integration-tests
-3.0.0-SNAPSHOT
+ 3.0.0-SNAPSHOT
+
4.0.0
spring-cloud-kubernetes-client-config-it
@@ -51,6 +52,22 @@
test
+
+ org.testcontainers
+ testcontainers
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+ org.testcontainers
+ k3s
+ test
+
+
@@ -64,6 +81,56 @@
true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ docker.io/springcloud/${project.artifactId}:${project.version}
+ paketobuildpacks/builder
+
+
+
+ package
+
+ build-image
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+
+
+
+ ${testsToRun}
+
+
+
+
+
+
+
+
@@ -103,6 +170,7 @@
springcloud/${project.artifactId}:${project.version}
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/application.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/application.yaml
index e81b66d5..7ea719a7 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/application.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/application.yaml
@@ -3,9 +3,3 @@ management:
web:
exposure:
include: "*"
-#logging:
-# level:
-# org:
-# springframework:
-# cloud:
-# kubernetes: DEBUG
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/bootstrap-kubernetes.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/bootstrap-kubernetes.yaml
index 723f28c9..7df1beb5 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/bootstrap-kubernetes.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/bootstrap-kubernetes.yaml
@@ -1,7 +1,6 @@
spring:
cloud:
kubernetes:
- enabled: true
secrets:
enable-api: true
reload:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/bootstrap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/bootstrap.yaml
index d4075ec0..1a857f32 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/bootstrap.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/bootstrap.yaml
@@ -1,7 +1,4 @@
spring:
application:
name: spring-cloud-kubernetes-client-config-it
- cloud:
- kubernetes:
- enabled: false
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/java/org/springframework/cloud/kubernetes/client/config/it/ConfigMapAndSecretIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/java/org/springframework/cloud/kubernetes/client/config/it/ConfigMapAndSecretIT.java
index 19a3949f..bec7030e 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/java/org/springframework/cloud/kubernetes/client/config/it/ConfigMapAndSecretIT.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/java/org/springframework/cloud/kubernetes/client/config/it/ConfigMapAndSecretIT.java
@@ -16,11 +16,10 @@
package org.springframework.cloud.kubernetes.client.config.it;
-import java.io.IOException;
import java.time.Duration;
import java.util.Map;
+import java.util.Objects;
-import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.apis.AppsV1Api;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.apis.NetworkingV1Api;
@@ -29,29 +28,34 @@ import io.kubernetes.client.openapi.models.V1Deployment;
import io.kubernetes.client.openapi.models.V1Ingress;
import io.kubernetes.client.openapi.models.V1Secret;
import io.kubernetes.client.openapi.models.V1Service;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.testcontainers.k3s.K3sContainer;
+import org.testcontainers.shaded.org.awaitility.Awaitility;
+import reactor.netty.http.client.HttpClient;
+import reactor.util.retry.Retry;
+import reactor.util.retry.RetryBackoffSpec;
-import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.web.client.ResponseErrorHandler;
-import org.springframework.web.client.RestTemplate;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.awaitility.Awaitility.await;
import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient;
import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion;
/**
* @author Ryan Baxter
*/
-public class ConfigMapAndSecretIT {
+class ConfigMapAndSecretIT {
- private static final Log LOG = LogFactory.getLog(ConfigMapAndSecretIT.class);
+ private static final String PROPERTY_URL = "localhost:80/myProperty";
+
+ private static final String SECRET_URL = "localhost:80/mySecret";
private static final String SPRING_CLOUD_CLIENT_CONFIG_IT_DEPLOYMENT_NAME = "spring-cloud-kubernetes-client-config-it-deployment";
@@ -61,15 +65,8 @@ public class ConfigMapAndSecretIT {
private static final String NAMESPACE = "default";
- private static final String MYPROPERTY_URL = "http://localhost:80/client-config-it/myProperty";
-
- private static final String MYSECRET_URL = "http://localhost:80/client-config-it/mySecret";
-
private static final String APP_NAME = "spring-cloud-kubernetes-client-config-it";
- // though not obvious, we need this, even if it is "unused"
- private static ApiClient client;
-
private static CoreV1Api api;
private static AppsV1Api appsApi;
@@ -78,17 +75,28 @@ public class ConfigMapAndSecretIT {
private static K8SUtils k8SUtils;
+ private static final K3sContainer K3S = Commons.container();
+
@BeforeAll
- public static void setup() throws Exception {
- client = createApiClient();
+ static void setup() throws Exception {
+ K3S.start();
+ Commons.validateImage(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, K3S);
+ Commons.loadImage(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, K3S);
+ createApiClient(K3S.getKubeConfigYaml());
api = new CoreV1Api();
appsApi = new AppsV1Api();
networkingApi = new NetworkingV1Api();
k8SUtils = new K8SUtils(api, appsApi);
+ k8SUtils.setUp(NAMESPACE);
+ }
+
+ @AfterAll
+ static void afterAll() throws Exception {
+ Commons.cleanUp(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, K3S);
}
@AfterEach
- public void after() throws Exception {
+ void after() throws Exception {
appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
"metadata.name=" + K8S_CONFIG_CLIENT_IT_NAME, null, null, null, null, null, null, null, null, null);
api.deleteNamespacedService(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, NAMESPACE, null, null, null, null, null, null);
@@ -97,56 +105,8 @@ public class ConfigMapAndSecretIT {
api.deleteNamespacedSecret(APP_NAME, NAMESPACE, null, null, null, null, null, null);
}
- public void testConfigMapAndSecretRefresh() throws Exception {
-
- RestTemplate rest = new RestTemplateBuilder().build();
- rest.setErrorHandler(new ResponseErrorHandler() {
- @Override
- public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
- LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
- return clientHttpResponse.getRawStatusCode() != 503;
- }
-
- @Override
- public void handleError(ClientHttpResponse clientHttpResponse) {
-
- }
- });
-
- // Sometimes the NGINX ingress takes a bit to catch up and realize the service is
- // available and we get a 503, we just need to wait a bit
- await().timeout(Duration.ofSeconds(60)).pollInterval(Duration.ofSeconds(2))
- .until(() -> rest.getForEntity(MYPROPERTY_URL, String.class).getStatusCode().is2xxSuccessful());
-
- String myProperty = rest.getForObject(MYPROPERTY_URL, String.class);
- assertThat(myProperty).isEqualTo("from-config-map");
- String mySecret = rest.getForObject(MYSECRET_URL, String.class);
- assertThat(mySecret).isEqualTo("p455w0rd");
-
- V1ConfigMap configMap = getConfigK8sClientItConfigMap();
- Map data = configMap.getData();
- data.replace("application.yaml", data.get("application.yaml").replace("from-config-map", "from-unit-test"));
- configMap.data(data);
- api.replaceNamespacedConfigMap(APP_NAME, NAMESPACE, configMap, null, null, null);
- await().timeout(Duration.ofSeconds(60)).pollInterval(Duration.ofSeconds(2))
- .until(() -> rest.getForObject(MYPROPERTY_URL, String.class).equals("from-unit-test"));
- myProperty = rest.getForObject(MYPROPERTY_URL, String.class);
- assertThat(myProperty).isEqualTo("from-unit-test");
-
- V1Secret secret = getConfigK8sClientItCSecret();
- Map secretData = secret.getData();
- secretData.replace("my.config.mySecret", "p455w1rd".getBytes());
- secret.setData(secretData);
- api.replaceNamespacedSecret(APP_NAME, NAMESPACE, secret, null, null, null);
- await().timeout(Duration.ofSeconds(60)).pollInterval(Duration.ofSeconds(2))
- .until(() -> rest.getForObject(MYSECRET_URL, String.class).equals("p455w1rd"));
- mySecret = rest.getForObject(MYSECRET_URL, String.class);
- assertThat(mySecret).isEqualTo("p455w1rd");
-
- }
-
@Test
- public void testConfigMapAndSecretWatchRefresh() throws Exception {
+ void testConfigMapAndSecretWatchRefresh() throws Exception {
deployConfigK8sClientIt();
// Check to make sure the controller deployment is ready
@@ -155,7 +115,7 @@ public class ConfigMapAndSecretIT {
}
@Test
- public void testConfigMapAndSecretPollingRefresh() throws Exception {
+ void testConfigMapAndSecretPollingRefresh() throws Exception {
deployConfigK8sClientPollingIt();
// Check to make sure the controller deployment is ready
@@ -163,13 +123,47 @@ public class ConfigMapAndSecretIT {
testConfigMapAndSecretRefresh();
}
+ void testConfigMapAndSecretRefresh() throws Exception {
+
+ WebClient.Builder builder = builder();
+ WebClient propertyClient = builder.baseUrl(PROPERTY_URL).build();
+
+ String property = propertyClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class)
+ .retryWhen(retrySpec()).block();
+ assertThat(property).isEqualTo("from-config-map");
+
+ WebClient secretClient = builder.baseUrl(SECRET_URL).build();
+ String secret = secretClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
+ .block();
+ assertThat(secret).isEqualTo("p455w0rd");
+
+ V1ConfigMap configMap = getConfigK8sClientItConfigMap();
+ Map data = configMap.getData();
+ data.replace("application.yaml", data.get("application.yaml").replace("from-config-map", "from-unit-test"));
+ configMap.data(data);
+ api.replaceNamespacedConfigMap(APP_NAME, NAMESPACE, configMap, null, null, null);
+ Awaitility.await().timeout(Duration.ofSeconds(60)).pollInterval(Duration.ofSeconds(2))
+ .until(() -> propertyClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).block()
+ .equals("from-unit-test"));
+ V1Secret v1Secret = getConfigK8sClientItCSecret();
+ Map secretData = v1Secret.getData();
+ secretData.replace("my.config.mySecret", "p455w1rd".getBytes());
+ v1Secret.setData(secretData);
+ api.replaceNamespacedSecret(APP_NAME, NAMESPACE, v1Secret, null, null, null);
+ Awaitility.await().timeout(Duration.ofSeconds(60)).pollInterval(Duration.ofSeconds(2)).until(() -> secretClient
+ .method(HttpMethod.GET).retrieve().bodyToMono(String.class).block().equals("p455w1rd"));
+ }
+
private static void deployConfigK8sClientIt() throws Exception {
k8SUtils.waitForDeploymentToBeDeleted(K8S_CONFIG_CLIENT_IT_NAME, NAMESPACE);
api.createNamespacedSecret(NAMESPACE, getConfigK8sClientItCSecret(), null, null, null);
api.createNamespacedConfigMap(NAMESPACE, getConfigK8sClientItConfigMap(), null, null, null);
appsApi.createNamespacedDeployment(NAMESPACE, getConfigK8sClientItDeployment(), null, null, null);
api.createNamespacedService(NAMESPACE, getConfigK8sClientItService(), null, null, null);
- networkingApi.createNamespacedIngress(NAMESPACE, getConfigK8sClientItIngress(), null, null, null);
+
+ V1Ingress ingress = getConfigK8sClientItIngress();
+ networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null);
+ k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE);
}
private static void deployConfigK8sClientPollingIt() throws Exception {
@@ -215,4 +209,12 @@ public class ConfigMapAndSecretIT {
return (V1Secret) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-secret.yaml");
}
+ private WebClient.Builder builder() {
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
+ }
+
+ private RetryBackoffSpec retrySpec() {
+ return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
+ }
+
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..9e284876
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/logback-test.xml
@@ -0,0 +1,14 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-ingress.yaml
index d65600fc..083811f4 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-ingress.yaml
@@ -3,13 +3,11 @@ kind: Ingress
metadata:
name: it-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /client-config-it(/|$)(.*)
+ - path: /
pathType: Prefix
backend:
service:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/pom.xml
index de824a22..c779ad35 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/pom.xml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/pom.xml
@@ -48,6 +48,27 @@
test
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+
+ org.testcontainers
+ testcontainers
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+ org.testcontainers
+ k3s
+ test
+
+
@@ -61,6 +82,55 @@
true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ docker.io/springcloud/${project.artifactId}:${project.version}
+ paketobuildpacks/builder
+
+
+
+ package
+
+ build-image
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+
+
+
+
+
+ ${testsToRun}
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/KubernetesClientLoadBalancerApplicationIt.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/KubernetesClientLoadBalancerApplicationIt.java
index 0b75a1e4..728ee4a4 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/KubernetesClientLoadBalancerApplicationIt.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/KubernetesClientLoadBalancerApplicationIt.java
@@ -19,15 +19,18 @@ package org.springframework.cloud.kubernetes.client.loadbalancer.it;
import java.util.List;
import java.util.Map;
+import reactor.netty.http.client.HttpClient;
+
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.client.RestTemplate;
+import org.springframework.web.reactive.function.client.WebClient;
/**
* @author Ryan Baxter
@@ -37,6 +40,8 @@ import org.springframework.web.client.RestTemplate;
@RestController
public class KubernetesClientLoadBalancerApplicationIt {
+ private static final String URL = "http://servicea-wiremock/__admin/mappings";
+
private final DiscoveryClient discoveryClient;
public KubernetesClientLoadBalancerApplicationIt(DiscoveryClient discoveryClien) {
@@ -49,13 +54,15 @@ public class KubernetesClientLoadBalancerApplicationIt {
@Bean
@LoadBalanced
- RestTemplate restTemplate() {
- return new RestTemplateBuilder().build();
+ WebClient.Builder client() {
+ return WebClient.builder();
}
- @GetMapping("/servicea")
+ @GetMapping("/loadbalancer-it/servicea")
+ @SuppressWarnings("unchecked")
public Map greeting() {
- return restTemplate().getForObject("http://servicea-wiremock/__admin/mappings", Map.class);
+ return (Map) client().clientConnector(new ReactorClientHttpConnector(HttpClient.create()))
+ .baseUrl(URL).build().method(HttpMethod.GET).retrieve().bodyToMono(Map.class).block();
}
@GetMapping("/services")
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/LoadBalancerIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/LoadBalancerIT.java
index e15157bd..f58353ba 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/LoadBalancerIT.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/LoadBalancerIT.java
@@ -16,12 +16,10 @@
package org.springframework.cloud.kubernetes.client.loadbalancer.it;
-import java.io.IOException;
import java.time.Duration;
import java.util.Map;
-import java.util.concurrent.TimeUnit;
+import java.util.Objects;
-import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.apis.AppsV1Api;
import io.kubernetes.client.openapi.apis.CoreV1Api;
@@ -29,33 +27,34 @@ import io.kubernetes.client.openapi.apis.NetworkingV1Api;
import io.kubernetes.client.openapi.models.V1Deployment;
import io.kubernetes.client.openapi.models.V1Ingress;
import io.kubernetes.client.openapi.models.V1Service;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.testcontainers.k3s.K3sContainer;
+import reactor.netty.http.client.HttpClient;
+import reactor.util.retry.Retry;
+import reactor.util.retry.RetryBackoffSpec;
-import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.web.client.ResponseErrorHandler;
-import org.springframework.web.client.RestTemplate;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.core.ResolvableType;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.web.reactive.function.client.WebClient;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.awaitility.Awaitility.await;
import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient;
import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion;
/**
* @author Ryan Baxter
*/
-public class LoadBalancerIT {
+class LoadBalancerIT {
- private static final Log LOG = LogFactory.getLog(LoadBalancerIT.class);
-
- private static final String WIREMOCK_DEPLOYMENT_NAME = "servicea-wiremock-deployment";
-
- private static final String WIREMOCK_APP_NAME = "servicea-wiremock";
+ private static final String SERVICE_URL = "localhost:80/loadbalancer-it/servicea";
private static final String SPRING_CLOUD_K8S_LOADBALANCER_DEPLOYMENT_NAME = "spring-cloud-kubernetes-client-loadbalancer-it-deployment";
@@ -63,54 +62,56 @@ public class LoadBalancerIT {
private static final String NAMESPACE = "default";
- private ApiClient client;
+ private static CoreV1Api api;
- private CoreV1Api api;
+ private static AppsV1Api appsApi;
- private AppsV1Api appsApi;
+ private static NetworkingV1Api networkingApi;
- private NetworkingV1Api networkingApi;
+ private static K8SUtils k8SUtils;
- private K8SUtils k8SUtils;
+ private static final K3sContainer K3S = Commons.container();
+
+ @BeforeAll
+ static void beforeAll() throws Exception {
+ K3S.start();
+ Commons.validateImage(SPRING_CLOUD_K8S_LOADBALANCER_APP_NAME, K3S);
+ Commons.loadImage(SPRING_CLOUD_K8S_LOADBALANCER_APP_NAME, K3S);
+ createApiClient(K3S.getKubeConfigYaml());
+ api = new CoreV1Api();
+ appsApi = new AppsV1Api();
+ networkingApi = new NetworkingV1Api();
+ k8SUtils = new K8SUtils(api, appsApi);
+ k8SUtils.setUp(NAMESPACE);
+ }
+
+ @AfterAll
+ static void afterAll() throws Exception {
+ Commons.cleanUp(SPRING_CLOUD_K8S_LOADBALANCER_APP_NAME, K3S);
+ k8SUtils.removeWiremockImage();
+ }
@BeforeEach
- public void setup() throws Exception {
- this.client = createApiClient();
- this.api = new CoreV1Api();
- this.appsApi = new AppsV1Api();
- this.networkingApi = new NetworkingV1Api();
- this.k8SUtils = new K8SUtils(api, appsApi);
-
- deployWiremock();
-
- // Check to make sure the wiremock deployment is ready
- k8SUtils.waitForDeployment(WIREMOCK_DEPLOYMENT_NAME, NAMESPACE);
-
- // Check to see if endpoint is ready
- k8SUtils.waitForEndpointReady(WIREMOCK_APP_NAME, NAMESPACE);
+ void setup() throws Exception {
+ k8SUtils.deployWiremock(NAMESPACE, false);
+ }
+ @AfterEach
+ void afterEach() throws Exception {
+ cleanup();
+ k8SUtils.cleanUpWiremock(NAMESPACE);
}
@Test
- public void testLoadBalancerServiceMode() throws Exception {
- try {
- deployLoadbalancerServiceIt();
- testLoadBalancer();
- }
- finally {
- cleanup();
- }
+ void testLoadBalancerServiceMode() throws Exception {
+ deployLoadbalancerServiceIt();
+ testLoadBalancer();
}
@Test
- public void testLoadBalancerPodMode() throws Exception {
- try {
- deployLoadbalancerPodIt();
- testLoadBalancer();
- }
- finally {
- cleanup();
- }
+ void testLoadBalancerPodMode() throws Exception {
+ deployLoadbalancerPodIt();
+ testLoadBalancer();
}
private void cleanup() throws ApiException {
@@ -125,50 +126,37 @@ public class LoadBalancerIT {
private void testLoadBalancer() {
// Check to make sure the controller deployment is ready
k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_LOADBALANCER_DEPLOYMENT_NAME, NAMESPACE);
- RestTemplate rest = new RestTemplateBuilder().build();
- rest.setErrorHandler(new ResponseErrorHandler() {
- @Override
- public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
- LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
- return clientHttpResponse.getRawStatusCode() != 503;
- }
- @Override
- public void handleError(ClientHttpResponse clientHttpResponse) {
+ WebClient.Builder builder = builder();
+ WebClient serviceClient = builder.baseUrl(SERVICE_URL).build();
- }
- });
- // Sometimes the NGINX ingress takes a bit to catch up and realize the service is
- // available and we get a 503, we just need to wait a bit
- await().pollInterval(Duration.ofSeconds(1)).atMost(600, TimeUnit.SECONDS).ignoreExceptions()
- .until(() -> rest.getForEntity("http://localhost:80/loadbalancer-it/servicea", String.class)
- .getStatusCode().is2xxSuccessful());
- Map result = rest.getForObject("http://localhost:80/loadbalancer-it/servicea", Map.class);
- assertThat(result.containsKey("mappings")).isTrue();
- assertThat(result.containsKey("meta")).isTrue();
+ ResolvableType resolvableType = ResolvableType.forClassWithGenerics(Map.class, String.class, Object.class);
+ @SuppressWarnings("unchecked")
+ Map result = (Map) serviceClient.method(HttpMethod.GET).retrieve()
+ .bodyToMono(ParameterizedTypeReference.forType(resolvableType.getType())).retryWhen(retrySpec())
+ .block();
- }
-
- @AfterEach
- public void after() throws Exception {
- appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
- "metadata.name=" + WIREMOCK_DEPLOYMENT_NAME, null, null, null, null, null, null, null, null, null);
-
- api.deleteNamespacedService(WIREMOCK_APP_NAME, NAMESPACE, null, null, null, null, null, null);
- networkingApi.deleteNamespacedIngress("wiremock-ingress", NAMESPACE, null, null, null, null, null, null);
+ Assertions.assertThat(result.containsKey("mappings")).isTrue();
+ Assertions.assertThat(result.containsKey("meta")).isTrue();
}
private void deployLoadbalancerServiceIt() throws Exception {
appsApi.createNamespacedDeployment(NAMESPACE, getLoadbalancerServiceItDeployment(), null, null, null);
api.createNamespacedService(NAMESPACE, getLoadbalancerItService(), null, null, null);
- networkingApi.createNamespacedIngress(NAMESPACE, getLoadbalancerItIngress(), null, null, null);
+ deployIngress();
}
private void deployLoadbalancerPodIt() throws Exception {
appsApi.createNamespacedDeployment(NAMESPACE, getLoadbalancerPodItDeployment(), null, null, null);
api.createNamespacedService(NAMESPACE, getLoadbalancerItService(), null, null, null);
- networkingApi.createNamespacedIngress(NAMESPACE, getLoadbalancerItIngress(), null, null, null);
+ deployIngress();
+ }
+
+ private void deployIngress() throws Exception {
+ V1Ingress ingress = getLoadbalancerItIngress();
+ networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null);
+ k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE);
}
private V1Deployment getLoadbalancerServiceItDeployment() throws Exception {
@@ -189,12 +177,6 @@ public class LoadBalancerIT {
return deployment;
}
- private void deployWiremock() throws Exception {
- appsApi.createNamespacedDeployment(NAMESPACE, getWireockDeployment(), null, null, null);
- api.createNamespacedService(NAMESPACE, getWiremockAppService(), null, null, null);
- networkingApi.createNamespacedIngress(NAMESPACE, getWiremockIngress(), null, null, null);
- }
-
private V1Ingress getLoadbalancerItIngress() throws Exception {
return (V1Ingress) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-client-loadbalancer-it-ingress.yaml");
@@ -205,16 +187,12 @@ public class LoadBalancerIT {
.readYamlFromClasspath("spring-cloud-kubernetes-client-loadbalancer-it-service.yaml");
}
- private V1Ingress getWiremockIngress() throws Exception {
- return (V1Ingress) K8SUtils.readYamlFromClasspath("wiremock-ingress.yaml");
+ private WebClient.Builder builder() {
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
}
- private V1Service getWiremockAppService() throws Exception {
- return (V1Service) K8SUtils.readYamlFromClasspath("wiremock-service.yaml");
- }
-
- private V1Deployment getWireockDeployment() throws Exception {
- return (V1Deployment) K8SUtils.readYamlFromClasspath("wiremock-deployment.yaml");
+ private RetryBackoffSpec retrySpec() {
+ return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
}
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..9e284876
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/logback-test.xml
@@ -0,0 +1,14 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/spring-cloud-kubernetes-client-loadbalancer-it-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/spring-cloud-kubernetes-client-loadbalancer-it-ingress.yaml
index f63e9f03..8e44f4e6 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/spring-cloud-kubernetes-client-loadbalancer-it-ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/spring-cloud-kubernetes-client-loadbalancer-it-ingress.yaml
@@ -3,13 +3,11 @@ kind: Ingress
metadata:
name: it-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /loadbalancer-it(/|$)(.*)
+ - path: /loadbalancer-it/
pathType: Prefix
backend:
service:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-deployment.yaml
similarity index 92%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock-deployment.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-deployment.yaml
index 1dc89ac9..9d28eb62 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock-deployment.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-deployment.yaml
@@ -13,7 +13,7 @@ spec:
spec:
containers:
- name: servicea-wiremock
- image: rodolpheche/wiremock:2.27.2
+ image: wiremock/wiremock:2.32.0
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-ingress.yaml
similarity index 75%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock-ingress.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-ingress.yaml
index 2d278b58..8786d59a 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock-ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-ingress.yaml
@@ -3,13 +3,11 @@ kind: Ingress
metadata:
name: wiremock-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /wiremock(/|$)(.*)
+ - path: /wiremock/
pathType: Prefix
backend:
service:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-service.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock-service.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-loadbalancer-it/src/test/resources/wiremock/wiremock-service.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/java/org/springframework/cloud/kubernetes/client/reactive/discovery/it/ReactiveDiscoveryClientIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/java/org/springframework/cloud/kubernetes/client/reactive/discovery/it/ReactiveDiscoveryClientIT.java
deleted file mode 100644
index 9d7f339e..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/java/org/springframework/cloud/kubernetes/client/reactive/discovery/it/ReactiveDiscoveryClientIT.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright 2013-2020 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
- *
- * https://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.client.reactive.discovery.it;
-
-import java.io.IOException;
-import java.time.Duration;
-import java.util.Arrays;
-import java.util.Map;
-
-import io.kubernetes.client.openapi.ApiClient;
-import io.kubernetes.client.openapi.ApiException;
-import io.kubernetes.client.openapi.apis.AppsV1Api;
-import io.kubernetes.client.openapi.apis.CoreV1Api;
-import io.kubernetes.client.openapi.apis.NetworkingV1Api;
-import io.kubernetes.client.openapi.models.V1Deployment;
-import io.kubernetes.client.openapi.models.V1Ingress;
-import io.kubernetes.client.openapi.models.V1Service;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import org.springframework.boot.web.client.RestTemplateBuilder;
-import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.web.client.ResponseErrorHandler;
-import org.springframework.web.client.RestTemplate;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.awaitility.Awaitility.await;
-import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient;
-import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion;
-
-/**
- * @author Ryan Baxter
- */
-public class ReactiveDiscoveryClientIT {
-
- private static final Log LOG = LogFactory.getLog(ReactiveDiscoveryClientIT.class);
-
- private static final String WIREMOCK_DEPLOYMENT_NAME = "servicea-wiremock-deployment";
-
- private static final String WIREMOCK_APP_NAME = "servicea-wiremock";
-
- private static final String SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_DEPLOYMENT_NAME = "spring-cloud-kubernetes-client-reactive-discovery-it-deployment";
-
- private static final String SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_APP_NAME = "spring-cloud-kubernetes-client-reactive-discovery-it";
-
- private static final String NAMESPACE = "default";
-
- private ApiClient client;
-
- private CoreV1Api api;
-
- private AppsV1Api appsApi;
-
- private NetworkingV1Api networkingApi;
-
- private K8SUtils k8SUtils;
-
- @BeforeEach
- public void setup() throws Exception {
- this.client = createApiClient();
- this.api = new CoreV1Api();
- this.appsApi = new AppsV1Api();
- this.networkingApi = new NetworkingV1Api();
- this.k8SUtils = new K8SUtils(api, appsApi);
-
- deployWiremock();
-
- // Check to make sure the wiremock deployment is ready
- k8SUtils.waitForDeployment(WIREMOCK_DEPLOYMENT_NAME, NAMESPACE);
-
- // Check to see if endpoint is ready
- k8SUtils.waitForEndpointReady(WIREMOCK_APP_NAME, NAMESPACE);
-
- }
-
- @AfterEach
- public void after() throws Exception {
- appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
- "metadata.name=" + WIREMOCK_DEPLOYMENT_NAME, null, null, null, null, null, null, null, null, null);
-
- api.deleteNamespacedService(WIREMOCK_APP_NAME, NAMESPACE, null, null, null, null, null, null);
- networkingApi.deleteNamespacedIngress("wiremock-ingress", NAMESPACE, null, null, null, null, null, null);
-
- }
-
- @Test
- public void testReactiveDiscoveryClient() throws Exception {
- try {
- deployReactiveDiscoveryIt();
- testLoadBalancer();
- testHealth();
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- finally {
- cleanup();
- }
- }
-
- private void testHealth() {
- RestTemplate rest = createRestTemplate();
-
- // Sometimes the NGINX ingress takes a bit to catch up and realize the service is
- // available and we get a 503, we just need to wait a bit
- await().timeout(Duration.ofSeconds(60)).pollInterval(Duration.ofSeconds(1))
- .until(() -> rest
- .getForEntity("http://localhost:80/reactive-discovery-it/actuator/health", String.class)
- .getStatusCode().is2xxSuccessful());
-
- Map health = rest.getForObject("http://localhost:80/reactive-discovery-it/actuator/health",
- Map.class);
- Map components = (Map) health.get("components");
-
- assertThat(components.containsKey("reactiveDiscoveryClients")).isTrue();
- Map discoveryComposite = (Map) components.get("discoveryComposite");
- assertThat(discoveryComposite.get("status")).isEqualTo("UP");
- }
-
- private void cleanup() throws ApiException {
- appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
- "metadata.name=" + SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_DEPLOYMENT_NAME, null, null, null, null, null,
- null, null, null, null);
- api.deleteNamespacedService(SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_APP_NAME, NAMESPACE, null, null, null, null,
- null, null);
- networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null);
- }
-
- private void testLoadBalancer() throws Exception {
- // Check to make sure the controller deployment is ready
- k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_DEPLOYMENT_NAME, NAMESPACE);
- RestTemplate rest = createRestTemplate();
- // Sometimes the NGINX ingress takes a bit to catch up and realize the service is
- // available and we get a 503, we just need to wait a bit
- await().timeout(Duration.ofSeconds(60)).pollInterval(Duration.ofSeconds(1))
- .until(() -> rest.getForEntity("http://localhost:80/reactive-discovery-it/services", String.class)
- .getStatusCode().is2xxSuccessful());
- String result = rest.getForObject("http://localhost:80/reactive-discovery-it/services", String.class);
- assertThat(Arrays.stream(result.split(",")).anyMatch(s -> "servicea-wiremock".equalsIgnoreCase(s))).isTrue();
-
- }
-
- private RestTemplate createRestTemplate() {
- RestTemplate rest = new RestTemplateBuilder().build();
-
- rest.setErrorHandler(new ResponseErrorHandler() {
- @Override
- public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
- LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
- return clientHttpResponse.getRawStatusCode() != 503;
- }
-
- @Override
- public void handleError(ClientHttpResponse clientHttpResponse) {
-
- }
- });
- return rest;
- }
-
- private void deployReactiveDiscoveryIt() throws Exception {
- appsApi.createNamespacedDeployment(NAMESPACE, getReactiveDiscoveryItDeployment(), null, null, null);
- api.createNamespacedService(NAMESPACE, getReactiveDiscoveryService(), null, null, null);
- networkingApi.createNamespacedIngress(NAMESPACE, getReactiveDiscoveryItIngress(), null, null, null);
- }
-
- private V1Deployment getReactiveDiscoveryItDeployment() throws Exception {
- V1Deployment deployment = (V1Deployment) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-client-reactive-discovery-it-deployment.yaml");
- String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
- + getPomVersion();
- deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
- return deployment;
- }
-
- private V1Service getReactiveDiscoveryService() throws Exception {
- return (V1Service) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-client-reactive-discovery-it-service.yaml");
- }
-
- private V1Ingress getReactiveDiscoveryItIngress() throws Exception {
- return (V1Ingress) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-client-reactive-discovery-it-ingress.yaml");
- }
-
- private void deployWiremock() throws Exception {
- appsApi.createNamespacedDeployment(NAMESPACE, getWiremockDeployment(), null, null, null);
- api.createNamespacedService(NAMESPACE, getWiremockAppService(), null, null, null);
- networkingApi.createNamespacedIngress(NAMESPACE, getWiremockIngress(), null, null, null);
- }
-
- private V1Ingress getWiremockIngress() throws Exception {
- return (V1Ingress) K8SUtils.readYamlFromClasspath("wiremock-ingress.yaml");
- }
-
- private V1Service getWiremockAppService() throws Exception {
- return (V1Service) K8SUtils.readYamlFromClasspath("wiremock-service.yaml");
- }
-
- private V1Deployment getWiremockDeployment() throws Exception {
- return (V1Deployment) K8SUtils.readYamlFromClasspath("wiremock-deployment.yaml");
- }
-
-}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discovery-it-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discovery-it-service.yaml
deleted file mode 100644
index df3aad15..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discovery-it-service.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- labels:
- app: spring-cloud-kubernetes-client-reactive-discovery-it
- name: spring-cloud-kubernetes-client-reactive-discovery-it
-spec:
- ports:
- - name: http
- port: 8080
- targetPort: 8080
- selector:
- app: spring-cloud-kubernetes-client-reactive-discovery-it
- type: ClusterIP
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/k8s/deployment-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/k8s/deployment-it.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/k8s/deployment-it.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/k8s/deployment-it.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/k8s/service-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/k8s/service-it.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/k8s/service-it.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/k8s/service-it.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/pom.xml
similarity index 58%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/pom.xml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/pom.xml
index 968ae912..b7c3fc58 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/pom.xml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/pom.xml
@@ -9,7 +9,7 @@
4.0.0
- spring-cloud-kubernetes-client-reactive-discovery-client-it
+ spring-cloud-kubernetes-client-reactive-discoveryclient-it
@@ -47,6 +47,22 @@
test
+
+ org.testcontainers
+ testcontainers
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+ org.testcontainers
+ k3s
+ test
+
+
@@ -60,6 +76,55 @@
true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ docker.io/springcloud/${project.artifactId}:${project.version}
+ paketobuildpacks/builder
+
+
+
+ package
+
+ build-image
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+
+
+
+
+
+ ${testsToRun}
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/skaffold.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/skaffold.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/skaffold.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/skaffold.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/main/java/org/springframework/cloud/kubernetes/client/reactive/discovery/it/KubernetesClientReactiveDiscoveryClientApplicationIt.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/main/java/org/springframework/cloud/kubernetes/client/reactive/discovery/it/KubernetesClientReactiveDiscoveryClientApplicationIt.java
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/main/java/org/springframework/cloud/kubernetes/client/reactive/discovery/it/KubernetesClientReactiveDiscoveryClientApplicationIt.java
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/main/java/org/springframework/cloud/kubernetes/client/reactive/discovery/it/KubernetesClientReactiveDiscoveryClientApplicationIt.java
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/main/resources/application.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/main/resources/application.yaml
similarity index 67%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/main/resources/application.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/main/resources/application.yaml
index cd402822..978e0cde 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/main/resources/application.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/main/resources/application.yaml
@@ -1,3 +1,7 @@
+spring:
+ webflux:
+ base-path: /reactive-discovery-it
+
management:
endpoint:
health:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/client/reactive/discovery/it/ReactiveDiscoveryClientIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/client/reactive/discovery/it/ReactiveDiscoveryClientIT.java
new file mode 100644
index 00000000..b1f3bf47
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/client/reactive/discovery/it/ReactiveDiscoveryClientIT.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2013-2020 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
+ *
+ * https://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.client.reactive.discovery.it;
+
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Objects;
+
+import io.kubernetes.client.openapi.ApiException;
+import io.kubernetes.client.openapi.apis.AppsV1Api;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.apis.NetworkingV1Api;
+import io.kubernetes.client.openapi.models.V1Deployment;
+import io.kubernetes.client.openapi.models.V1Ingress;
+import io.kubernetes.client.openapi.models.V1Service;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.testcontainers.k3s.K3sContainer;
+import reactor.netty.http.client.HttpClient;
+import reactor.util.retry.Retry;
+import reactor.util.retry.RetryBackoffSpec;
+
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
+import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.core.ResolvableType;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient;
+import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion;
+
+/**
+ * @author Ryan Baxter
+ */
+class ReactiveDiscoveryClientIT {
+
+ private static final String HEALTH_URL = "localhost:80/reactive-discovery-it/actuator/health";
+
+ private static final String SERVICES_URL = "localhost:80/reactive-discovery-it/services";
+
+ private static final String SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_DEPLOYMENT_NAME = "spring-cloud-kubernetes-client-reactive-discoveryclient-it-deployment";
+
+ private static final String SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_APP_NAME = "spring-cloud-kubernetes-client-reactive-discoveryclient-it";
+
+ private static final String NAMESPACE = "default";
+
+ private static CoreV1Api api;
+
+ private static AppsV1Api appsApi;
+
+ private static NetworkingV1Api networkingApi;
+
+ private static K8SUtils k8SUtils;
+
+ private static final K3sContainer K3S = Commons.container();
+
+ @BeforeAll
+ static void beforeAll() throws Exception {
+ K3S.start();
+ Commons.validateImage(SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_APP_NAME, K3S);
+ Commons.loadImage(SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_APP_NAME, K3S);
+ createApiClient(K3S.getKubeConfigYaml());
+ api = new CoreV1Api();
+ appsApi = new AppsV1Api();
+ networkingApi = new NetworkingV1Api();
+ k8SUtils = new K8SUtils(api, appsApi);
+ k8SUtils.setUp(NAMESPACE);
+ }
+
+ @AfterAll
+ static void afterAll() throws Exception {
+ Commons.cleanUp(SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_APP_NAME, K3S);
+ k8SUtils.removeWiremockImage();
+ }
+
+ @BeforeEach
+ void setup() throws Exception {
+ k8SUtils.deployWiremock(NAMESPACE, false);
+ }
+
+ @AfterEach
+ void after() throws Exception {
+ k8SUtils.cleanUpWiremock(NAMESPACE);
+ cleanup();
+ }
+
+ @Test
+ void testReactiveDiscoveryClient() throws Exception {
+ deployReactiveDiscoveryIt();
+ testLoadBalancer();
+ testHealth();
+ }
+
+ @SuppressWarnings("unchecked")
+ private void testHealth() {
+
+ WebClient.Builder builder = builder();
+ WebClient serviceClient = builder.baseUrl(HEALTH_URL).build();
+ ResolvableType resolvableType = ResolvableType.forClassWithGenerics(Map.class, String.class, Object.class);
+ @SuppressWarnings("unchecked")
+ Map health = (Map) serviceClient.method(HttpMethod.GET).retrieve()
+ .bodyToMono(ParameterizedTypeReference.forType(resolvableType.getType())).retryWhen(retrySpec())
+ .block();
+
+ Map components = (Map) health.get("components");
+
+ assertThat(components.containsKey("reactiveDiscoveryClients")).isTrue();
+ Map discoveryComposite = (Map) components.get("discoveryComposite");
+ assertThat(discoveryComposite.get("status")).isEqualTo("UP");
+ }
+
+ private void cleanup() throws ApiException {
+ appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
+ "metadata.name=" + SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_DEPLOYMENT_NAME, null, null, null, null, null,
+ null, null, null, null);
+ api.deleteNamespacedService(SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_APP_NAME, NAMESPACE, null, null, null, null,
+ null, null);
+ networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null);
+ }
+
+ private void testLoadBalancer() {
+
+ // Check to make sure the controller deployment is ready
+ k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_REACTIVE_DISCOVERY_DEPLOYMENT_NAME, NAMESPACE);
+
+ WebClient.Builder builder = builder();
+ WebClient serviceClient = builder.baseUrl(SERVICES_URL).build();
+ String servicesResponse = serviceClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class)
+ .retryWhen(retrySpec()).block();
+
+ Assertions
+ .assertThat(Arrays.stream(servicesResponse.split(",")).anyMatch("servicea-wiremock"::equalsIgnoreCase))
+ .isTrue();
+
+ }
+
+ private void deployIngress(V1Ingress ingress) throws Exception {
+ networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null);
+ k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE);
+ }
+
+ private void deployReactiveDiscoveryIt() throws Exception {
+ appsApi.createNamespacedDeployment(NAMESPACE, getReactiveDiscoveryItDeployment(), null, null, null);
+ api.createNamespacedService(NAMESPACE, getReactiveDiscoveryService(), null, null, null);
+ deployIngress(getReactiveDiscoveryItIngress());
+ }
+
+ private V1Deployment getReactiveDiscoveryItDeployment() throws Exception {
+ V1Deployment deployment = (V1Deployment) K8SUtils
+ .readYamlFromClasspath("spring-cloud-kubernetes-client-reactive-discoveryclient-it-deployment.yaml");
+ String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ + getPomVersion();
+ deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
+ return deployment;
+ }
+
+ private V1Service getReactiveDiscoveryService() throws Exception {
+ return (V1Service) K8SUtils
+ .readYamlFromClasspath("spring-cloud-kubernetes-client-reactive-discoveryclient-it-service.yaml");
+ }
+
+ private V1Ingress getReactiveDiscoveryItIngress() throws Exception {
+ return (V1Ingress) K8SUtils
+ .readYamlFromClasspath("spring-cloud-kubernetes-client-reactive-discoveryclient-it-ingress.yaml");
+ }
+
+ private WebClient.Builder builder() {
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
+ }
+
+ private RetryBackoffSpec retrySpec() {
+ return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
+ }
+
+}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..9e284876
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/resources/logback-test.xml
@@ -0,0 +1,14 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discovery-it-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discoveryclient-it-deployment.yaml
similarity index 58%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discovery-it-deployment.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discoveryclient-it-deployment.yaml
index c6687cb3..4d1ce28e 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discovery-it-deployment.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discoveryclient-it-deployment.yaml
@@ -1,28 +1,28 @@
apiVersion: apps/v1
kind: Deployment
metadata:
- name: spring-cloud-kubernetes-client-reactive-discovery-it-deployment
+ name: spring-cloud-kubernetes-client-reactive-discoveryclient-it-deployment
spec:
selector:
matchLabels:
- app: spring-cloud-kubernetes-client-reactive-discovery-it
+ app: spring-cloud-kubernetes-client-reactive-discoveryclient-it
template:
metadata:
labels:
- app: spring-cloud-kubernetes-client-reactive-discovery-it
+ app: spring-cloud-kubernetes-client-reactive-discoveryclient-it
spec:
serviceAccountName: spring-cloud-kubernetes-serviceaccount
containers:
- - name: spring-cloud-kubernetes-client-reactive-discovery-it
- image: docker.io/springcloud/spring-cloud-kubernetes-client-reactive-discovery-client-it
+ - name: spring-cloud-kubernetes-client-reactive-discoveryclient-it
+ image: docker.io/springcloud/spring-cloud-kubernetes-client-reactive-discoveryclient-it
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
port: 8080
- path: /actuator/health/readiness
+ path: /reactive-discovery-it/actuator/health/readiness
livenessProbe:
httpGet:
port: 8080
- path: /actuator/health/liveness
+ path: /reactive-discovery-it/actuator/health/liveness
ports:
- containerPort: 8080
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discovery-it-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discoveryclient-it-ingress.yaml
similarity index 65%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discovery-it-ingress.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discoveryclient-it-ingress.yaml
index 305cc67b..6f361e0e 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discovery-it-ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discoveryclient-it-ingress.yaml
@@ -3,16 +3,14 @@ kind: Ingress
metadata:
name: it-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /reactive-discovery-it(/|$)(.*)
- pathType: Prefix
+ - path: /reactive-discovery-it
+ pathType: ImplementationSpecific
backend:
service:
- name: spring-cloud-kubernetes-client-reactive-discovery-it
+ name: spring-cloud-kubernetes-client-reactive-discoveryclient-it
port:
number: 8080
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discoveryclient-it-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discoveryclient-it-service.yaml
new file mode 100644
index 00000000..8d2e27d5
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discoveryclient-it/src/test/resources/spring-cloud-kubernetes-client-reactive-discoveryclient-it-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ app: spring-cloud-kubernetes-client-reactive-discoveryclient-it
+ name: spring-cloud-kubernetes-client-reactive-discoveryclient-it
+spec:
+ ports:
+ - name: http
+ port: 8080
+ targetPort: 8080
+ selector:
+ app: spring-cloud-kubernetes-client-reactive-discoveryclient-it
+ type: ClusterIP
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/pom.xml
index aecd8f8b..c5e73072 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/pom.xml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/pom.xml
@@ -5,7 +5,7 @@
org.springframework.cloud
spring-cloud-kubernetes-integration-tests
-3.0.0-SNAPSHOT
+ 3.0.0-SNAPSHOT
4.0.0
@@ -74,6 +74,29 @@
docker-java-transport-httpclient5
test
+
+
+ org.testcontainers
+ testcontainers
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+ org.testcontainers
+ k3s
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+ test
+
+
@@ -87,6 +110,55 @@
true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ docker.io/springcloud/${project.artifactId}:${project.version}
+ paketobuildpacks/builder
+
+
+
+ package
+
+ build-image
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+
+
+
+
+
+ ${testsToRun}
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigWatcherTestApplication.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigWatcherTestApplication.java
index 4033cee7..a3fb642f 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigWatcherTestApplication.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigWatcherTestApplication.java
@@ -38,15 +38,15 @@ public class ConfigWatcherTestApplication implements ApplicationListener stubFor(post(urlEqualTo("/actuator/refresh")).willReturn(aResponse().withStatus(200)))
.getResponse().wasConfigured());
// Create new configmap to trigger controller to signal app to refresh
- V1ConfigMap configMap = new V1ConfigMapBuilder().editOrNewMetadata().withName(CONFIG_WATCHER_WIREMOCK_APP_NAME)
+ V1ConfigMap configMap = new V1ConfigMapBuilder().editOrNewMetadata().withName("servicea-wiremock")
.addToLabels("spring.cloud.kubernetes.config", "true").endMetadata().addToData("foo", "bar").build();
api.createNamespacedConfigMap(NAMESPACE, configMap, null, null, null);
@@ -119,67 +138,34 @@ public class ActuatorRefreshIT {
verify(postRequestedFor(urlEqualTo("/actuator/refresh")));
}
- @AfterEach
- public void after() throws Exception {
-
- appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
- "metadata.name=" + SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, null, null, null, null, null, null,
- null, null, null);
- appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
- "metadata.name=" + CONFIG_WATCHER_WIREMOCK_DEPLOYMENT_NAME, null, null, null, null, null, null, null,
- null, null);
- api.deleteNamespacedService(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, NAMESPACE, null, null, null, null, null,
- null);
- api.deleteNamespacedService(CONFIG_WATCHER_WIREMOCK_APP_NAME, NAMESPACE, null, null, null, null, null, null);
- networkingApi.deleteNamespacedIngress("nginx-ingress", NAMESPACE, null, null, null, null, null, null);
- api.deleteNamespacedConfigMap(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, NAMESPACE, null, null, null, null, null,
- null);
- api.deleteNamespacedConfigMap(CONFIG_WATCHER_WIREMOCK_APP_NAME, NAMESPACE, null, null, null, null, null, null);
- // Check to make sure the controller deployment is deleted
- k8SUtils.waitForDeploymentToBeDeleted(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE);
- k8SUtils.waitForDeploymentToBeDeleted(CONFIG_WATCHER_WIREMOCK_DEPLOYMENT_NAME, NAMESPACE);
- }
-
private void deployConfigWatcher() throws Exception {
- api.createNamespacedConfigMap(NAMESPACE, getConfigWatcherConfigMap(), null, null, null);
+ V1ConfigMap configMap = getConfigWatcherConfigMap();
+ configWatcherConfigMapName = configMap.getMetadata().getName();
+ api.createNamespacedConfigMap(NAMESPACE, configMap, null, null, null);
appsApi.createNamespacedDeployment(NAMESPACE, getConfigWatcherDeployment(), null, null, null);
api.createNamespacedService(NAMESPACE, getConfigWatcherService(), null, null, null);
+
+ // Check to make sure the controller deployment is ready
+ k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE);
}
private V1Deployment getConfigWatcherDeployment() throws Exception {
- V1Deployment deployment = (V1Deployment) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-http-deployment.yaml");
+ V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath(
+ "config-watcher/spring-cloud-kubernetes-configuration-watcher-http-deployment.yaml");
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ getPomVersion();
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
return deployment;
}
- private void deployWiremock() throws Exception {
- appsApi.createNamespacedDeployment(NAMESPACE, getWiremockDeployment(), null, null, null);
- api.createNamespacedService(NAMESPACE, getWiremockAppService(), null, null, null);
- networkingApi.createNamespacedIngress(NAMESPACE, getWiremockIngress(), null, null, null);
- }
-
private V1Service getConfigWatcherService() throws Exception {
- return (V1Service) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-service.yaml");
+ return (V1Service) K8SUtils
+ .readYamlFromClasspath("config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml");
}
private V1ConfigMap getConfigWatcherConfigMap() throws Exception {
return (V1ConfigMap) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-configmap.yaml");
- }
-
- private V1Ingress getWiremockIngress() throws Exception {
- return (V1Ingress) K8SUtils.readYamlFromClasspath("wiremock-ingress.yaml");
- }
-
- private V1Service getWiremockAppService() throws Exception {
- return (V1Service) K8SUtils.readYamlFromClasspath("wiremock-service.yaml");
- }
-
- private V1Deployment getWiremockDeployment() throws Exception {
- return (V1Deployment) K8SUtils.readYamlFromClasspath("wiremock-deployment.yaml");
+ .readYamlFromClasspath("config-watcher/spring-cloud-kubernetes-configuration-watcher-configmap.yaml");
}
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshKafkaIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshKafkaIT.java
index c928fbbd..ef5751c3 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshKafkaIT.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshKafkaIT.java
@@ -16,10 +16,10 @@
package org.springframework.cloud.kubernetes.configuration.watcher;
-import java.io.IOException;
import java.time.Duration;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
-import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.apis.AppsV1Api;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.apis.NetworkingV1Api;
@@ -28,19 +28,23 @@ import io.kubernetes.client.openapi.models.V1ConfigMapBuilder;
import io.kubernetes.client.openapi.models.V1Deployment;
import io.kubernetes.client.openapi.models.V1Ingress;
import io.kubernetes.client.openapi.models.V1Service;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.testcontainers.k3s.K3sContainer;
+import reactor.netty.http.client.HttpClient;
+import reactor.util.retry.Retry;
+import reactor.util.retry.RetryBackoffSpec;
-import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.web.client.ResponseErrorHandler;
-import org.springframework.web.client.RestTemplate;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.web.reactive.function.client.WebClient;
-import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient;
import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion;
@@ -48,9 +52,7 @@ import static org.springframework.cloud.kubernetes.integration.tests.commons.K8S
/**
* @author Kris Iyer
*/
-public class ActuatorRefreshKafkaIT {
-
- private final Log log = LogFactory.getLog(getClass());
+class ActuatorRefreshKafkaIT {
private static final String CONFIG_WATCHER_IT_IMAGE = "spring-cloud-kubernetes-configuration-watcher-it";
@@ -70,23 +72,42 @@ public class ActuatorRefreshKafkaIT {
private static final String ZOOKEEPER_DEPLOYMENT = "zookeeper";
- private ApiClient client;
+ private static CoreV1Api api;
- private CoreV1Api api;
+ private static AppsV1Api appsApi;
- private AppsV1Api appsApi;
+ private static NetworkingV1Api networkingApi;
- private NetworkingV1Api networkingApi;
+ private static K8SUtils k8SUtils;
- private K8SUtils k8SUtils;
+ private static final K3sContainer K3S = Commons.container();
+
+ @BeforeAll
+ static void beforeAll() throws Exception {
+ K3S.start();
+
+ Commons.validateImage(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, K3S);
+ Commons.loadImage(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, K3S);
+
+ Commons.validateImage(CONFIG_WATCHER_IT_IMAGE, K3S);
+ Commons.loadImage(CONFIG_WATCHER_IT_IMAGE, K3S);
+
+ createApiClient(K3S.getKubeConfigYaml());
+ api = new CoreV1Api();
+ appsApi = new AppsV1Api();
+ k8SUtils = new K8SUtils(api, appsApi);
+ networkingApi = new NetworkingV1Api();
+ k8SUtils.setUp(NAMESPACE);
+ }
+
+ @AfterAll
+ static void afterAll() throws Exception {
+ Commons.cleanUp(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, K3S);
+ Commons.cleanUp(CONFIG_WATCHER_IT_IMAGE, K3S);
+ }
@BeforeEach
- public void setup() throws Exception {
- this.client = createApiClient();
- this.api = new CoreV1Api();
- this.appsApi = new AppsV1Api();
- this.networkingApi = new NetworkingV1Api();
- this.k8SUtils = new K8SUtils(api, appsApi);
+ void setup() throws Exception {
deployZookeeper();
deployKafka();
@@ -94,68 +115,23 @@ public class ActuatorRefreshKafkaIT {
deployConfigWatcher();
// Check to make sure the controller deployment is ready
- k8SUtils.waitForDeployment(ZOOKEEPER_DEPLOYMENT, NAMESPACE);
- k8SUtils.waitForDeployment(KAFKA_BROKER, NAMESPACE);
- k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME, NAMESPACE);
- k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE);
- }
-
- @Test
- public void testRefresh() throws Exception {
- // Create new configmap to trigger controller to signal app to refresh
- V1ConfigMap configMap = new V1ConfigMapBuilder().editOrNewMetadata().withName(CONFIG_WATCHER_IT_IMAGE)
- .addToLabels("spring.cloud.kubernetes.config", "true").endMetadata().addToData("foo", "hello world")
- .build();
- api.createNamespacedConfigMap(NAMESPACE, configMap, null, null, null);
- RestTemplate rest = new RestTemplateBuilder().build();
- rest.setErrorHandler(new ResponseErrorHandler() {
- @Override
- public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
- log.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
- return clientHttpResponse.getRawStatusCode() != 503;
- }
-
- @Override
- public void handleError(ClientHttpResponse clientHttpResponse) {
-
- }
- });
-
- // Sometimes the NGINX ingress takes a bit to catch up and realize the service is
- // available and we get a 503, we just need to wait a bit
- await().timeout(Duration.ofSeconds(60)).until(
- () -> rest.getForEntity("http://localhost:80/it", String.class).getStatusCode().is2xxSuccessful());
- // Wait a bit before we verify
- await().pollInterval(Duration.ofSeconds(1)).atMost(Duration.ofSeconds(90)).until(() -> {
- Boolean value = rest.getForObject("http://localhost:80/it", Boolean.class);
- log.info("Returned " + value + " from http://localhost:80/it");
- return value;
- });
-
- assertThat(rest.getForObject("http://localhost:80/it", Boolean.class)).isTrue();
+ waitForDeployment(ZOOKEEPER_DEPLOYMENT);
+ waitForDeployment(KAFKA_BROKER);
+ waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME);
+ waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME);
}
@AfterEach
- public void after() throws Exception {
- appsApi.deleteNamespacedDeployment(KAFKA_BROKER, NAMESPACE, null, null, null, null, null, null);
- api.deleteNamespacedService(KAFKA_SERVICE, NAMESPACE, null, null, null, null, null, null);
- appsApi.deleteNamespacedDeployment(ZOOKEEPER_DEPLOYMENT, NAMESPACE, null, null, null, null, null, null);
- api.deleteNamespacedService(ZOOKEEPER_SERVICE, NAMESPACE, null, null, null, null, null, null);
+ void after() throws Exception {
- api.deleteNamespacedService(CONFIG_WATCHER_IT_IMAGE, NAMESPACE, null, null, null, null, null, null);
- api.deleteNamespacedService(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, NAMESPACE, null, null, null, null, null,
- null);
-
- appsApi.deleteNamespacedDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE, null, null, null,
- null, null, null);
- appsApi.deleteNamespacedDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME, NAMESPACE, null, null,
- null, null, null, null);
+ cleanUpKafka();
+ cleanUpZookeeper();
+ cleanUpServices();
+ cleanUpDeployments();
networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null);
- api.deleteNamespacedConfigMap(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, NAMESPACE, null, null, null, null, null,
- null);
- api.deleteNamespacedConfigMap(CONFIG_WATCHER_IT_IMAGE, NAMESPACE, null, null, null, null, null, null);
+ cleanUpConfigMaps();
// Check to make sure the controller deployment is deleted
k8SUtils.waitForDeploymentToBeDeleted(KAFKA_BROKER, NAMESPACE);
@@ -164,10 +140,39 @@ public class ActuatorRefreshKafkaIT {
k8SUtils.waitForDeploymentToBeDeleted(SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME, NAMESPACE);
}
+ @Test
+ void testRefresh() throws Exception {
+ // Create new configmap to trigger controller to signal app to refresh
+ V1ConfigMap configMap = new V1ConfigMapBuilder().editOrNewMetadata().withName(CONFIG_WATCHER_IT_IMAGE)
+ .addToLabels("spring.cloud.kubernetes.config", "true").endMetadata().addToData("foo", "hello world")
+ .build();
+ api.createNamespacedConfigMap(NAMESPACE, configMap, null, null, null);
+
+ WebClient.Builder builder = builder();
+ WebClient serviceClient = builder.baseUrl("http://localhost:80/it").build();
+
+ Boolean[] value = new Boolean[1];
+ await().pollInterval(Duration.ofSeconds(3)).atMost(Duration.ofSeconds(90)).until(() -> {
+ value[0] = serviceClient.method(HttpMethod.GET).retrieve().bodyToMono(Boolean.class).retryWhen(retrySpec())
+ .block();
+ return value[0];
+ });
+
+ Assertions.assertThat(value[0]).isTrue();
+ }
+
+ private void waitForDeployment(String deploymentName) {
+ await().pollInterval(Duration.ofSeconds(3)).atMost(600, TimeUnit.SECONDS)
+ .until(() -> k8SUtils.isDeploymentReady(deploymentName, NAMESPACE));
+ }
+
private void deployTestApp() throws Exception {
appsApi.createNamespacedDeployment(NAMESPACE, getItDeployment(), null, null, null);
api.createNamespacedService(NAMESPACE, getItAppService(), null, null, null);
- networkingApi.createNamespacedIngress(NAMESPACE, getItIngress(), null, null, null);
+
+ V1Ingress ingress = getItIngress();
+ networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null);
+ k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE);
}
private void deployConfigWatcher() throws Exception {
@@ -177,24 +182,28 @@ public class ActuatorRefreshKafkaIT {
}
private void deployZookeeper() throws Exception {
- System.out.println("deploy deployZookeeper");
api.createNamespacedService(NAMESPACE, getZookeeperService(), null, null, null);
- System.out.println("created getZookeeperService");
appsApi.createNamespacedDeployment(NAMESPACE, getZookeeperDeployment(), null, null, null);
- System.out.println("created getZookeeperDeployment");
}
private void deployKafka() throws Exception {
- System.out.println("deploy kafka");
api.createNamespacedService(NAMESPACE, getKafkaService(), null, null, null);
- System.out.println("created getKafkaService");
appsApi.createNamespacedDeployment(NAMESPACE, getKafkaDeployment(), null, null, null);
- System.out.println("created getKafkaDeployment");
+ }
+
+ private void cleanUpKafka() throws Exception {
+ appsApi.deleteNamespacedDeployment(KAFKA_BROKER, NAMESPACE, null, null, null, null, null, null);
+ api.deleteNamespacedService(KAFKA_SERVICE, NAMESPACE, null, null, null, null, null, null);
+ }
+
+ private void cleanUpZookeeper() throws Exception {
+ appsApi.deleteNamespacedDeployment(ZOOKEEPER_DEPLOYMENT, NAMESPACE, null, null, null, null, null, null);
+ api.deleteNamespacedService(ZOOKEEPER_SERVICE, NAMESPACE, null, null, null, null, null, null);
}
private V1Deployment getConfigWatcherDeployment() throws Exception {
- V1Deployment deployment = (V1Deployment) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-bus-kafka-deployment.yaml");
+ V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath(
+ "app-watcher/spring-cloud-kubernetes-configuration-watcher-bus-kafka-deployment.yaml");
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ getPomVersion();
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
@@ -202,7 +211,7 @@ public class ActuatorRefreshKafkaIT {
}
private V1Deployment getItDeployment() throws Exception {
- String urlString = "spring-cloud-kubernetes-configuration-watcher-it-bus-kafka-deployment.yaml";
+ String urlString = "app/spring-cloud-kubernetes-configuration-watcher-it-bus-kafka-deployment.yaml";
V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath(urlString);
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ getPomVersion();
@@ -211,38 +220,66 @@ public class ActuatorRefreshKafkaIT {
}
private V1Service getConfigWatcherService() throws Exception {
- return (V1Service) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-service.yaml");
+ return (V1Service) K8SUtils
+ .readYamlFromClasspath("config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml");
}
private V1ConfigMap getConfigWatcherConfigMap() throws Exception {
return (V1ConfigMap) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-configmap.yaml");
+ .readYamlFromClasspath("config-watcher/spring-cloud-kubernetes-configuration-watcher-configmap.yaml");
}
private V1Service getItAppService() throws Exception {
return (V1Service) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-it-service.yaml");
+ .readYamlFromClasspath("app/spring-cloud-kubernetes-configuration-watcher-it-service.yaml");
}
private V1Ingress getItIngress() throws Exception {
return (V1Ingress) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml");
+ .readYamlFromClasspath("app/spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml");
}
private V1Deployment getKafkaDeployment() throws Exception {
- return (V1Deployment) K8SUtils.readYamlFromClasspath("kafka-deployment.yaml");
+ return (V1Deployment) K8SUtils.readYamlFromClasspath("kafka/kafka-deployment.yaml");
}
private V1Service getKafkaService() throws Exception {
- return (V1Service) K8SUtils.readYamlFromClasspath("kafka-service.yaml");
+ return (V1Service) K8SUtils.readYamlFromClasspath("kafka/kafka-service.yaml");
}
private V1Deployment getZookeeperDeployment() throws Exception {
- return (V1Deployment) K8SUtils.readYamlFromClasspath("zookeeper-deployment.yaml");
+ return (V1Deployment) K8SUtils.readYamlFromClasspath("zookeeper/zookeeper-deployment.yaml");
}
private V1Service getZookeeperService() throws Exception {
- return (V1Service) K8SUtils.readYamlFromClasspath("zookeeper-service.yaml");
+ return (V1Service) K8SUtils.readYamlFromClasspath("zookeeper/zookeeper-service.yaml");
+ }
+
+ private void cleanUpConfigMaps() throws Exception {
+ api.deleteNamespacedConfigMap(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, NAMESPACE, null, null, null, null, null,
+ null);
+ api.deleteNamespacedConfigMap(CONFIG_WATCHER_IT_IMAGE, NAMESPACE, null, null, null, null, null, null);
+ }
+
+ private void cleanUpDeployments() throws Exception {
+ appsApi.deleteNamespacedDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE, null, null, null,
+ null, null, null);
+ appsApi.deleteNamespacedDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME, NAMESPACE, null, null,
+ null, null, null, null);
+ }
+
+ private void cleanUpServices() throws Exception {
+ api.deleteNamespacedService(CONFIG_WATCHER_IT_IMAGE, NAMESPACE, null, null, null, null, null, null);
+ api.deleteNamespacedService(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, NAMESPACE, null, null, null, null, null,
+ null);
+ }
+
+ private WebClient.Builder builder() {
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
+ }
+
+ private RetryBackoffSpec retrySpec() {
+ return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
}
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshRabbitMQIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshRabbitMQIT.java
index dc1c3da1..e15a163f 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshRabbitMQIT.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshRabbitMQIT.java
@@ -16,10 +16,10 @@
package org.springframework.cloud.kubernetes.configuration.watcher;
-import java.io.IOException;
import java.time.Duration;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
-import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.apis.AppsV1Api;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.apis.NetworkingV1Api;
@@ -29,19 +29,23 @@ import io.kubernetes.client.openapi.models.V1Deployment;
import io.kubernetes.client.openapi.models.V1Ingress;
import io.kubernetes.client.openapi.models.V1ReplicationController;
import io.kubernetes.client.openapi.models.V1Service;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.testcontainers.k3s.K3sContainer;
+import reactor.netty.http.client.HttpClient;
+import reactor.util.retry.Retry;
+import reactor.util.retry.RetryBackoffSpec;
-import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.web.client.ResponseErrorHandler;
-import org.springframework.web.client.RestTemplate;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.web.reactive.function.client.WebClient;
-import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient;
import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion;
@@ -49,11 +53,7 @@ import static org.springframework.cloud.kubernetes.integration.tests.commons.K8S
/**
* @author Ryan Baxter
*/
-public class ActuatorRefreshRabbitMQIT {
-
- private static final Log LOG = LogFactory.getLog(ActuatorRefreshRabbitMQIT.class);
-
- private Log log = LogFactory.getLog(getClass());
+class ActuatorRefreshRabbitMQIT {
private static final String CONFIG_WATCHER_IT_IMAGE = "spring-cloud-kubernetes-configuration-watcher-it";
@@ -67,23 +67,42 @@ public class ActuatorRefreshRabbitMQIT {
private static final String RABBIT_MQ_CONTROLLER_NAME = "rabbitmq-controller";
- private ApiClient client;
+ private static CoreV1Api api;
- private CoreV1Api api;
+ private static AppsV1Api appsApi;
- private AppsV1Api appsApi;
+ private static NetworkingV1Api networkingApi;
- private NetworkingV1Api networkingApi;
+ private static K8SUtils k8SUtils;
- private K8SUtils k8SUtils;
+ private static final K3sContainer K3S = Commons.container();
+
+ @BeforeAll
+ static void beforeAll() throws Exception {
+ K3S.start();
+
+ Commons.validateImage(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, K3S);
+ Commons.loadImage(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, K3S);
+
+ Commons.validateImage(CONFIG_WATCHER_IT_IMAGE, K3S);
+ Commons.loadImage(CONFIG_WATCHER_IT_IMAGE, K3S);
+
+ createApiClient(K3S.getKubeConfigYaml());
+ api = new CoreV1Api();
+ appsApi = new AppsV1Api();
+ k8SUtils = new K8SUtils(api, appsApi);
+ networkingApi = new NetworkingV1Api();
+ k8SUtils.setUp(NAMESPACE);
+ }
+
+ @AfterAll
+ static void afterAll() throws Exception {
+ Commons.cleanUp(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, K3S);
+ Commons.cleanUp(CONFIG_WATCHER_IT_IMAGE, K3S);
+ }
@BeforeEach
- public void setup() throws Exception {
- this.client = createApiClient();
- this.api = new CoreV1Api();
- this.appsApi = new AppsV1Api();
- this.networkingApi = new NetworkingV1Api();
- this.k8SUtils = new K8SUtils(api, appsApi);
+ void setup() throws Exception {
deployRabbitMQ();
deployTestApp();
@@ -91,48 +110,33 @@ public class ActuatorRefreshRabbitMQIT {
// Check to make sure the controller deployment is ready
k8SUtils.waitForReplicationController(RABBIT_MQ_CONTROLLER_NAME, NAMESPACE);
- k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME, NAMESPACE);
- k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME, NAMESPACE);
+ waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_IT_DEPLOYMENT_NAME);
+ waitForDeployment(SPRING_CLOUD_K8S_CONFIG_WATCHER_DEPLOYMENT_NAME);
}
@Test
- public void testRefresh() throws Exception {
+ void testRefresh() throws Exception {
// Create new configmap to trigger controller to signal app to refresh
V1ConfigMap configMap = new V1ConfigMapBuilder().editOrNewMetadata().withName(CONFIG_WATCHER_IT_IMAGE)
.addToLabels("spring.cloud.kubernetes.config", "true").endMetadata().addToData("foo", "hello world")
.build();
api.createNamespacedConfigMap(NAMESPACE, configMap, null, null, null);
- RestTemplate rest = new RestTemplateBuilder().build();
- rest.setErrorHandler(new ResponseErrorHandler() {
- @Override
- public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
- LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
- return clientHttpResponse.getRawStatusCode() != 503;
- }
- @Override
- public void handleError(ClientHttpResponse clientHttpResponse) {
+ WebClient.Builder builder = builder();
+ WebClient serviceClient = builder.baseUrl("http://localhost:80/it").build();
- }
+ Boolean[] value = new Boolean[1];
+ await().pollInterval(Duration.ofSeconds(3)).atMost(Duration.ofSeconds(90)).until(() -> {
+ value[0] = serviceClient.method(HttpMethod.GET).retrieve().bodyToMono(Boolean.class).retryWhen(retrySpec())
+ .block();
+ return value[0];
});
- // Sometimes the NGINX ingress takes a bit to catch up and realize the service is
- // available and we get a 503, we just need to wait a bit
- await().timeout(Duration.ofSeconds(60)).until(
- () -> rest.getForEntity("http://localhost:80/it", String.class).getStatusCode().is2xxSuccessful());
-
- // Wait a bit before we verify
- await().pollInterval(Duration.ofSeconds(1)).atMost(Duration.ofSeconds(120)).until(() -> {
- Boolean value = rest.getForObject("http://localhost:80/it", Boolean.class);
- log.info("Returned " + value + " from http://localhost:80/it");
- return value;
- });
-
- assertThat(rest.getForObject("http://localhost:80/it", Boolean.class)).isTrue();
+ Assertions.assertThat(value[0]).isTrue();
}
@AfterEach
- public void after() throws Exception {
+ void after() throws Exception {
api.deleteNamespacedService("rabbitmq-service", NAMESPACE, null, null, null, null, null, null);
api.deleteNamespacedService(CONFIG_WATCHER_IT_IMAGE, NAMESPACE, null, null, null, null, null, null);
api.deleteNamespacedService(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, NAMESPACE, null, null, null, null, null,
@@ -148,10 +152,8 @@ public class ActuatorRefreshRabbitMQIT {
null, null);
}
catch (Exception e) {
- // swallowing this exception, the delete does actually happen, its a problem
- // downstream from the k8s
- // client
- // see
+ // swallowing this exception, delete does actually happen, it's a problem
+ // downstream from the k8s client; see:
// https://github.com/kubernetes-client/java/issues/86#issuecomment-411234259
}
@@ -170,7 +172,10 @@ public class ActuatorRefreshRabbitMQIT {
private void deployTestApp() throws Exception {
appsApi.createNamespacedDeployment(NAMESPACE, getItDeployment(), null, null, null);
api.createNamespacedService(NAMESPACE, getItAppService(), null, null, null);
- networkingApi.createNamespacedIngress(NAMESPACE, getItIngress(), null, null, null);
+
+ V1Ingress ingress = getItIngress();
+ networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null);
+ k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE);
}
private void deployConfigWatcher() throws Exception {
@@ -185,8 +190,8 @@ public class ActuatorRefreshRabbitMQIT {
}
private V1Deployment getConfigWatcherDeployment() throws Exception {
- V1Deployment deployment = (V1Deployment) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-bus-amqp-deployment.yaml");
+ V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath(
+ "app-watcher/spring-cloud-kubernetes-configuration-watcher-bus-amqp-deployment.yaml");
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ getPomVersion();
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
@@ -194,7 +199,7 @@ public class ActuatorRefreshRabbitMQIT {
}
private V1Deployment getItDeployment() throws Exception {
- String urlString = "spring-cloud-kubernetes-configuration-watcher-it-bus-amqp-deployment.yaml";
+ String urlString = "app-watcher/spring-cloud-kubernetes-configuration-watcher-it-bus-amqp-deployment.yaml";
V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath(urlString);
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ getPomVersion();
@@ -204,29 +209,43 @@ public class ActuatorRefreshRabbitMQIT {
private V1Service getItAppService() throws Exception {
return (V1Service) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-it-service.yaml");
+ .readYamlFromClasspath("app/spring-cloud-kubernetes-configuration-watcher-it-service.yaml");
}
private V1Service getConfigWatcherService() throws Exception {
- return (V1Service) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-service.yaml");
+ return (V1Service) K8SUtils
+ .readYamlFromClasspath("config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml");
}
private V1ConfigMap getConfigWatcherConfigMap() throws Exception {
return (V1ConfigMap) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-configmap.yaml");
+ .readYamlFromClasspath("config-watcher/spring-cloud-kubernetes-configuration-watcher-configmap.yaml");
}
private V1Ingress getItIngress() throws Exception {
return (V1Ingress) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml");
+ .readYamlFromClasspath("app/spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml");
}
private V1ReplicationController getRabbitMQReplicationController() throws Exception {
- return (V1ReplicationController) K8SUtils.readYamlFromClasspath("rabbitmq-controller.yaml");
+ return (V1ReplicationController) K8SUtils.readYamlFromClasspath("rabbitmq/rabbitmq-controller.yaml");
}
private V1Service getRabbitMQService() throws Exception {
- return (V1Service) K8SUtils.readYamlFromClasspath("rabbitmq-service.yaml");
+ return (V1Service) K8SUtils.readYamlFromClasspath("rabbitmq/rabbitmq-service.yaml");
+ }
+
+ private void waitForDeployment(String deploymentName) {
+ await().pollInterval(Duration.ofSeconds(3)).atMost(600, TimeUnit.SECONDS)
+ .until(() -> k8SUtils.isDeploymentReady(deploymentName, NAMESPACE));
+ }
+
+ private WebClient.Builder builder() {
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
+ }
+
+ private RetryBackoffSpec retrySpec() {
+ return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
}
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-bus-amqp-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/app-watcher/spring-cloud-kubernetes-configuration-watcher-bus-amqp-deployment.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-bus-amqp-deployment.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/app-watcher/spring-cloud-kubernetes-configuration-watcher-bus-amqp-deployment.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-bus-kafka-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/app-watcher/spring-cloud-kubernetes-configuration-watcher-bus-kafka-deployment.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-bus-kafka-deployment.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/app-watcher/spring-cloud-kubernetes-configuration-watcher-bus-kafka-deployment.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-it-bus-amqp-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/app-watcher/spring-cloud-kubernetes-configuration-watcher-it-bus-amqp-deployment.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-it-bus-amqp-deployment.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/app-watcher/spring-cloud-kubernetes-configuration-watcher-it-bus-amqp-deployment.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-it-bus-kafka-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/app/spring-cloud-kubernetes-configuration-watcher-it-bus-kafka-deployment.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-it-bus-kafka-deployment.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/app/spring-cloud-kubernetes-configuration-watcher-it-bus-kafka-deployment.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/app/spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml
similarity index 77%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/app/spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml
index 2ca14ad9..222b748a 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/app/spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml
@@ -3,13 +3,11 @@ kind: Ingress
metadata:
name: it-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /it(/|$)(.*)
+ - path: /it
pathType: Prefix
backend:
service:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-it-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/app/spring-cloud-kubernetes-configuration-watcher-it-service.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-it-service.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/app/spring-cloud-kubernetes-configuration-watcher-it-service.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-configmap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/config-watcher/spring-cloud-kubernetes-configuration-watcher-configmap.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-configmap.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/config-watcher/spring-cloud-kubernetes-configuration-watcher-configmap.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-http-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/config-watcher/spring-cloud-kubernetes-configuration-watcher-http-deployment.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-http-deployment.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/config-watcher/spring-cloud-kubernetes-configuration-watcher-http-deployment.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/spring-cloud-kubernetes-configuration-watcher-service.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka/kafka-deployment.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka-deployment.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka/kafka-deployment.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka/kafka-service.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka-service.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/kafka/kafka-service.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..9e284876
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/logback-test.xml
@@ -0,0 +1,14 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq-controller.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq/rabbitmq-controller.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq-controller.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq/rabbitmq-controller.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq/rabbitmq-service.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq-service.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/rabbitmq/rabbitmq-service.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/wiremock-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/wiremock-deployment.yaml
deleted file mode 100644
index fe39b31c..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/wiremock-deployment.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: config-watcher-wiremock-deployment
-spec:
- selector:
- matchLabels:
- app: config-watcher-wiremock
- template:
- metadata:
- labels:
- app: config-watcher-wiremock
- spec:
- containers:
- - name: config-watcher-wiremock
- image: rodolpheche/wiremock:2.27.2
- imagePullPolicy: IfNotPresent
- readinessProbe:
- httpGet:
- port: 8080
- path: /__admin/mappings
- livenessProbe:
- httpGet:
- port: 8080
- path: /__admin/mappings
- ports:
- - containerPort: 8080
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/wiremock-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/wiremock-service.yaml
deleted file mode 100644
index 559c7645..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/wiremock-service.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- labels:
- app: config-watcher-wiremock
- name: config-watcher-wiremock
-spec:
- ports:
- - name: http
- port: 8080
- targetPort: 8080
- selector:
- app: config-watcher-wiremock
- type: ClusterIP
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper/zookeeper-deployment.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper-deployment.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper/zookeeper-deployment.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper/zookeeper-service.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper-service.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/zookeeper/zookeeper-service.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/pom.xml
index b52d3a6f..e7ef75a3 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/pom.xml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/pom.xml
@@ -59,6 +59,55 @@
true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ docker.io/springcloud/${project.artifactId}:${project.version}
+ paketobuildpacks/builder
+
+
+
+ package
+
+ build-image
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+
+
+
+
+
+ ${testsToRun}
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/java/org/springframework/cloud/kubernetes/core/k8s/it/ActuatorEndpointIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/java/org/springframework/cloud/kubernetes/core/k8s/it/ActuatorEndpointIT.java
index 019f2f6f..df5923e9 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/java/org/springframework/cloud/kubernetes/core/k8s/it/ActuatorEndpointIT.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/java/org/springframework/cloud/kubernetes/core/k8s/it/ActuatorEndpointIT.java
@@ -16,40 +16,40 @@
package org.springframework.cloud.kubernetes.core.k8s.it;
-import java.io.IOException;
import java.time.Duration;
import java.util.Map;
+import java.util.Objects;
-import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.apis.AppsV1Api;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.apis.NetworkingV1Api;
import io.kubernetes.client.openapi.models.V1Deployment;
import io.kubernetes.client.openapi.models.V1Ingress;
import io.kubernetes.client.openapi.models.V1Service;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.testcontainers.k3s.K3sContainer;
+import reactor.netty.http.client.HttpClient;
+import reactor.util.retry.Retry;
+import reactor.util.retry.RetryBackoffSpec;
-import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.web.client.ResponseErrorHandler;
-import org.springframework.web.client.RestTemplate;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.core.ResolvableType;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
-import static org.awaitility.Awaitility.await;
import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient;
import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion;
/**
* @author Ryan Baxter
*/
-public class ActuatorEndpointIT {
-
- private static final Log LOG = LogFactory.getLog(ActuatorEndpointIT.class);
+class ActuatorEndpointIT {
private static final String SPRING_CLOUD_K8S_CLIENT_IT_DEPLOYMENT_NAME = "spring-cloud-kubernetes-core-k8s-client-it-deployment";
@@ -59,23 +59,27 @@ public class ActuatorEndpointIT {
private static final String NAMESPACE = "default";
- private static ApiClient client;
-
private static CoreV1Api api;
private static AppsV1Api appsApi;
- private static NetworkingV1Api networkingApi;
-
private static K8SUtils k8SUtils;
+ private static NetworkingV1Api networkingApi;
+
+ private static final K3sContainer K3S = Commons.container();
+
@BeforeAll
- public static void setup() throws Exception {
- client = createApiClient();
+ static void beforeAll() throws Exception {
+ K3S.start();
+ Commons.validateImage(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, K3S);
+ Commons.loadImage(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, K3S);
+ createApiClient(K3S.getKubeConfigYaml());
api = new CoreV1Api();
appsApi = new AppsV1Api();
networkingApi = new NetworkingV1Api();
k8SUtils = new K8SUtils(api, appsApi);
+ k8SUtils.setUp(NAMESPACE);
deployCoreK8sClientIt();
@@ -84,7 +88,8 @@ public class ActuatorEndpointIT {
}
@AfterAll
- public static void after() throws Exception {
+ static void after() throws Exception {
+ Commons.cleanUp(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, K3S);
appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
"metadata.name=" + K8S_CONFIG_CLIENT_IT_NAME, null, null, null, null, null, null, null, null, null);
api.deleteNamespacedService(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, NAMESPACE, null, null, null, null, null, null);
@@ -92,31 +97,18 @@ public class ActuatorEndpointIT {
}
@Test
- public void testHealth() {
- RestTemplate rest = new RestTemplateBuilder().build();
+ @SuppressWarnings("unchecked")
+ void testHealth() {
- rest.setErrorHandler(new ResponseErrorHandler() {
- @Override
- public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
- LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
- return clientHttpResponse.getRawStatusCode() != 503;
- }
+ WebClient.Builder builder = builder();
+ WebClient serviceClient = builder.baseUrl("http://localhost:80/actuator/health").build();
- @Override
- public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
+ ResolvableType resolvableType = ResolvableType.forClassWithGenerics(Map.class, String.class, Object.class);
+ @SuppressWarnings("unchecked")
+ Map health = (Map) serviceClient.method(HttpMethod.GET).retrieve()
+ .bodyToMono(ParameterizedTypeReference.forType(resolvableType.getType())).retryWhen(retrySpec())
+ .block();
- }
- });
-
- // Sometimes the NGINX ingress takes a bit to catch up and realize the service is
- // available and we get a 503, we just need to wait a bit
- await().timeout(Duration.ofSeconds(60))
- .until(() -> rest.getForEntity("http://localhost:80/core-k8s-client-it/actuator/health", String.class)
- .getStatusCode().is2xxSuccessful());
- LOG.debug("Response from /health endpoint: "
- + rest.getForEntity("http://localhost:80/core-k8s-client-it/actuator/health", String.class));
- Map health = rest.getForObject("http://localhost:80/core-k8s-client-it/actuator/health",
- Map.class);
Map components = (Map) health.get("components");
assertThat(components.containsKey("kubernetes")).isTrue();
Map kubernetes = (Map) components.get("kubernetes");
@@ -132,35 +124,24 @@ public class ActuatorEndpointIT {
assertThat(details.containsKey("serviceAccount")).isTrue();
assertThat(components.containsKey("discoveryComposite")).isTrue();
- Map discoveryComposite = (Map) components.get("discoveryComposite");
+ Map discoveryComposite = (Map) components.get("discoveryComposite");
assertThat(discoveryComposite.get("status")).isEqualTo("UP");
+
}
@Test
- public void testInfo() {
- RestTemplate rest = new RestTemplateBuilder().build();
+ @SuppressWarnings("unchecked")
+ void testInfo() {
- rest.setErrorHandler(new ResponseErrorHandler() {
- @Override
- public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
- LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
- return clientHttpResponse.getRawStatusCode() != 503;
- }
+ WebClient.Builder builder = builder();
+ WebClient serviceClient = builder.baseUrl("http://localhost:80/actuator/info").build();
- @Override
- public void handleError(ClientHttpResponse clientHttpResponse) {
+ ResolvableType resolvableType = ResolvableType.forClassWithGenerics(Map.class, String.class, Object.class);
+ @SuppressWarnings("unchecked")
+ Map info = (Map) serviceClient.method(HttpMethod.GET).retrieve()
+ .bodyToMono(ParameterizedTypeReference.forType(resolvableType.getType())).retryWhen(retrySpec())
+ .block();
- }
- });
-
- // Sometimes the NGINX ingress takes a bit to catch up and realize the service is
- // available and we get a 503, we just need to wait a bit
- await().timeout(Duration.ofSeconds(60))
- .until(() -> rest.getForEntity("http://localhost:80/core-k8s-client-it/actuator/info", String.class)
- .getStatusCode().is2xxSuccessful());
- LOG.debug("Response from /info endpoint: "
- + rest.getForEntity("http://localhost:80/core-k8s-client-it/actuator/info", String.class));
- Map info = rest.getForObject("http://localhost:80/core-k8s-client-it/actuator/info", Map.class);
Map kubernetes = (Map) info.get("kubernetes");
assertThat(kubernetes.containsKey("hostIp")).isTrue();
assertThat(kubernetes.containsKey("inside")).isTrue();
@@ -174,7 +155,10 @@ public class ActuatorEndpointIT {
private static void deployCoreK8sClientIt() throws Exception {
appsApi.createNamespacedDeployment(NAMESPACE, getCoreK8sClientItDeployment(), null, null, null);
api.createNamespacedService(NAMESPACE, getCoreK8sClientItService(), null, null, null);
- networkingApi.createNamespacedIngress(NAMESPACE, getCoreK8sClientItIngress(), null, null, null);
+
+ V1Ingress ingress = getCoreK8sClientItIngress();
+ networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null);
+ k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE);
}
private static V1Deployment getCoreK8sClientItDeployment() throws Exception {
@@ -194,4 +178,12 @@ public class ActuatorEndpointIT {
return (V1Ingress) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-it-ingress.yaml");
}
+ private WebClient.Builder builder() {
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
+ }
+
+ private RetryBackoffSpec retrySpec() {
+ return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
+ }
+
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..9e284876
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/resources/logback-test.xml
@@ -0,0 +1,14 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/resources/spring-cloud-kubernetes-core-k8s-client-it-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/resources/spring-cloud-kubernetes-core-k8s-client-it-ingress.yaml
index 90b7b89f..770915a5 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/resources/spring-cloud-kubernetes-core-k8s-client-it-ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/resources/spring-cloud-kubernetes-core-k8s-client-it-ingress.yaml
@@ -3,13 +3,11 @@ kind: Ingress
metadata:
name: it-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /core-k8s-client-it(/|$)(.*)
+ - path: /
pathType: Prefix
backend:
service:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/pom.xml
deleted file mode 100644
index 7eb08b8e..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/pom.xml
+++ /dev/null
@@ -1,110 +0,0 @@
-
-
-
- spring-cloud-kubernetes-integration-tests
- org.springframework.cloud
- 3.0.0-SNAPSHOT
-
- 4.0.0
-
- spring-cloud-kubernetes-discoverclient-it
-
-
- 1.8.0
- openjdk:8u222-slim
-
-
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.cloud
- spring-cloud-starter-kubernetes-discoveryclient
-
-
- org.springframework.boot
- spring-boot-starter-actuator
-
-
- org.springframework.cloud
- spring-cloud-kubernetes-test-support
-
-
- io.kubernetes
- client-java
-
-
- io.kubernetes
- client-java-extended
-
-
- com.github.docker-java
- docker-java-core
- test
-
-
- com.github.docker-java
- docker-java-transport-httpclient5
- test
-
-
-
-
-
-
-
- ../src/main/resources
- true
-
-
- src/main/resources
- true
-
-
-
-
-
-
- skaffold
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
- ${env.IMAGE}
-
- build-image
-
-
-
- package
-
- build-image
-
-
-
-
-
-
-
-
- imagename
-
-
- !env.IMAGE
-
-
-
- springcloud/${project.artifactId}:${project.version}
-
-
-
-
-
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/main/resources/application.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/main/resources/application.yaml
deleted file mode 100644
index 1b70c818..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/main/resources/application.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-spring:
- cloud:
- kubernetes:
- discovery:
- discoveryServerUrl: http://spring-cloud-kubernetes-discoveryserver
-management:
- endpoint:
- health:
- show-details: always
- endpoints:
- web:
- exposure:
- include: "*"
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientIT.java
deleted file mode 100644
index 3f9b62ad..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientIT.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright 2013-2021 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
- *
- * https://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.discoveryclient.it;
-
-import java.io.IOException;
-import java.time.Duration;
-import java.util.Arrays;
-import java.util.Map;
-
-import io.kubernetes.client.openapi.ApiClient;
-import io.kubernetes.client.openapi.ApiException;
-import io.kubernetes.client.openapi.apis.AppsV1Api;
-import io.kubernetes.client.openapi.apis.CoreV1Api;
-import io.kubernetes.client.openapi.apis.NetworkingV1Api;
-import io.kubernetes.client.openapi.models.V1Deployment;
-import io.kubernetes.client.openapi.models.V1Ingress;
-import io.kubernetes.client.openapi.models.V1Service;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-import org.springframework.boot.web.client.RestTemplateBuilder;
-import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.web.client.ResponseErrorHandler;
-import org.springframework.web.client.RestTemplate;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.awaitility.Awaitility.await;
-import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient;
-import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion;
-
-/**
- * @author Ryan Baxter
- */
-public class DiscoveryClientIT {
-
- private static final Log LOG = LogFactory.getLog(DiscoveryClientIT.class);
-
- private static final String DISCOVERYSERVER_DEPLOYMENT_NAME = "spring-cloud-kubernetes-discoveryserver-deployment";
-
- private static final String DISCOVERYSERVER_APP_NAME = "spring-cloud-kubernetes-discoveryserver";
-
- private static final String SPRING_CLOUD_K8S_DISCOVERYCLIENT_DEPLOYMENT_NAME = "spring-cloud-kubernetes-discoveryclient-it-deployment";
-
- private static final String SPRING_CLOUD_K8S_DISCOVERYCLIENT_APP_NAME = "spring-cloud-kubernetes-discoveryclient-it";
-
- private static final String NAMESPACE = "default";
-
- private static ApiClient client;
-
- private static CoreV1Api api;
-
- private static AppsV1Api appsApi;
-
- private static NetworkingV1Api networkingApi;
-
- private static K8SUtils k8SUtils;
-
- @BeforeAll
- public static void setup() throws Exception {
- client = createApiClient();
- api = new CoreV1Api();
- appsApi = new AppsV1Api();
- networkingApi = new NetworkingV1Api();
- k8SUtils = new K8SUtils(api, appsApi);
-
- deployDiscoveryServer();
-
- // Check to make sure the discovery server deployment is ready
- k8SUtils.waitForDeployment(DISCOVERYSERVER_DEPLOYMENT_NAME, NAMESPACE);
-
- // Check to see if endpoint is ready
- k8SUtils.waitForEndpointReady(DISCOVERYSERVER_APP_NAME, NAMESPACE);
-
- }
-
- @Test
- public void testDiscoveryClient() throws Exception {
- try {
- deployDiscoveryIt();
- testLoadBalancer();
- testHealth();
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- finally {
- cleanup();
- }
- }
-
- private void cleanup() throws ApiException {
- appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
- "metadata.name=" + SPRING_CLOUD_K8S_DISCOVERYCLIENT_DEPLOYMENT_NAME, null, null, null, null, null, null,
- null, null, null);
- api.deleteNamespacedService(SPRING_CLOUD_K8S_DISCOVERYCLIENT_APP_NAME, NAMESPACE, null, null, null, null, null,
- null);
- networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null);
- }
-
- private void testLoadBalancer() throws Exception {
- // Check to make sure the controller deployment is ready
- k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_DISCOVERYCLIENT_DEPLOYMENT_NAME, NAMESPACE);
- RestTemplate rest = createRestTemplate();
- // Sometimes the NGINX ingress takes a bit to catch up and realize the service is
- // available and we get a 503, we just need to wait a bit
- await().timeout(Duration.ofSeconds(60))
- .until(() -> rest.getForEntity("http://localhost:80/discoveryclient-it/services", String.class)
- .getStatusCode().is2xxSuccessful());
- String[] result = rest.getForObject("http://localhost:80/discoveryclient-it/services", String[].class);
- LOG.info("Services: " + Arrays.toString(result));
- assertThat(Arrays.stream(result).anyMatch(s -> "spring-cloud-kubernetes-discoveryserver".equalsIgnoreCase(s)))
- .isTrue();
-
- }
-
- private RestTemplate createRestTemplate() {
- RestTemplate rest = new RestTemplateBuilder().build();
-
- rest.setErrorHandler(new ResponseErrorHandler() {
- @Override
- public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
- LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
- return clientHttpResponse.getRawStatusCode() != 503;
- }
-
- @Override
- public void handleError(ClientHttpResponse clientHttpResponse) {
-
- }
- });
- return rest;
- }
-
- public void testHealth() {
- RestTemplate rest = createRestTemplate();
-
- // Sometimes the NGINX ingress takes a bit to catch up and realize the service is
- // available and we get a 503, we just need to wait a bit
- await().timeout(Duration.ofSeconds(60))
- .until(() -> rest.getForEntity("http://localhost:80/discoveryclient-it/actuator/health", String.class)
- .getStatusCode().is2xxSuccessful());
-
- Map health = rest.getForObject("http://localhost:80/discoveryclient-it/actuator/health",
- Map.class);
- Map components = (Map) health.get("components");
-
- Map discoveryComposite = (Map) components.get("discoveryComposite");
- assertThat(discoveryComposite.get("status")).isEqualTo("UP");
- }
-
- @AfterAll
- public static void after() throws Exception {
- appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
- "metadata.name=" + DISCOVERYSERVER_DEPLOYMENT_NAME, null, null, null, null, null, null, null, null,
- null);
-
- api.deleteNamespacedService(DISCOVERYSERVER_APP_NAME, NAMESPACE, null, null, null, null, null, null);
- networkingApi.deleteNamespacedIngress("discoveryserver-ingress", NAMESPACE, null, null, null, null, null, null);
-
- }
-
- private void deployDiscoveryIt() throws Exception {
- appsApi.createNamespacedDeployment(NAMESPACE, getDiscoveryItDeployment(), null, null, null);
- api.createNamespacedService(NAMESPACE, getDiscoveryService(), null, null, null);
- networkingApi.createNamespacedIngress(NAMESPACE, getDiscoveryItIngress(), null, null, null);
- }
-
- private V1Deployment getDiscoveryItDeployment() throws Exception {
- V1Deployment deployment = (V1Deployment) k8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-discoveryclient-it-deployment.yaml");
- String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
- + getPomVersion();
- deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
- return deployment;
- }
-
- private static void deployDiscoveryServer() throws Exception {
- appsApi.createNamespacedDeployment(NAMESPACE, getDiscoveryServerDeployment(), null, null, null);
- api.createNamespacedService(NAMESPACE, getDiscoveryServerService(), null, null, null);
- networkingApi.createNamespacedIngress(NAMESPACE, getDiscoveryServerIngress(), null, null, null);
- }
-
- private static V1Deployment getDiscoveryServerDeployment() throws Exception {
- V1Deployment deployment = (V1Deployment) k8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-discoveryserver-deployment.yaml");
- String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
- + getPomVersion();
- deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
- return deployment;
- }
-
- private static V1Ingress getDiscoveryServerIngress() throws Exception {
- return (V1Ingress) k8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-discoveryserver-ingress.yaml");
- }
-
- private static V1Service getDiscoveryServerService() throws Exception {
- return (V1Service) k8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-discoveryserver-service.yaml");
- }
-
- private V1Ingress getDiscoveryItIngress() throws Exception {
- return (V1Ingress) k8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-discoveryclient-it-ingress.yaml");
- }
-
- private V1Service getDiscoveryService() throws Exception {
- return (V1Service) k8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-discoveryclient-it-service.yaml");
- }
-
-}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml
deleted file mode 100644
index 45aebedf..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: it-ingress
- namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
-spec:
- rules:
- - http:
- paths:
- - path: /discoveryclient-it(/|$)(.*)
- pathType: Prefix
- backend:
- service:
- name: spring-cloud-kubernetes-discoveryclient-it
- port:
- number: 8080
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-ingress.yaml
deleted file mode 100644
index d58cf1b4..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-ingress.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: discoveryserver-ingress
- namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
-spec:
- rules:
- - http:
- paths:
- - path: /discoveryserver(/|$)(.*)
- pathType: Prefix
- backend:
- service:
- name: spring-cloud-kubernetes-discoveryserver
- port:
- number: 80
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/k8s/deployment-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/k8s/deployment-it.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/k8s/deployment-it.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/k8s/deployment-it.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/k8s/service-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/k8s/service-it.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/k8s/service-it.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/k8s/service-it.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/pom.xml
similarity index 62%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/pom.xml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/pom.xml
index d03f6401..03541153 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/pom.xml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/pom.xml
@@ -9,12 +9,12 @@
4.0.0
- spring-cloud-kubernetes-reactive-discoveryclient-it
+ spring-cloud-kubernetes-discoveryclient-it
org.springframework.boot
- spring-boot-starter-webflux
+ spring-boot-starter-web
org.springframework.cloud
@@ -46,6 +46,12 @@
docker-java-transport-httpclient5
test
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+ test
+
+
@@ -59,6 +65,55 @@
true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ docker.io/springcloud/${project.artifactId}:${project.version}
+ paketobuildpacks/builder
+
+
+
+ package
+
+ build-image
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+
+
+
+
+
+ ${testsToRun}
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/skaffold.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/skaffold.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/skaffold.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/skaffold.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/main/java/org/springframework/cloud/kubernetes/discoveryclient/it/KubernetesDiscoveryClientApplicationIt.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/main/java/org/springframework/cloud/kubernetes/discoveryclient/it/KubernetesDiscoveryClientApplicationIt.java
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/main/java/org/springframework/cloud/kubernetes/discoveryclient/it/KubernetesDiscoveryClientApplicationIt.java
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/main/java/org/springframework/cloud/kubernetes/discoveryclient/it/KubernetesDiscoveryClientApplicationIt.java
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/main/resources/application.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/main/resources/application.yaml
similarity index 80%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/main/resources/application.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/main/resources/application.yaml
index 1b70c818..ae3c7411 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/main/resources/application.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/main/resources/application.yaml
@@ -1,3 +1,7 @@
+server:
+ servlet:
+ context-path: /discoveryclient-it
+
spring:
cloud:
kubernetes:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientIT.java
new file mode 100644
index 00000000..7832cd30
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/java/org/springframework/cloud/kubernetes/discoveryclient/it/DiscoveryClientIT.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2013-2021 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
+ *
+ * https://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.discoveryclient.it;
+
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Objects;
+
+import io.kubernetes.client.openapi.ApiException;
+import io.kubernetes.client.openapi.apis.AppsV1Api;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.apis.NetworkingV1Api;
+import io.kubernetes.client.openapi.models.V1Deployment;
+import io.kubernetes.client.openapi.models.V1Ingress;
+import io.kubernetes.client.openapi.models.V1Service;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.testcontainers.k3s.K3sContainer;
+import reactor.netty.http.client.HttpClient;
+import reactor.util.retry.Retry;
+import reactor.util.retry.RetryBackoffSpec;
+
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
+import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.core.ResolvableType;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient;
+import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion;
+
+/**
+ * @author Ryan Baxter
+ */
+class DiscoveryClientIT {
+
+ private static final Log LOG = LogFactory.getLog(DiscoveryClientIT.class);
+
+ private static final String DISCOVERY_SERVER_DEPLOYMENT_NAME = "spring-cloud-kubernetes-discoveryserver-deployment";
+
+ private static final String DISCOVERY_SERVER_APP_NAME = "spring-cloud-kubernetes-discoveryserver";
+
+ private static final String SPRING_CLOUD_K8S_DISCOVERY_CLIENT_DEPLOYMENT_NAME = "spring-cloud-kubernetes-discoveryclient-it-deployment";
+
+ private static final String SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME = "spring-cloud-kubernetes-discoveryclient-it";
+
+ private static final String NAMESPACE = "default";
+
+ private static CoreV1Api api;
+
+ private static AppsV1Api appsApi;
+
+ private static NetworkingV1Api networkingApi;
+
+ private static K8SUtils k8SUtils;
+
+ private static final K3sContainer K3S = Commons.container();
+
+ @BeforeAll
+ static void beforeAll() throws Exception {
+ K3S.start();
+
+ Commons.validateImage(DISCOVERY_SERVER_APP_NAME, K3S);
+ Commons.loadImage(DISCOVERY_SERVER_APP_NAME, K3S);
+
+ Commons.validateImage(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S);
+ Commons.loadImage(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S);
+
+ createApiClient(K3S.getKubeConfigYaml());
+ api = new CoreV1Api();
+ appsApi = new AppsV1Api();
+ networkingApi = new NetworkingV1Api();
+ k8SUtils = new K8SUtils(api, appsApi);
+ k8SUtils.setUp(NAMESPACE);
+
+ deployDiscoveryServer();
+
+ // Check to make sure the discovery server deployment is ready
+ k8SUtils.waitForDeployment(DISCOVERY_SERVER_DEPLOYMENT_NAME, NAMESPACE);
+
+ // Check to see if endpoint is ready
+ k8SUtils.waitForEndpointReady(DISCOVERY_SERVER_APP_NAME, NAMESPACE);
+ }
+
+ @AfterAll
+ static void afterAll() throws Exception {
+ Commons.cleanUp(DISCOVERY_SERVER_APP_NAME, K3S);
+ Commons.cleanUp(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S);
+
+ appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
+ "metadata.name=" + DISCOVERY_SERVER_DEPLOYMENT_NAME, null, null, null, null, null, null, null, null,
+ null);
+
+ api.deleteNamespacedService(DISCOVERY_SERVER_APP_NAME, NAMESPACE, null, null, null, null, null, null);
+ networkingApi.deleteNamespacedIngress("discoveryserver-ingress", NAMESPACE, null, null, null, null, null, null);
+ }
+
+ @AfterEach
+ void afterEach() throws ApiException {
+ cleanup();
+ }
+
+ @Test
+ void testDiscoveryClient() throws Exception {
+ deployDiscoveryIt();
+ testLoadBalancer();
+ testHealth();
+ }
+
+ private void cleanup() throws ApiException {
+ appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
+ "metadata.name=" + SPRING_CLOUD_K8S_DISCOVERY_CLIENT_DEPLOYMENT_NAME, null, null, null, null, null,
+ null, null, null, null);
+ api.deleteNamespacedService(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, NAMESPACE, null, null, null, null, null,
+ null);
+ networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null);
+ }
+
+ private void testLoadBalancer() {
+
+ // Check to make sure the controller deployment is ready
+ k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_DEPLOYMENT_NAME, NAMESPACE);
+ WebClient.Builder builder = builder();
+ WebClient serviceClient = builder.baseUrl("http://localhost:80/discoveryclient-it/services").build();
+
+ String[] result = serviceClient.method(HttpMethod.GET).retrieve().bodyToMono(String[].class)
+ .retryWhen(retrySpec()).block();
+ LOG.info("Services: " + Arrays.toString(result));
+ assertThat(Arrays.stream(result).anyMatch("spring-cloud-kubernetes-discoveryserver"::equalsIgnoreCase))
+ .isTrue();
+
+ }
+
+ @SuppressWarnings("unchecked")
+ void testHealth() {
+ WebClient.Builder builder = builder();
+ WebClient serviceClient = builder.baseUrl("http://localhost:80/discoveryclient-it/actuator/health").build();
+
+ ResolvableType resolvableType = ResolvableType.forClassWithGenerics(Map.class, String.class, Object.class);
+ @SuppressWarnings("unchecked")
+ Map health = (Map) serviceClient.method(HttpMethod.GET).retrieve()
+ .bodyToMono(ParameterizedTypeReference.forType(resolvableType.getType())).retryWhen(retrySpec())
+ .block();
+
+ Map components = (Map) health.get("components");
+
+ Map discoveryComposite = (Map) components.get("discoveryComposite");
+ assertThat(discoveryComposite.get("status")).isEqualTo("UP");
+ }
+
+ private void deployDiscoveryIt() throws Exception {
+ appsApi.createNamespacedDeployment(NAMESPACE, getDiscoveryItDeployment(), null, null, null);
+ api.createNamespacedService(NAMESPACE, getDiscoveryService(), null, null, null);
+
+ V1Ingress ingress = getDiscoveryItIngress();
+ networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null);
+ k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE);
+ }
+
+ private V1Deployment getDiscoveryItDeployment() throws Exception {
+ V1Deployment deployment = (V1Deployment) k8SUtils
+ .readYamlFromClasspath("client/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml");
+ String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ + getPomVersion();
+ deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
+ return deployment;
+ }
+
+ private static void deployDiscoveryServer() throws Exception {
+ appsApi.createNamespacedDeployment(NAMESPACE, getDiscoveryServerDeployment(), null, null, null);
+ api.createNamespacedService(NAMESPACE, getDiscoveryServerService(), null, null, null);
+
+ V1Ingress ingress = getDiscoveryServerIngress();
+ networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null);
+ k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE);
+ }
+
+ private static V1Deployment getDiscoveryServerDeployment() throws Exception {
+ V1Deployment deployment = (V1Deployment) k8SUtils
+ .readYamlFromClasspath("server/spring-cloud-kubernetes-discoveryserver-deployment.yaml");
+ String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ + getPomVersion();
+ deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
+ return deployment;
+ }
+
+ private static V1Ingress getDiscoveryServerIngress() throws Exception {
+ return (V1Ingress) K8SUtils
+ .readYamlFromClasspath("server/spring-cloud-kubernetes-discoveryserver-ingress.yaml");
+ }
+
+ private static V1Service getDiscoveryServerService() throws Exception {
+ return (V1Service) K8SUtils
+ .readYamlFromClasspath("server/spring-cloud-kubernetes-discoveryserver-service.yaml");
+ }
+
+ private V1Ingress getDiscoveryItIngress() throws Exception {
+ return (V1Ingress) K8SUtils
+ .readYamlFromClasspath("client/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml");
+ }
+
+ private V1Service getDiscoveryService() throws Exception {
+ return (V1Service) K8SUtils
+ .readYamlFromClasspath("client/spring-cloud-kubernetes-discoveryclient-it-service.yaml");
+ }
+
+ private WebClient.Builder builder() {
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
+ }
+
+ private RetryBackoffSpec retrySpec() {
+ return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
+ }
+
+}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/client/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml
similarity index 85%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/client/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml
index d4f120a6..7e47e543 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/client/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml
@@ -19,10 +19,10 @@ spec:
readinessProbe:
httpGet:
port: 8080
- path: /actuator/health/readiness
+ path: /discoveryclient-it/actuator/health/readiness
livenessProbe:
httpGet:
port: 8080
- path: /actuator/health/liveness
+ path: /discoveryclient-it/actuator/health/liveness
ports:
- containerPort: 8080
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/client/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml
similarity index 74%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/client/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml
index 45aebedf..dd39366a 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/client/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml
@@ -3,13 +3,11 @@ kind: Ingress
metadata:
name: it-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /discoveryclient-it(/|$)(.*)
+ - path: /discoveryclient-it
pathType: Prefix
backend:
service:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/client/spring-cloud-kubernetes-discoveryclient-it-service.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-service.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/client/spring-cloud-kubernetes-discoveryclient-it-service.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..9e284876
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/logback-test.xml
@@ -0,0 +1,14 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/server/spring-cloud-kubernetes-discoveryserver-deployment.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-deployment.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/server/spring-cloud-kubernetes-discoveryserver-deployment.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/server/spring-cloud-kubernetes-discoveryserver-ingress.yaml
similarity index 75%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-ingress.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/server/spring-cloud-kubernetes-discoveryserver-ingress.yaml
index d58cf1b4..d820d54e 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/server/spring-cloud-kubernetes-discoveryserver-ingress.yaml
@@ -3,13 +3,11 @@ kind: Ingress
metadata:
name: discoveryserver-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /discoveryserver(/|$)(.*)
+ - path: /
pathType: Prefix
backend:
service:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/server/spring-cloud-kubernetes-discoveryserver-service.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-service.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-discoveryclient-it/src/test/resources/server/spring-cloud-kubernetes-discoveryserver-service.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/pom.xml
index a59c913a..d670bf6d 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/pom.xml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/pom.xml
@@ -16,10 +16,6 @@
org.springframework.cloud
spring-cloud-starter-kubernetes-fabric8-all
-
- org.springframework.cloud
- spring-cloud-starter-bootstrap
-
org.springframework.cloud
spring-cloud-kubernetes-test-support
@@ -55,6 +51,55 @@
true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ docker.io/springcloud/${project.artifactId}:${project.version}
+ paketobuildpacks/builder
+
+
+
+ package
+
+ build-image
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+
+
+
+
+
+ ${testsToRun}
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/main/resources/application.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/main/resources/application.yaml
new file mode 100644
index 00000000..ace4cb6b
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/main/resources/application.yaml
@@ -0,0 +1,5 @@
+spring:
+ application:
+ name: my-configmap
+ config:
+ import: "kubernetes:"
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/main/resources/bootstrap.yml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/main/resources/bootstrap.yml
deleted file mode 100644
index 7a0c1eae..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/main/resources/bootstrap.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-spring:
- cloud:
- kubernetes:
- config:
- sources:
- - name: my-configmap
- namespace: default
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8ConfigMapIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8ConfigMapIT.java
index 5ed7b928..fc3db950 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8ConfigMapIT.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8ConfigMapIT.java
@@ -16,8 +16,9 @@
package org.springframework.cloud.kubernetes.fabric8.configmap;
-import java.io.FileInputStream;
+import java.io.InputStream;
import java.time.Duration;
+import java.util.Objects;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.Service;
@@ -30,17 +31,21 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.testcontainers.k3s.K3sContainer;
import reactor.netty.http.client.HttpClient;
import reactor.util.retry.Retry;
+import reactor.util.retry.RetryBackoffSpec;
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils;
import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
-public class Fabric8ConfigMapIT {
+class Fabric8ConfigMapIT {
+
+ private static final String IMAGE_NAME = "spring-cloud-kubernetes-fabric8-client-configmap";
private static final String NAMESPACE = "default";
@@ -54,26 +59,30 @@ public class Fabric8ConfigMapIT {
private static String configMapName;
+ private static final K3sContainer K3S = Commons.container();
+
@BeforeAll
- public static void setup() {
- Config config = Config.autoConfigure(null);
+ static void beforeAll() throws Exception {
+ K3S.start();
+ Commons.validateImage(IMAGE_NAME, K3S);
+ Commons.loadImage(IMAGE_NAME, K3S);
+ Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml());
client = new DefaultKubernetesClient(config);
+ Fabric8Utils.setUp(client, NAMESPACE);
deployManifests();
}
@AfterAll
- public static void after() {
+ static void after() throws Exception {
deleteManifests();
+ Commons.cleanUp(IMAGE_NAME, K3S);
}
@Test
- public void test() {
- WebClient client = WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()))
- .baseUrl("localhost/fabric8-configmap/key1").build();
+ void test() {
+ WebClient client = builder().baseUrl("localhost/key1").build();
- String result = client.method(HttpMethod.GET).retrieve().bodyToMono(String.class)
- .retryWhen(Retry.fixedDelay(15, Duration.ofSeconds(1))
- .filter(x -> ((WebClientResponseException) x).getStatusCode().value() == 503))
+ String result = client.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
.block();
Assertions.assertEquals("value1", result);
@@ -130,20 +139,28 @@ public class Fabric8ConfigMapIT {
}
- private static FileInputStream getService() throws Exception {
+ private static InputStream getService() {
return Fabric8Utils.inputStream("fabric8-service.yaml");
}
- private static FileInputStream getDeployment() throws Exception {
+ private static InputStream getDeployment() {
return Fabric8Utils.inputStream("fabric8-deployment.yaml");
}
- private static FileInputStream getIngress() throws Exception {
+ private static InputStream getIngress() {
return Fabric8Utils.inputStream("fabric8-ingress.yaml");
}
- private static FileInputStream getConfigMap() throws Exception {
+ private static InputStream getConfigMap() {
return Fabric8Utils.inputStream("fabric8-configmap.yaml");
}
+ private WebClient.Builder builder() {
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
+ }
+
+ private RetryBackoffSpec retrySpec() {
+ return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
+ }
+
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/resources/fabric8-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/resources/fabric8-ingress.yaml
index 197f078b..51dc769b 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/resources/fabric8-ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/resources/fabric8-ingress.yaml
@@ -3,13 +3,11 @@ kind: Ingress
metadata:
name: spring-cloud-kubernetes-fabric8-client-configmap-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /fabric8-configmap(/|$)(.*)
+ - path: /
pathType: Prefix
backend:
service:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..9e284876
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-configmap/src/test/resources/logback-test.xml
@@ -0,0 +1,14 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/pom.xml
index 6b9cd73c..746b531b 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/pom.xml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/pom.xml
@@ -51,6 +51,54 @@
true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ docker.io/springcloud/${project.artifactId}:${project.version}
+ paketobuildpacks/builder
+
+
+
+ package
+
+ build-image
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+
+
+
+
+
+ ${testsToRun}
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8DiscoveryIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8DiscoveryIT.java
index 82c75691..dfa2be10 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8DiscoveryIT.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/configmap/Fabric8DiscoveryIT.java
@@ -16,9 +16,10 @@
package org.springframework.cloud.kubernetes.fabric8.configmap;
-import java.io.FileInputStream;
+import java.io.InputStream;
import java.time.Duration;
import java.util.List;
+import java.util.Objects;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.Deployment;
@@ -30,23 +31,27 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.testcontainers.k3s.K3sContainer;
import reactor.netty.http.client.HttpClient;
import reactor.util.retry.Retry;
+import reactor.util.retry.RetryBackoffSpec;
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils;
import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
/**
* @author wind57
*/
-public class Fabric8DiscoveryIT {
+class Fabric8DiscoveryIT {
private static final String NAMESPACE = "default";
+ private static final String IMAGE_NAME = "spring-cloud-kubernetes-fabric8-client-discovery";
+
private static KubernetesClient client;
private static String deploymentName;
@@ -59,30 +64,38 @@ public class Fabric8DiscoveryIT {
private static String mockDeploymentName;
+ private static String mockDeploymentImage;
+
+ private static final K3sContainer K3S = Commons.container();
+
@BeforeAll
- public static void setup() {
- Config config = Config.autoConfigure(null);
+ static void beforeAll() throws Exception {
+ K3S.start();
+ Commons.validateImage(IMAGE_NAME, K3S);
+ Commons.loadImage(IMAGE_NAME, K3S);
+
+ Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml());
client = new DefaultKubernetesClient(config);
+ Fabric8Utils.setUp(client, NAMESPACE);
deployManifests();
deployMockManifests();
}
@AfterAll
- public static void after() {
+ static void after() throws Exception {
deleteManifests();
+ Commons.cleanUp(IMAGE_NAME, K3S);
+ Commons.cleanUpDownloadedImage(mockDeploymentImage);
}
@Test
- public void test() {
- WebClient client = WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()))
- .baseUrl("localhost/fabric8-discovery/services").build();
+ void test() {
+ WebClient client = builder().baseUrl("localhost/services").build();
@SuppressWarnings("unchecked")
List result = (List) client.method(HttpMethod.GET).retrieve().bodyToMono(List.class)
- .retryWhen(Retry.fixedDelay(15, Duration.ofSeconds(1))
- .filter(x -> ((WebClientResponseException) x).getStatusCode().value() == 503))
- .block();
+ .retryWhen(retrySpec()).block();
Assertions.assertEquals(result.size(), 3);
Assertions.assertTrue(result.contains("kubernetes"));
@@ -146,6 +159,7 @@ public class Fabric8DiscoveryIT {
Deployment deployment = client.apps().deployments().load(getMockDeployment()).get();
client.apps().deployments().inNamespace(NAMESPACE).create(deployment);
mockDeploymentName = deployment.getMetadata().getName();
+ mockDeploymentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage();
Service service = client.services().load(getMockService()).get();
mockServiceName = service.getMetadata().getName();
@@ -160,24 +174,32 @@ public class Fabric8DiscoveryIT {
}
- private static FileInputStream getService() throws Exception {
+ private static InputStream getService() {
return Fabric8Utils.inputStream("fabric8-discovery-service.yaml");
}
- private static FileInputStream getDeployment() throws Exception {
+ private static InputStream getDeployment() {
return Fabric8Utils.inputStream("fabric8-discovery-deployment.yaml");
}
- private static FileInputStream getIngress() throws Exception {
+ private static InputStream getIngress() {
return Fabric8Utils.inputStream("fabric8-discovery-ingress.yaml");
}
- private static FileInputStream getMockService() throws Exception {
- return Fabric8Utils.inputStream("fabric8-discovery-wiremock-service.yaml");
+ private static InputStream getMockService() {
+ return Fabric8Utils.inputStream("wiremock/fabric8-discovery-wiremock-service.yaml");
}
- private static FileInputStream getMockDeployment() throws Exception {
- return Fabric8Utils.inputStream("fabric8-discovery-wiremock-deployment.yaml");
+ private static InputStream getMockDeployment() {
+ return Fabric8Utils.inputStream("wiremock/fabric8-discovery-wiremock-deployment.yaml");
+ }
+
+ private WebClient.Builder builder() {
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
+ }
+
+ private RetryBackoffSpec retrySpec() {
+ return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
}
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/fabric8-discovery-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/fabric8-discovery-ingress.yaml
index 0a46fe3c..334508bf 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/fabric8-discovery-ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/fabric8-discovery-ingress.yaml
@@ -3,13 +3,11 @@ kind: Ingress
metadata:
name: spring-cloud-kubernetes-fabric8-client-discovery-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /fabric8-discovery(/|$)(.*)
+ - path: /
pathType: Prefix
backend:
service:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..9e284876
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/logback-test.xml
@@ -0,0 +1,14 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/fabric8-discovery-wiremock-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/wiremock/fabric8-discovery-wiremock-deployment.yaml
similarity index 92%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/fabric8-discovery-wiremock-deployment.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/wiremock/fabric8-discovery-wiremock-deployment.yaml
index 1dc89ac9..9d28eb62 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/fabric8-discovery-wiremock-deployment.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/wiremock/fabric8-discovery-wiremock-deployment.yaml
@@ -13,7 +13,7 @@ spec:
spec:
containers:
- name: servicea-wiremock
- image: rodolpheche/wiremock:2.27.2
+ image: wiremock/wiremock:2.32.0
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/fabric8-discovery-wiremock-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/wiremock/fabric8-discovery-wiremock-service.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/fabric8-discovery-wiremock-service.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-discovery/src/test/resources/wiremock/fabric8-discovery-wiremock-service.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/pom.xml
index af96c765..4ab0f5c5 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/pom.xml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/pom.xml
@@ -51,6 +51,55 @@
true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ docker.io/springcloud/${project.artifactId}:${project.version}
+ paketobuildpacks/builder
+
+
+
+ package
+
+ build-image
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+
+
+
+
+
+ ${testsToRun}
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/main/resources/application.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/main/resources/application.yaml
new file mode 100644
index 00000000..c83b17d1
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/main/resources/application.yaml
@@ -0,0 +1,3 @@
+spring:
+ webflux:
+ base-path: /loadbalancer-it
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/Fabric8ClientLoadbalancerIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/Fabric8ClientLoadbalancerIT.java
index 46b0d35c..3eeaba5e 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/Fabric8ClientLoadbalancerIT.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/it/Fabric8ClientLoadbalancerIT.java
@@ -16,9 +16,10 @@
package org.springframework.cloud.kubernetes.client.loadbalancer.it;
-import java.io.FileInputStream;
+import java.io.InputStream;
import java.time.Duration;
import java.util.Map;
+import java.util.Objects;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.Deployment;
@@ -26,18 +27,22 @@ import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
+import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.testcontainers.k3s.K3sContainer;
import reactor.netty.http.client.HttpClient;
import reactor.util.retry.Retry;
+import reactor.util.retry.RetryBackoffSpec;
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils;
import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
import static org.assertj.core.api.Assertions.assertThat;
@@ -48,6 +53,8 @@ public class Fabric8ClientLoadbalancerIT {
private static final String NAMESPACE = "default";
+ private static final String IMAGE_NAME = "spring-cloud-kubernetes-fabric8-client-loadbalancer";
+
private static KubernetesClient client;
private static String deploymentName;
@@ -62,33 +69,44 @@ public class Fabric8ClientLoadbalancerIT {
private static String mockIngressName;
- @BeforeEach
- public void setup() {
- Config config = Config.autoConfigure(null);
+ private static final K3sContainer K3S = Commons.container();
+
+ @BeforeAll
+ static void beforeAll() throws Exception {
+ K3S.start();
+ Commons.validateImage(IMAGE_NAME, K3S);
+ Commons.loadImage(IMAGE_NAME, K3S);
+
+ Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml());
client = new DefaultKubernetesClient(config);
+ Fabric8Utils.setUp(client, NAMESPACE);
+ }
+ @AfterAll
+ static void afterAll() throws Exception {
+ Commons.cleanUp(IMAGE_NAME, K3S);
+ }
+
+ @BeforeEach
+ void beforeEach() {
deployMockManifests();
-
}
@AfterEach
- public void after() {
+ void after() {
deleteManifests();
}
@Test
- public void testLoadBalancerServiceMode() {
+ void testLoadBalancerServiceMode() {
deployServiceManifests();
- WebClient client = WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()))
- .baseUrl("localhost/loadbalancer-it/servicea").build();
+ WebClient client = builder().baseUrl("localhost/loadbalancer-it/servicea").build();
@SuppressWarnings("unchecked")
Map mapResult = (Map) client.method(HttpMethod.GET).retrieve()
- .bodyToMono(Map.class).retryWhen(Retry.fixedDelay(15, Duration.ofSeconds(1))
- .filter(x -> ((WebClientResponseException) x).getStatusCode().value() == 503))
- .block();
+ .bodyToMono(Map.class).retryWhen(retrySpec()).block();
assertThat(mapResult.containsKey("mappings")).isTrue();
assertThat(mapResult.containsKey("meta")).isTrue();
@@ -100,14 +118,11 @@ public class Fabric8ClientLoadbalancerIT {
deployPodManifests();
- WebClient client = WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()))
- .baseUrl("localhost/loadbalancer-it/servicea").build();
+ WebClient client = builder().baseUrl("localhost/loadbalancer-it/servicea").build();
@SuppressWarnings("unchecked")
Map mapResult = (Map) client.method(HttpMethod.GET).retrieve()
- .bodyToMono(Map.class).retryWhen(Retry.fixedDelay(15, Duration.ofSeconds(1))
- .filter(x -> ((WebClientResponseException) x).getStatusCode().value() == 503))
- .block();
+ .bodyToMono(Map.class).retryWhen(retrySpec()).block();
assertThat(mapResult.containsKey("mappings")).isTrue();
assertThat(mapResult.containsKey("meta")).isTrue();
@@ -220,32 +235,40 @@ public class Fabric8ClientLoadbalancerIT {
}
- private static FileInputStream getIngress() throws Exception {
+ private static InputStream getIngress() {
return Fabric8Utils.inputStream("spring-cloud-kubernetes-fabric8-client-loadbalancer-ingress.yaml");
}
- private static FileInputStream getService() throws Exception {
+ private static InputStream getService() {
return Fabric8Utils.inputStream("spring-cloud-kubernetes-fabric8-client-loadbalancer-service.yaml");
}
- private static FileInputStream getPodDeployment() throws Exception {
+ private static InputStream getPodDeployment() {
return Fabric8Utils.inputStream("spring-cloud-kubernetes-fabric8-client-loadbalancer-pod-deployment.yaml");
}
- private static FileInputStream getServiceDeployment() throws Exception {
+ private static InputStream getServiceDeployment() {
return Fabric8Utils.inputStream("spring-cloud-kubernetes-fabric8-client-loadbalancer-service-deployment.yaml");
}
- private static FileInputStream getMockIngress() throws Exception {
- return Fabric8Utils.inputStream("wiremock-ingress.yaml");
+ private static InputStream getMockIngress() {
+ return Fabric8Utils.inputStream("wiremock/wiremock-ingress.yaml");
}
- private static FileInputStream getMockService() throws Exception {
- return Fabric8Utils.inputStream("wiremock-service.yaml");
+ private static InputStream getMockService() {
+ return Fabric8Utils.inputStream("wiremock/wiremock-service.yaml");
}
- private static FileInputStream getMockDeployment() throws Exception {
- return Fabric8Utils.inputStream("wiremock-deployment.yaml");
+ private static InputStream getMockDeployment() {
+ return Fabric8Utils.inputStream("wiremock/wiremock-deployment.yaml");
+ }
+
+ private WebClient.Builder builder() {
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
+ }
+
+ private RetryBackoffSpec retrySpec() {
+ return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
}
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..9e284876
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/logback-test.xml
@@ -0,0 +1,14 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-ingress.yaml
index 3c140c5b..17aafe66 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-ingress.yaml
@@ -3,13 +3,11 @@ kind: Ingress
metadata:
name: it-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /loadbalancer-it(/|$)(.*)
+ - path: /loadbalancer-it
pathType: Prefix
backend:
service:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-pod-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-pod-deployment.yaml
index 5ecbe185..a3285b69 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-pod-deployment.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-pod-deployment.yaml
@@ -22,10 +22,10 @@ spec:
readinessProbe:
httpGet:
port: 8080
- path: /actuator/health/readiness
+ path: /loadbalancer-it/actuator/health/readiness
livenessProbe:
httpGet:
port: 8080
- path: /actuator/health/liveness
+ path: /loadbalancer-it/actuator/health/liveness
ports:
- containerPort: 8080
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-service-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-service-deployment.yaml
index c1903319..71d5120a 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-service-deployment.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/spring-cloud-kubernetes-fabric8-client-loadbalancer-service-deployment.yaml
@@ -22,10 +22,10 @@ spec:
readinessProbe:
httpGet:
port: 8080
- path: /actuator/health/readiness
+ path: /loadbalancer-it/actuator/health/readiness
livenessProbe:
httpGet:
port: 8080
- path: /actuator/health/liveness
+ path: /loadbalancer-it/actuator/health/liveness
ports:
- containerPort: 8080
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-deployment.yaml
similarity index 92%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock-deployment.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-deployment.yaml
index 1dc89ac9..9d28eb62 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock-deployment.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-deployment.yaml
@@ -13,7 +13,7 @@ spec:
spec:
containers:
- name: servicea-wiremock
- image: rodolpheche/wiremock:2.27.2
+ image: wiremock/wiremock:2.32.0
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-ingress.yaml
similarity index 75%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock-ingress.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-ingress.yaml
index 2d278b58..bd2d857a 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock-ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-ingress.yaml
@@ -3,13 +3,11 @@ kind: Ingress
metadata:
name: wiremock-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /wiremock(/|$)(.*)
+ - path: /
pathType: Prefix
backend:
service:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/wiremock-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-service.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/wiremock-service.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock/wiremock-service.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/pom.xml
index 04d16d98..132ad6d1 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/pom.xml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/pom.xml
@@ -51,6 +51,55 @@
true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ docker.io/springcloud/${project.artifactId}:${project.version}
+ paketobuildpacks/builder
+
+
+
+ package
+
+ build-image
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+
+
+
+
+
+ ${testsToRun}
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/java/SimpleCoreIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/java/SimpleCoreIT.java
index 3138beb4..885428da 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/java/SimpleCoreIT.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/java/SimpleCoreIT.java
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-import java.io.FileInputStream;
+import java.io.InputStream;
import java.time.Duration;
+import java.util.Objects;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.Deployment;
@@ -27,15 +28,17 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.testcontainers.k3s.K3sContainer;
import reactor.netty.http.client.HttpClient;
import reactor.util.retry.Retry;
+import reactor.util.retry.RetryBackoffSpec;
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils;
import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
/**
* @author wind57
@@ -44,6 +47,8 @@ class SimpleCoreIT {
private static final String NAMESPACE = "default";
+ private static final String IMAGE_NAME = "spring-cloud-kubernetes-fabric8-client-simple-core";
+
private static KubernetesClient client;
private static String deploymentName;
@@ -52,26 +57,32 @@ class SimpleCoreIT {
private static String ingressName;
+ private static final K3sContainer K3S = Commons.container();
+
@BeforeAll
- public static void setup() {
- Config config = Config.autoConfigure(null);
+ static void beforeAll() throws Exception {
+ K3S.start();
+ Commons.validateImage(IMAGE_NAME, K3S);
+ Commons.loadImage(IMAGE_NAME, K3S);
+
+ Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml());
client = new DefaultKubernetesClient(config);
+ Fabric8Utils.setUp(client, NAMESPACE);
+
deployManifests();
}
@AfterAll
- public static void after() {
+ static void after() throws Exception {
deleteManifests();
+ Commons.cleanUp(IMAGE_NAME, K3S);
}
@Test
- public void test() {
- WebClient client = WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()))
- .baseUrl("localhost/fabric8-client-simple-core/message").build();
+ void test() {
+ WebClient client = builder().baseUrl("localhost/message").build();
- String result = client.method(HttpMethod.GET).retrieve().bodyToMono(String.class)
- .retryWhen(Retry.fixedDelay(15, Duration.ofSeconds(1))
- .filter(x -> ((WebClientResponseException) x).getStatusCode().value() == 503))
+ String result = client.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
.block();
// value must come from application-kubernetes.yml
@@ -124,16 +135,24 @@ class SimpleCoreIT {
}
- private static FileInputStream getService() throws Exception {
+ private static InputStream getService() {
return Fabric8Utils.inputStream("simple-core-service.yaml");
}
- private static FileInputStream getDeployment() throws Exception {
+ private static InputStream getDeployment() {
return Fabric8Utils.inputStream("simple-core-deployment.yaml");
}
- private static FileInputStream getIngress() throws Exception {
+ private static InputStream getIngress() {
return Fabric8Utils.inputStream("simple-core-ingress.yaml");
}
+ private WebClient.Builder builder() {
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
+ }
+
+ private RetryBackoffSpec retrySpec() {
+ return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
+ }
+
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..9e284876
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/resources/logback-test.xml
@@ -0,0 +1,14 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/resources/simple-core-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/resources/simple-core-ingress.yaml
index cd7de80b..d0b52aa4 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/resources/simple-core-ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-simple-core/src/test/resources/simple-core-ingress.yaml
@@ -3,13 +3,11 @@ kind: Ingress
metadata:
name: it-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /fabric8-client-simple-core(/|$)(.*)
+ - path: /
pathType: Prefix
backend:
service:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/pom.xml
index 0201b5cb..bef179e4 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/pom.xml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/pom.xml
@@ -51,6 +51,55 @@
true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ docker.io/springcloud/${project.artifactId}:${project.version}
+ paketobuildpacks/builder
+
+
+
+ package
+
+ build-image
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+
+
+
+
+
+ ${testsToRun}
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/Fabric8IstioIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/Fabric8IstioIT.java
index 98fa5941..eae29da6 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/Fabric8IstioIT.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/Fabric8IstioIT.java
@@ -16,9 +16,11 @@
package org.springframework.cloud.kubernetes.fabric8.istio;
-import java.io.FileInputStream;
+import java.io.File;
+import java.io.InputStream;
import java.time.Duration;
import java.util.List;
+import java.util.Objects;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.Deployment;
@@ -30,23 +32,32 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.testcontainers.containers.Container;
+import org.testcontainers.k3s.K3sContainer;
import reactor.netty.http.client.HttpClient;
import reactor.util.retry.Retry;
+import reactor.util.retry.RetryBackoffSpec;
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils;
import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
/**
* @author wind57
*/
-public class Fabric8IstioIT {
+class Fabric8IstioIT {
private static final String NAMESPACE = "istio-test";
+ private static final String IMAGE_NAME = "spring-cloud-kubernetes-fabric8-istio-it";
+
+ private static final String LOCAL_ISTIO_BIN_PATH = "../../istio-cli/istio-1.13.3/bin";
+
+ private static final String CONTAINER_ISTIO_BIN_PATH = "/tmp/istio/istio-bin/bin/";
+
private static KubernetesClient client;
private static String deploymentName;
@@ -55,27 +66,54 @@ public class Fabric8IstioIT {
private static String ingressName;
+ private static K3sContainer K3S;
+
@BeforeAll
- public static void setup() {
- Config config = Config.autoConfigure(null);
+ static void beforeAll() throws Exception {
+ // Path passed to K3S container must be absolute
+ String absolutePath = new File(LOCAL_ISTIO_BIN_PATH).getAbsolutePath();
+ K3S = Commons.container().withFileSystemBind(absolutePath, CONTAINER_ISTIO_BIN_PATH);
+ K3S.start();
+ Commons.validateImage(IMAGE_NAME, K3S);
+ Commons.loadImage(IMAGE_NAME, K3S);
+
+ processExecResult(K3S.execInContainer("sh", "-c", "kubectl create namespace istio-test"));
+ processExecResult(
+ K3S.execInContainer("sh", "-c", "kubectl label namespace istio-test istio-injection=enabled"));
+
+ // for Mac M1 with aarch64
+ if (System.getProperty("os.arch").equals("aarch64")) {
+ processExecResult(K3S.execInContainer("sh", "-c", CONTAINER_ISTIO_BIN_PATH + "istioctl"
+ + " --kubeconfig=/etc/rancher/k3s/k3s.yaml install --set hub=docker.io/querycapistio --set profile=minimal -y"));
+ }
+ else {
+ processExecResult(K3S.execInContainer("sh", "-c", CONTAINER_ISTIO_BIN_PATH + "istioctl"
+ + " --kubeconfig=/etc/rancher/k3s/k3s.yaml install --set profile=minimal -y"));
+ }
+
+ Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml());
client = new DefaultKubernetesClient(config);
+ Fabric8Utils.setUpIstio(client, NAMESPACE);
+
deployManifests();
}
@AfterAll
- public static void after() {
+ static void afterAll() throws Exception {
+ Commons.cleanUp(IMAGE_NAME, K3S);
+ }
+
+ @AfterAll
+ static void after() {
deleteManifests();
}
@Test
- public void test() {
- WebClient client = WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()))
- .baseUrl("localhost/fabric8-client-istio/profiles").build();
+ void test() {
+ WebClient client = builder().baseUrl("localhost/profiles").build();
@SuppressWarnings("unchecked")
- List result = client.method(HttpMethod.GET).retrieve().bodyToMono(List.class)
- .retryWhen(Retry.fixedDelay(15, Duration.ofSeconds(1))
- .filter(x -> ((WebClientResponseException) x).getStatusCode().value() == 503))
+ List result = client.method(HttpMethod.GET).retrieve().bodyToMono(List.class).retryWhen(retrySpec())
.block();
// istio profile is present
@@ -92,6 +130,7 @@ public class Fabric8IstioIT {
}
catch (Exception e) {
+ e.printStackTrace();
throw new RuntimeException(e);
}
@@ -118,26 +157,44 @@ public class Fabric8IstioIT {
ingressName = ingress.getMetadata().getName();
client.network().v1().ingresses().inNamespace(NAMESPACE).create(ingress);
+ Fabric8Utils.waitForIngress(client, ingressName, NAMESPACE);
Fabric8Utils.waitForDeployment(client, "spring-cloud-kubernetes-fabric8-istio-it-deployment", NAMESPACE, 2,
600);
}
catch (Exception e) {
+ e.printStackTrace();
throw new RuntimeException(e);
}
}
- private static FileInputStream getService() throws Exception {
+ private static InputStream getService() {
return Fabric8Utils.inputStream("istio-service.yaml");
}
- private static FileInputStream getDeployment() throws Exception {
+ private static InputStream getDeployment() {
return Fabric8Utils.inputStream("istio-deployment.yaml");
}
- private static FileInputStream getIngress() throws Exception {
+ private static InputStream getIngress() {
return Fabric8Utils.inputStream("istio-ingress.yaml");
}
+ private WebClient.Builder builder() {
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
+ }
+
+ private RetryBackoffSpec retrySpec() {
+ return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
+ }
+
+ private static String processExecResult(Container.ExecResult execResult) {
+ if (execResult.getExitCode() != 0) {
+ throw new RuntimeException("stdout=" + execResult.getStdout() + "\n" + "stderr=" + execResult.getStderr());
+ }
+
+ return execResult.getStdout();
+ }
+
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/resources/istio-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/resources/istio-ingress.yaml
index 5def7c6c..f5e5d776 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/resources/istio-ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/resources/istio-ingress.yaml
@@ -3,13 +3,11 @@ kind: Ingress
metadata:
name: it-ingress
namespace: istio-test
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /fabric8-client-istio(/|$)(.*)
+ - path: /
pathType: Prefix
backend:
service:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..9e284876
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-istio-it/src/test/resources/logback-test.xml
@@ -0,0 +1,14 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/k8s/deployment-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/k8s/deployment-it.yaml
deleted file mode 100644
index 7e9b54fb..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/k8s/deployment-it.yaml
+++ /dev/null
@@ -1,26 +0,0 @@
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- creationTimestamp: null
- labels:
- app: spring-cloud-kubernetes-reactive-discoveryclient-it
- name: spring-cloud-kubernetes-reactive-discoveryclient-it-deployment
-spec:
- replicas: 1
- selector:
- matchLabels:
- app: spring-cloud-kubernetes-reactive-discoveryclient-it
- strategy: {}
- template:
- metadata:
- creationTimestamp: null
- labels:
- app: spring-cloud-kubernetes-reactive-discoveryclient-it
- spec:
- serviceAccountName: spring-cloud-kubernetes-serviceaccount
- containers:
- - image: springcloud/spring-cloud-kubernetes-reactive-discoveryclient-it:2.0.4-SNAPSHOT
- imagePullPolicy: IfNotPresent
- name: spring-cloud-kubernetes-reactive-discoveryclient-it
- resources: {}
-status: {}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/k8s/service-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/k8s/service-it.yaml
deleted file mode 100644
index 5b253f93..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/k8s/service-it.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- creationTimestamp: null
- labels:
- app: spring-cloud-kubernetes-reactive-discoveryclient-it
- name: spring-cloud-kubernetes-reactive-discoveryclient-it
-spec:
- ports:
- - name: 80-8080
- port: 80
- protocol: TCP
- targetPort: 8080
- selector:
- app: spring-cloud-kubernetes-reactive-discoveryclient-it
- type: ClusterIP
-status:
- loadBalancer: {}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/skaffold.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/skaffold.yaml
deleted file mode 100644
index 599b2ebf..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/skaffold.yaml
+++ /dev/null
@@ -1,22 +0,0 @@
-apiVersion: skaffold/v2alpha3
-kind: Config
-metadata:
- name: spring-cloud-kubernetes-reactive-discoveryclient-it
-build:
- artifacts:
- - image: springcloud/spring-cloud-kubernetes-reactive-discoveryclient-it
- jib: {
- args: [ "-Pjib" ]
- }
-# custom:
-# buildCommand: "../../mvnw clean install -Pskaffold"
-# dependencies:
-# paths:
-# - src
-# - pom.xml
-deploy:
- kubectl:
- manifests:
- - k8s/deployment-it.yaml
- - k8s/service-it.yaml
- - ../permissions.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/main/java/org/springframework/cloud/kubernetes/reactive/discoveryclient/it/KubernetesReactiveDiscoveryClientApplicationIt.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/main/java/org/springframework/cloud/kubernetes/reactive/discoveryclient/it/KubernetesReactiveDiscoveryClientApplicationIt.java
deleted file mode 100644
index 0974a80c..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/main/java/org/springframework/cloud/kubernetes/reactive/discoveryclient/it/KubernetesReactiveDiscoveryClientApplicationIt.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2013-2021 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
- *
- * https://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.reactive.discoveryclient.it;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.cloud.client.ServiceInstance;
-import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * @author Ryan Baxter
- */
-@SpringBootApplication
-@RestController
-public class KubernetesReactiveDiscoveryClientApplicationIt {
-
- private final ReactiveDiscoveryClient discoveryClient;
-
- public KubernetesReactiveDiscoveryClientApplicationIt(ReactiveDiscoveryClient discoveryClient) {
- this.discoveryClient = discoveryClient;
- }
-
- public static void main(String[] args) {
- SpringApplication.run(KubernetesReactiveDiscoveryClientApplicationIt.class, args);
- }
-
- @GetMapping("/services")
- public Mono> services() {
- return discoveryClient.getServices().collect(Collectors.toList());
- }
-
- @GetMapping("/service/{serviceId}")
- public Flux service(@PathVariable String serviceId) {
- return discoveryClient.getInstances(serviceId);
- }
-
-}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/java/org/springframework/cloud/kubernetes/reactive/discoveryclient/it/ReactiveDiscoveryClientIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/java/org/springframework/cloud/kubernetes/reactive/discoveryclient/it/ReactiveDiscoveryClientIT.java
deleted file mode 100644
index cdfd25b7..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/java/org/springframework/cloud/kubernetes/reactive/discoveryclient/it/ReactiveDiscoveryClientIT.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright 2013-2021 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
- *
- * https://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.reactive.discoveryclient.it;
-
-import java.io.IOException;
-import java.time.Duration;
-import java.util.Arrays;
-import java.util.Map;
-
-import io.kubernetes.client.openapi.ApiClient;
-import io.kubernetes.client.openapi.ApiException;
-import io.kubernetes.client.openapi.apis.AppsV1Api;
-import io.kubernetes.client.openapi.apis.CoreV1Api;
-import io.kubernetes.client.openapi.apis.NetworkingV1Api;
-import io.kubernetes.client.openapi.models.V1Deployment;
-import io.kubernetes.client.openapi.models.V1Ingress;
-import io.kubernetes.client.openapi.models.V1Service;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-import org.springframework.boot.web.client.RestTemplateBuilder;
-import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.web.client.ResponseErrorHandler;
-import org.springframework.web.client.RestTemplate;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.awaitility.Awaitility.await;
-import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient;
-import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion;
-
-/**
- * @author Ryan Baxter
- */
-class ReactiveDiscoveryClientIT {
-
- private static final Log LOG = LogFactory.getLog(ReactiveDiscoveryClientIT.class);
-
- private static final String DISCOVERYSERVER_DEPLOYMENT_NAME = "spring-cloud-kubernetes-discoveryserver-deployment";
-
- private static final String DISCOVERYSERVER_APP_NAME = "spring-cloud-kubernetes-discoveryserver";
-
- private static final String SPRING_CLOUD_K8S_DISCOVERYCLIENT_DEPLOYMENT_NAME = "spring-cloud-kubernetes-discoveryclient-it-deployment";
-
- private static final String SPRING_CLOUD_K8S_DISCOVERYCLIENT_APP_NAME = "spring-cloud-kubernetes-discoveryclient-it";
-
- private static final String NAMESPACE = "default";
-
- private static ApiClient client;
-
- private static CoreV1Api api;
-
- private static AppsV1Api appsApi;
-
- private static NetworkingV1Api networkingApi;
-
- private static K8SUtils k8SUtils;
-
- @BeforeAll
- public static void setup() throws Exception {
- client = createApiClient();
- api = new CoreV1Api();
- appsApi = new AppsV1Api();
- networkingApi = new NetworkingV1Api();
- k8SUtils = new K8SUtils(api, appsApi);
-
- deployDiscoveryServer();
-
- // Check to make sure the discovery server deployment is ready
- k8SUtils.waitForDeployment(DISCOVERYSERVER_DEPLOYMENT_NAME, NAMESPACE);
-
- // Check to see if endpoint is ready
- k8SUtils.waitForEndpointReady(DISCOVERYSERVER_APP_NAME, NAMESPACE);
-
- }
-
- @Test
- public void testDiscoveryClient() throws Exception {
- try {
- deployDiscoveryIt();
- testLoadBalancer();
- testHealth();
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- finally {
- cleanup();
- }
- }
-
- private void cleanup() throws ApiException {
- appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
- "metadata.name=" + SPRING_CLOUD_K8S_DISCOVERYCLIENT_DEPLOYMENT_NAME, null, null, null, null, null, null,
- null, null, null);
- api.deleteNamespacedService(SPRING_CLOUD_K8S_DISCOVERYCLIENT_APP_NAME, NAMESPACE, null, null, null, null, null,
- null);
- networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null);
- }
-
- private void testLoadBalancer() throws Exception {
- // Check to make sure the controller deployment is ready
- k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_DISCOVERYCLIENT_DEPLOYMENT_NAME, NAMESPACE);
- RestTemplate rest = createRestTemplate();
- // Sometimes the NGINX ingress takes a bit to catch up and realize the service is
- // available and we get a 503, we just need to wait a bit
- await().timeout(Duration.ofSeconds(60))
- .until(() -> rest.getForEntity("http://localhost:80/discoveryclient-it/services", String.class)
- .getStatusCode().is2xxSuccessful());
- String[] result = rest.getForObject("http://localhost:80/discoveryclient-it/services", String[].class);
- LOG.info("Services: " + Arrays.toString(result));
- assertThat(Arrays.stream(result).anyMatch(s -> "spring-cloud-kubernetes-discoveryserver".equalsIgnoreCase(s)))
- .isTrue();
-
- }
-
- private RestTemplate createRestTemplate() {
- RestTemplate rest = new RestTemplateBuilder().build();
-
- rest.setErrorHandler(new ResponseErrorHandler() {
- @Override
- public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
- LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
- return clientHttpResponse.getRawStatusCode() != 503;
- }
-
- @Override
- public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
-
- }
- });
- return rest;
- }
-
- public void testHealth() {
- RestTemplate rest = createRestTemplate();
-
- // Sometimes the NGINX ingress takes a bit to catch up and realize the service is
- // available and we get a 503, we just need to wait a bit
- await().timeout(Duration.ofSeconds(60))
- .until(() -> rest.getForEntity("http://localhost:80/discoveryclient-it/actuator/health", String.class)
- .getStatusCode().is2xxSuccessful());
-
- Map health = rest.getForObject("http://localhost:80/discoveryclient-it/actuator/health",
- Map.class);
- Map components = (Map) health.get("components");
-
- Map discoveryComposite = (Map) components.get("discoveryComposite");
- assertThat(discoveryComposite.get("status")).isEqualTo("UP");
- }
-
- @AfterAll
- public static void after() throws Exception {
- appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
- "metadata.name=" + DISCOVERYSERVER_DEPLOYMENT_NAME, null, null, null, null, null, null, null, null,
- null);
-
- api.deleteNamespacedService(DISCOVERYSERVER_APP_NAME, NAMESPACE, null, null, null, null, null, null);
- networkingApi.deleteNamespacedIngress("discoveryserver-ingress", NAMESPACE, null, null, null, null, null, null);
-
- }
-
- private void deployDiscoveryIt() throws Exception {
- appsApi.createNamespacedDeployment(NAMESPACE, getDiscoveryItDeployment(), null, null, null);
- api.createNamespacedService(NAMESPACE, getDiscoveryService(), null, null, null);
- networkingApi.createNamespacedIngress(NAMESPACE, getDiscoveryItIngress(), null, null, null);
- }
-
- private V1Deployment getDiscoveryItDeployment() throws Exception {
- V1Deployment deployment = (V1Deployment) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-discoveryclient-it-deployment.yaml");
- String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
- + getPomVersion();
- deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
- return deployment;
- }
-
- private static void deployDiscoveryServer() throws Exception {
- appsApi.createNamespacedDeployment(NAMESPACE, getDiscoveryServerDeployment(), null, null, null);
- api.createNamespacedService(NAMESPACE, getDiscoveryServerService(), null, null, null);
- networkingApi.createNamespacedIngress(NAMESPACE, getDiscoveryServerIngress(), null, null, null);
- }
-
- private static V1Deployment getDiscoveryServerDeployment() throws Exception {
- V1Deployment deployment = (V1Deployment) K8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-discoveryserver-deployment.yaml");
- String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
- + getPomVersion();
- deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
- return deployment;
- }
-
- private V1Service getDiscoveryService() throws Exception {
- return (V1Service) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-discoveryclient-it-service.yaml");
- }
-
- private static V1Ingress getDiscoveryServerIngress() throws Exception {
- return (V1Ingress) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-discoveryserver-ingress.yaml");
- }
-
- private V1Ingress getDiscoveryItIngress() throws Exception {
- return (V1Ingress) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-discoveryclient-it-ingress.yaml");
- }
-
- private static V1Service getDiscoveryServerService() throws Exception {
- return (V1Service) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-discoveryserver-service.yaml");
- }
-
-}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml
deleted file mode 100644
index e42d0c39..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml
+++ /dev/null
@@ -1,28 +0,0 @@
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: spring-cloud-kubernetes-discoveryclient-it-deployment
-spec:
- selector:
- matchLabels:
- app: spring-cloud-kubernetes-discoveryclient-it
- template:
- metadata:
- labels:
- app: spring-cloud-kubernetes-discoveryclient-it
- spec:
- serviceAccountName: spring-cloud-kubernetes-serviceaccount
- containers:
- - name: spring-cloud-kubernetes-discoveryclient-it
- image: docker.io/springcloud/spring-cloud-kubernetes-reactive-discoveryclient-it
- imagePullPolicy: IfNotPresent
- readinessProbe:
- httpGet:
- port: 8080
- path: /actuator/health/readiness
- livenessProbe:
- httpGet:
- port: 8080
- path: /actuator/health/liveness
- ports:
- - containerPort: 8080
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-service.yaml
deleted file mode 100644
index 32b4bd7e..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryclient-it-service.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- labels:
- app: spring-cloud-kubernetes-discoveryclient-it
- name: spring-cloud-kubernetes-discoveryclient-it
-spec:
- ports:
- - name: http
- port: 8080
- targetPort: 8080
- selector:
- app: spring-cloud-kubernetes-discoveryclient-it
- type: ClusterIP
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-deployment.yaml
deleted file mode 100644
index 3672520d..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-deployment.yaml
+++ /dev/null
@@ -1,28 +0,0 @@
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: spring-cloud-kubernetes-discoveryserver-deployment
-spec:
- selector:
- matchLabels:
- app: spring-cloud-kubernetes-discoveryserver
- template:
- metadata:
- labels:
- app: spring-cloud-kubernetes-discoveryserver
- spec:
- serviceAccountName: spring-cloud-kubernetes-serviceaccount
- containers:
- - name: spring-cloud-kubernetes-discoveryserver
- image: docker.io/springcloud/spring-cloud-kubernetes-discoveryserver
- imagePullPolicy: IfNotPresent
- readinessProbe:
- httpGet:
- port: 8761
- path: /actuator/health/readiness
- livenessProbe:
- httpGet:
- port: 8761
- path: /actuator/health/liveness
- ports:
- - containerPort: 8761
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-service.yaml
deleted file mode 100644
index ba996118..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-reactive-discovery-client-it/src/test/resources/spring-cloud-kubernetes-discoveryserver-service.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- labels:
- app: spring-cloud-kubernetes-discoveryserver
- name: spring-cloud-kubernetes-discoveryserver
-spec:
- ports:
- - name: http
- port: 80
- targetPort: 8761
- selector:
- app: spring-cloud-kubernetes-discoveryserver
- type: ClusterIP
diff --git a/spring-cloud-kubernetes-test-support/pom.xml b/spring-cloud-kubernetes-test-support/pom.xml
index 94fa3ba0..0a0379fd 100644
--- a/spring-cloud-kubernetes-test-support/pom.xml
+++ b/spring-cloud-kubernetes-test-support/pom.xml
@@ -41,6 +41,18 @@
awaitility
${awaitility.version}
+
+
+ org.testcontainers
+ testcontainers
+ 1.16.3
+
+
+ org.testcontainers
+ k3s
+ 1.16.3
+
+
diff --git a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Commons.java b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Commons.java
new file mode 100644
index 00000000..71414f8a
--- /dev/null
+++ b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Commons.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2013-2022 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
+ *
+ * https://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.integration.tests.commons;
+
+import java.io.File;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+
+import com.github.dockerjava.api.model.Image;
+import org.testcontainers.k3s.K3sContainer;
+import org.testcontainers.utility.DockerImageName;
+
+import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion;
+
+/**
+ * A few commons things that can be re-used across clients. This is meant to be used for
+ * testing purposes only.
+ *
+ * @author wind57
+ */
+public final class Commons {
+
+ private Commons() {
+ throw new AssertionError("No instance provided");
+ }
+
+ /**
+ * Rancher version to use for test-containers.
+ */
+ public static final String RANCHER = "rancher/k3s:v1.21.10-k3s1";
+
+ /**
+ * Command to use when starting rancher. Without "server" option, traefik si not
+ * installed
+ */
+ public static final String RANCHER_COMMAND = "server";
+
+ /**
+ * Test containers exposed ports.
+ */
+ public static final int[] EXPOSED_PORTS = new int[] { 80, 6443, 8080, 8888, 9092 };
+
+ /**
+ * Temporary folder where to load images.
+ */
+ public static final String TEMP_FOLDER = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath();
+
+ private static final K3sContainer CONTAINER = new FixedPortsK3sContainer(DockerImageName.parse(Commons.RANCHER))
+ .configureFixedPorts(EXPOSED_PORTS).withFileSystemBind(TEMP_FOLDER, TEMP_FOLDER)
+ .withCommand(Commons.RANCHER_COMMAND).withReuse(true);
+
+ public static K3sContainer container() {
+ return CONTAINER;
+ }
+
+ public static void loadImage(String image, K3sContainer container) throws Exception {
+ // save image
+ InputStream imageStream = container.getDockerClient().saveImageCmd("springcloud/" + image)
+ .withTag(getPomVersion()).exec();
+
+ Path imagePath = Paths.get(TEMP_FOLDER + "/" + image + ".tar");
+ Files.deleteIfExists(imagePath);
+ Files.copy(imageStream, imagePath);
+ // import image with ctr. this works because TEMP_FOLDER is mounted in the
+ // container
+ container.execInContainer("ctr", "i", "import", TEMP_FOLDER + "/" + image + ".tar");
+ }
+
+ public static void cleanUp(String image, K3sContainer container) throws Exception {
+ container.execInContainer("crictl", "rmi", "docker.io/springcloud/" + image + ":" + getPomVersion());
+ container.execInContainer("rm", TEMP_FOLDER + "/" + image + ".tar");
+ }
+
+ public static void cleanUpDownloadedImage(String image) throws Exception {
+ CONTAINER.execInContainer("crictl", "rmi", image);
+ }
+
+ /**
+ * validates that the provided image does exist in the local docker registry.
+ */
+ public static void validateImage(String image, K3sContainer container) {
+ List images = container.getDockerClient().listImagesCmd().exec();
+ images.stream()
+ .filter(x -> Arrays.stream(x.getRepoTags() == null ? new String[] {} : x.getRepoTags())
+ .anyMatch(y -> y.contains(image)))
+ .findFirst().orElseThrow(() -> new IllegalArgumentException("Image : " + image + " not build locally. "
+ + "You need to build it first, and then run the test"));
+ }
+
+ /**
+ * A K3sContainer, but with fixed port mappings. This is needed because of the nature
+ * of some integration tests.
+ *
+ * @author wind57
+ */
+ private static final class FixedPortsK3sContainer extends K3sContainer {
+
+ private FixedPortsK3sContainer(DockerImageName dockerImageName) {
+ super(dockerImageName);
+ }
+
+ private FixedPortsK3sContainer configureFixedPorts(int[] ports) {
+ for (int port : ports) {
+ super.addFixedExposedPort(port, port);
+ }
+ return this;
+ }
+
+ }
+
+}
diff --git a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Fabric8Utils.java b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Fabric8Utils.java
index eb95c71e..93d25e10 100644
--- a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Fabric8Utils.java
+++ b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/Fabric8Utils.java
@@ -16,13 +16,18 @@
package org.springframework.cloud.kubernetes.integration.tests.commons;
-import java.io.File;
-import java.io.FileInputStream;
+import java.io.InputStream;
import java.time.Duration;
+import java.util.List;
import java.util.concurrent.TimeUnit;
import io.fabric8.kubernetes.api.model.Endpoints;
+import io.fabric8.kubernetes.api.model.LoadBalancerIngress;
+import io.fabric8.kubernetes.api.model.ServiceAccount;
import io.fabric8.kubernetes.api.model.apps.Deployment;
+import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
+import io.fabric8.kubernetes.api.model.rbac.Role;
+import io.fabric8.kubernetes.api.model.rbac.RoleBinding;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -41,10 +46,8 @@ public final class Fabric8Utils {
throw new AssertionError("no instance provided");
}
- public static FileInputStream inputStream(String fileName) throws Exception {
- ClassLoader classLoader = Fabric8Utils.class.getClassLoader();
- File file = new File(classLoader.getResource(fileName).getFile());
- return new FileInputStream(file);
+ public static InputStream inputStream(String fileName) {
+ return Fabric8Utils.class.getClassLoader().getResourceAsStream(fileName);
}
public static void waitForDeployment(KubernetesClient client, String deploymentName, String namespace,
@@ -79,4 +82,77 @@ public final class Fabric8Utils {
return endpoint.getSubsets().get(0).getAddresses().size() >= 1;
}
+ public static void setUp(KubernetesClient client, String namespace) throws Exception {
+ InputStream serviceAccountAsStream = inputStream("setup/service-account.yaml");
+ InputStream roleBindingAsStream = inputStream("setup/role-binding.yaml");
+ InputStream roleAsStream = inputStream("setup/role.yaml");
+
+ innerSetup(client, namespace, serviceAccountAsStream, roleBindingAsStream, roleAsStream);
+ }
+
+ public static void setUpIstio(KubernetesClient client, String namespace) throws Exception {
+ InputStream serviceAccountAsStream = inputStream("istio/service-account.yaml");
+ InputStream roleBindingAsStream = inputStream("istio/role-binding.yaml");
+ InputStream roleAsStream = inputStream("istio/role.yaml");
+
+ innerSetup(client, namespace, serviceAccountAsStream, roleBindingAsStream, roleAsStream);
+ }
+
+ public static void waitForIngress(KubernetesClient client, String ingressName, String namespace) {
+
+ try {
+ await().pollInterval(Duration.ofSeconds(2)).atMost(180, TimeUnit.SECONDS).until(() -> {
+ Ingress ingress = client.network().v1().ingresses().inNamespace(namespace).withName(ingressName).get();
+
+ if (ingress == null) {
+ System.out.println("ingress : " + ingressName + " not ready yet present");
+ return false;
+ }
+
+ List loadBalancerIngress = ingress.getStatus().getLoadBalancer().getIngress();
+ if (loadBalancerIngress == null || loadBalancerIngress.isEmpty()) {
+ System.out.println(
+ "ingress : " + ingressName + " not ready yet (loadbalancer ingress not yet present)");
+ return false;
+ }
+
+ String ip = loadBalancerIngress.get(0).getIp();
+ if (ip == null) {
+ System.out.println("ingress : " + ingressName + " not ready yet");
+ return false;
+ }
+
+ System.out.println("ingress : " + ingressName + " ready with ip : " + ip);
+ return true;
+
+ });
+ }
+ catch (Exception e) {
+ System.out.println("Error waiting for ingress");
+ e.printStackTrace();
+ }
+
+ }
+
+ private static void innerSetup(KubernetesClient client, String namespace, InputStream serviceAccountAsStream,
+ InputStream roleBindingAsStream, InputStream roleAsStream) {
+ ServiceAccount serviceAccountFromStream = client.serviceAccounts().load(serviceAccountAsStream).get();
+ if (client.serviceAccounts().inNamespace(namespace).withName(serviceAccountFromStream.getMetadata().getName())
+ .get() == null) {
+ client.serviceAccounts().inNamespace(namespace).create(serviceAccountFromStream);
+ }
+
+ RoleBinding roleBindingFromStream = client.rbac().roleBindings().load(roleBindingAsStream).get();
+ if (client.rbac().roleBindings().inNamespace(namespace).withName(roleBindingFromStream.getMetadata().getName())
+ .get() == null) {
+ client.rbac().roleBindings().inNamespace(namespace).create(roleBindingFromStream);
+ }
+
+ Role roleFromStream = client.rbac().roles().load(roleAsStream).get();
+ if (client.rbac().roles().inNamespace(namespace).withName(roleFromStream.getMetadata().getName())
+ .get() == null) {
+ client.rbac().roles().inNamespace(namespace).create(roleFromStream);
+ }
+ }
+
}
diff --git a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/K8SUtils.java b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/K8SUtils.java
index 10feae86..dedf09af 100644
--- a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/K8SUtils.java
+++ b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/K8SUtils.java
@@ -17,32 +17,42 @@
package org.springframework.cloud.kubernetes.integration.tests.commons;
import java.io.BufferedReader;
-import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.AppsV1Api;
import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.apis.NetworkingV1Api;
+import io.kubernetes.client.openapi.apis.RbacAuthorizationV1Api;
import io.kubernetes.client.openapi.models.V1Deployment;
import io.kubernetes.client.openapi.models.V1DeploymentBuilder;
import io.kubernetes.client.openapi.models.V1DeploymentList;
import io.kubernetes.client.openapi.models.V1Endpoints;
import io.kubernetes.client.openapi.models.V1EndpointsList;
import io.kubernetes.client.openapi.models.V1EnvVar;
+import io.kubernetes.client.openapi.models.V1Ingress;
+import io.kubernetes.client.openapi.models.V1LoadBalancerIngress;
+import io.kubernetes.client.openapi.models.V1LoadBalancerStatus;
import io.kubernetes.client.openapi.models.V1ReplicationController;
import io.kubernetes.client.openapi.models.V1ReplicationControllerList;
+import io.kubernetes.client.openapi.models.V1Role;
+import io.kubernetes.client.openapi.models.V1RoleBinding;
import io.kubernetes.client.openapi.models.V1Service;
+import io.kubernetes.client.openapi.models.V1ServiceAccount;
import io.kubernetes.client.openapi.models.V1ServiceBuilder;
import io.kubernetes.client.util.Config;
import io.kubernetes.client.util.Yaml;
@@ -64,12 +74,20 @@ public class K8SUtils {
private static final String KUBERNETES_VERSION_FILE = "META-INF/springcloudkubernetes-version.txt";
+ private static final String WIREMOCK_DEPLOYMENT_NAME = "servicea-wiremock-deployment";
+
+ private static final String WIREMOCK_APP_NAME = "servicea-wiremock";
+
private final Log log = LogFactory.getLog(getClass());
private final CoreV1Api api;
private final AppsV1Api appsApi;
+ private final NetworkingV1Api networkingApi;
+
+ private final RbacAuthorizationV1Api rbacApi;
+
public static ApiClient createApiClient() throws IOException {
return createApiClient(false, Duration.ofSeconds(15));
}
@@ -97,9 +115,19 @@ public class K8SUtils {
return client;
}
+ public static ApiClient createApiClient(String configFile) throws IOException {
+ ApiClient client = Config.fromConfig(new StringReader(configFile));
+ client.setHttpClient(client.getHttpClient().newBuilder().readTimeout(Duration.ofSeconds(15)).build());
+ client.setDebugging(false);
+ Configuration.setDefaultApiClient(client);
+ return client;
+ }
+
public K8SUtils(CoreV1Api api, AppsV1Api appsApi) {
this.api = api;
this.appsApi = appsApi;
+ this.networkingApi = new NetworkingV1Api();
+ this.rbacApi = new RbacAuthorizationV1Api();
}
public Object readYaml(String urlString) throws Exception {
@@ -125,7 +153,8 @@ public class K8SUtils {
public static Object readYamlFromClasspath(String fileName) throws Exception {
ClassLoader classLoader = K8SUtils.class.getClassLoader();
- File file = new File(classLoader.getResource(fileName).getFile());
+ String file = new BufferedReader(new InputStreamReader(classLoader.getResourceAsStream(fileName))).lines()
+ .collect(Collectors.joining("\n"));
return Yaml.load(file);
}
@@ -185,7 +214,7 @@ public class K8SUtils {
V1ReplicationController replicationController = controllerList.getItems().get(0);
Integer availableReplicas = replicationController.getStatus().getAvailableReplicas();
- log.info("Available replicas for " + name + ": " + availableReplicas);
+ log.info("Available replicas for " + name + ": " + (availableReplicas == null ? 0 : availableReplicas));
return availableReplicas != null && availableReplicas >= 1;
}
@@ -195,6 +224,41 @@ public class K8SUtils {
.until(() -> isDeploymentReady(deploymentName, namespace));
}
+ public void waitForIngress(String ingressName, String namespace) {
+ await().timeout(Duration.ofSeconds(90)).pollInterval(Duration.ofSeconds(3)).until(() -> {
+ try {
+ V1LoadBalancerStatus status = networkingApi
+ .readNamespacedIngress(ingressName, namespace, null, null, null).getStatus().getLoadBalancer();
+
+ if (status == null) {
+ log.info("ingress : " + ingressName + " not ready yet (loadbalancer not yet present)");
+ return false;
+ }
+
+ List loadBalancerIngress = status.getIngress();
+ if (loadBalancerIngress == null) {
+ log.info("ingress : " + ingressName + " not ready yet (loadbalancer ingress not yet present)");
+ return false;
+ }
+
+ String ip = loadBalancerIngress.get(0).getIp();
+ if (ip == null) {
+ log.info("ingress : " + ingressName + " not ready yet");
+ return false;
+ }
+
+ log.info("ingress : " + ingressName + " ready with ip : " + ip);
+ return true;
+ }
+ catch (ApiException e) {
+ if (e.getCode() == HttpURLConnection.HTTP_NOT_FOUND) {
+ return false;
+ }
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
public void waitForDeploymentToBeDeleted(String deploymentName, String namespace) {
await().timeout(Duration.ofSeconds(90)).until(() -> {
try {
@@ -218,8 +282,125 @@ public class K8SUtils {
}
V1Deployment deployment = deployments.getItems().get(0);
Integer availableReplicas = deployment.getStatus().getAvailableReplicas();
- log.info("Available replicas for " + deploymentName + ": " + availableReplicas);
+ log.info("Available replicas for " + deploymentName + ": "
+ + (availableReplicas == null ? 0 : availableReplicas));
return availableReplicas != null && availableReplicas >= 1;
}
+ public void setUp(String namespace) throws Exception {
+
+ V1ServiceAccount serviceAccount = getConfigK8sClientItServiceAccount();
+ CheckedSupplier accountSupplier = () -> api
+ .readNamespacedServiceAccount(serviceAccount.getMetadata().getName(), namespace, null, null, null);
+ CheckedSupplier accountDefaulter = () -> api.createNamespacedServiceAccount(namespace,
+ serviceAccount, null, null, null);
+ notExistsHandler(accountSupplier, accountDefaulter);
+
+ V1RoleBinding roleBinding = getConfigK8sClientItRoleBinding();
+ notExistsHandler(() -> rbacApi.readNamespacedRoleBinding(roleBinding.getMetadata().getName(), namespace, null),
+ () -> rbacApi.createNamespacedRoleBinding(namespace, roleBinding, null, null, null));
+
+ V1Role role = getConfigK8sClientItRole();
+ notExistsHandler(() -> rbacApi.readNamespacedRole(role.getMetadata().getName(), namespace, null),
+ () -> rbacApi.createNamespacedRole(namespace, role, null, null, null));
+ }
+
+ public static V1ServiceAccount getConfigK8sClientItServiceAccount() throws Exception {
+ return (V1ServiceAccount) K8SUtils.readYamlFromClasspath("setup/service-account.yaml");
+ }
+
+ public static V1RoleBinding getConfigK8sClientItRoleBinding() throws Exception {
+ return (V1RoleBinding) K8SUtils.readYamlFromClasspath("setup/role-binding.yaml");
+ }
+
+ public static V1Role getConfigK8sClientItRole() throws Exception {
+ return (V1Role) K8SUtils.readYamlFromClasspath("setup/role.yaml");
+ }
+
+ public void deployWiremock(String namespace, boolean rootPath) throws Exception {
+ innerDeployWiremock(namespace, rootPath);
+
+ // Check to make sure the wiremock deployment is ready
+ waitForDeployment(WIREMOCK_DEPLOYMENT_NAME, namespace);
+
+ // Check to see if endpoint is ready
+ waitForEndpointReady(WIREMOCK_APP_NAME, namespace);
+ }
+
+ /**
+ * this removes wiremock related manifests, but keeps the image loaded in the
+ * container. As such can be used across tests.
+ */
+ public void cleanUpWiremock(String namespace) throws Exception {
+ appsApi.deleteCollectionNamespacedDeployment(namespace, null, null, null,
+ "metadata.name=" + WIREMOCK_DEPLOYMENT_NAME, null, null, null, null, null, null, null, null, null);
+
+ api.deleteNamespacedService(WIREMOCK_APP_NAME, namespace, null, null, null, null, null, null);
+ networkingApi.deleteNamespacedIngress("wiremock-ingress", namespace, null, null, null, null, null, null);
+ waitForDeploymentToBeDeleted(WIREMOCK_DEPLOYMENT_NAME, namespace);
+ }
+
+ /**
+ * this one should be called once all tests in a suite are done, as it removes the
+ * image from a running container.
+ */
+ public void removeWiremockImage() throws Exception {
+ V1Deployment wiremockDeployment = getWiremockDeployment();
+ String wiremockImage = wiremockDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage();
+ Commons.cleanUpDownloadedImage(wiremockImage);
+ }
+
+ private void innerDeployWiremock(String namespace, boolean rootPath) throws Exception {
+ appsApi.createNamespacedDeployment(namespace, getWiremockDeployment(), null, null, null);
+ api.createNamespacedService(namespace, getWiremockAppService(), null, null, null);
+
+ V1Ingress ingress;
+ if (rootPath) {
+ ingress = getWiremockRootPathIngress();
+ }
+ else {
+ ingress = getWiremockIngress();
+ }
+
+ networkingApi.createNamespacedIngress(namespace, ingress, null, null, null);
+ waitForIngress(ingress.getMetadata().getName(), namespace);
+ }
+
+ private static V1Ingress getWiremockIngress() throws Exception {
+ return (V1Ingress) K8SUtils.readYamlFromClasspath("wiremock/wiremock-ingress.yaml");
+ }
+
+ private static V1Ingress getWiremockRootPathIngress() throws Exception {
+ return (V1Ingress) K8SUtils.readYamlFromClasspath("wiremock/wiremock-root-path-ingress.yaml");
+ }
+
+ private static V1Service getWiremockAppService() throws Exception {
+ return (V1Service) K8SUtils.readYamlFromClasspath("wiremock/wiremock-service.yaml");
+ }
+
+ private static V1Deployment getWiremockDeployment() throws Exception {
+ return (V1Deployment) K8SUtils.readYamlFromClasspath("wiremock/wiremock-deployment.yaml");
+ }
+
+ private static void notExistsHandler(CheckedSupplier callee, CheckedSupplier defaulter) throws Exception {
+ try {
+ callee.get();
+ }
+ catch (Exception exception) {
+ if (exception instanceof ApiException apiException) {
+ if (apiException.getCode() == 404) {
+ defaulter.get();
+ return;
+ }
+ }
+ throw new RuntimeException(exception);
+ }
+ }
+
+ private interface CheckedSupplier {
+
+ T get() throws Exception;
+
+ }
+
}
diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/istio/role-binding.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/istio/role-binding.yaml
new file mode 100644
index 00000000..cd1bff4b
--- /dev/null
+++ b/spring-cloud-kubernetes-test-support/src/main/resources/istio/role-binding.yaml
@@ -0,0 +1,14 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ labels:
+ app: spring-cloud-kubernetes-core-k8s-client-it
+ name: istio-test-rb
+roleRef:
+ kind: Role
+ apiGroup: rbac.authorization.k8s.io
+ name: istio-test
+subjects:
+ - kind: ServiceAccount
+ name: spring-cloud-kubernetes-istio-serviceaccount
+ namespace: istio-test
diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/istio/role.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/istio/role.yaml
new file mode 100644
index 00000000..2765eee3
--- /dev/null
+++ b/spring-cloud-kubernetes-test-support/src/main/resources/istio/role.yaml
@@ -0,0 +1,9 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ namespace: istio-test
+ name: istio-test
+rules:
+ - apiGroups: [ "", "extensions", "apps" ]
+ resources: [ "configmaps", "pods", "services", "endpoints", "secrets" ]
+ verbs: [ "get", "list", "watch" ]
diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/istio/service-account.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/istio/service-account.yaml
new file mode 100644
index 00000000..2f4ac50c
--- /dev/null
+++ b/spring-cloud-kubernetes-test-support/src/main/resources/istio/service-account.yaml
@@ -0,0 +1,7 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ labels:
+ app: istio-integration-test
+ name: spring-cloud-kubernetes-istio-serviceaccount
+ namespace: istio-test
diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/setup/role-binding.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/setup/role-binding.yaml
new file mode 100644
index 00000000..43d1e2a9
--- /dev/null
+++ b/spring-cloud-kubernetes-test-support/src/main/resources/setup/role-binding.yaml
@@ -0,0 +1,14 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ labels:
+ app: spring-cloud-kubernetes-core-k8s-client-it
+ name: spring-cloud-kubernetes-core-k8s-client-it:view
+roleRef:
+ kind: Role
+ apiGroup: rbac.authorization.k8s.io
+ name: namespace-reader
+subjects:
+ - kind: ServiceAccount
+ name: spring-cloud-kubernetes-serviceaccount
+ namespace: default
diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/setup/role.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/setup/role.yaml
new file mode 100644
index 00000000..83ba8006
--- /dev/null
+++ b/spring-cloud-kubernetes-test-support/src/main/resources/setup/role.yaml
@@ -0,0 +1,9 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ namespace: default
+ name: namespace-reader
+rules:
+ - apiGroups: ["", "extensions", "apps"]
+ resources: ["configmaps", "pods", "services", "endpoints", "secrets"]
+ verbs: ["get", "list", "watch"]
diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/setup/service-account.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/setup/service-account.yaml
new file mode 100644
index 00000000..e847e1d7
--- /dev/null
+++ b/spring-cloud-kubernetes-test-support/src/main/resources/setup/service-account.yaml
@@ -0,0 +1,6 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ labels:
+ app: integration-test
+ name: spring-cloud-kubernetes-serviceaccount
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/wiremock-deployment.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-deployment.yaml
similarity index 89%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/wiremock-deployment.yaml
rename to spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-deployment.yaml
index 1dc89ac9..8ee19126 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/wiremock-deployment.yaml
+++ b/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-deployment.yaml
@@ -13,7 +13,8 @@ spec:
spec:
containers:
- name: servicea-wiremock
- image: rodolpheche/wiremock:2.27.2
+ image: wiremock/wiremock:2.32.0
+ args: ["--verbose"]
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/wiremock-ingress.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-ingress.yaml
similarity index 74%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/wiremock-ingress.yaml
rename to spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-ingress.yaml
index 61bb48a0..8786d59a 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-reactive-discovery-client-it/src/test/resources/wiremock-ingress.yaml
+++ b/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-ingress.yaml
@@ -3,13 +3,11 @@ kind: Ingress
metadata:
name: wiremock-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /wiremock(/|$)(.*)
+ - path: /wiremock/
pathType: Prefix
backend:
service:
@@ -17,4 +15,3 @@ spec:
port:
number: 8080
-
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/wiremock-ingress.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-root-path-ingress.yaml
similarity index 58%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/wiremock-ingress.yaml
rename to spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-root-path-ingress.yaml
index 546618fe..bd2d857a 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/resources/wiremock-ingress.yaml
+++ b/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-root-path-ingress.yaml
@@ -1,18 +1,17 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
- name: nginx-ingress
+ name: wiremock-ingress
namespace: default
- annotations:
- nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- - path: /wiremock(/|$)(.*)
+ - path: /
pathType: Prefix
backend:
service:
- name: config-watcher-wiremock
+ name: servicea-wiremock
port:
number: 8080
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock-service.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-service.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-loadbalancer/src/test/resources/wiremock-service.yaml
rename to spring-cloud-kubernetes-test-support/src/main/resources/wiremock/wiremock-service.yaml