drop microk8s tests + minor polishing (#923)

This commit is contained in:
erabii
2022-02-21 16:21:01 +02:00
committed by GitHub
parent 35ff8f7519
commit 2191ee068b
131 changed files with 2430 additions and 1811 deletions

View File

@@ -79,61 +79,6 @@ jobs:
command: |
cd spring-cloud-kubernetes-integration-tests
./run.sh
- run:
name: Launch Kubernetes with microk8s
command: |
sudo snap install microk8s --classic --channel=1.11/stable
# wait until a k8s node is ready
sleep 10
n=0
until [ $n -ge 10 ]
do
(/snap/bin/microk8s.kubectl get no | grep -z "Ready") && break
n=$[$n+1]
sleep 20
done
echo "Kubernetes cluster launched"
# Allow intra-pod communication
sudo iptables -P FORWARD ACCEPT
echo n |/snap/bin/microk8s.enable dns registry istio
# wait until the registry is up and running
sleep 10
n=0
until [ $n -ge 10 ]
do
(/snap/bin/microk8s.kubectl get pod --namespace=container-registry | grep -z "Running") && break
n=$[$n+1]
sleep 10
done
echo "Kubernetes Container Registry enabled"
# wait until istio is up and running
sleep 10
n=0
until [ $n -ge 10 ]
do
(/snap/bin/microk8s.kubectl get pod -l istio=sidecar-injector --namespace=istio-system | grep -z "Running") && break
n=$[$n+1]
sleep 10
done
echo "Istio enabled"
# create the namespace where the istio integration test will run
/snap/bin/microk8s.kubectl create -f .circleci/istio-test-namespace.yml
- run:
name: Run integration tests
command: |
/snap/bin/microk8s.kubectl config view --raw > /tmp/kubeconfig
export KUBECONFIG=/tmp/kubeconfig
cd spring-cloud-kubernetes-integration-tests
../mvnw -Djkube.docker.host='unix:///var/snap/microk8s/current/docker.sock' clean package verify -Pk8s,it,spring
- run:
name: "Aggregate test results"
when: always

1
.gitignore vendored
View File

@@ -83,3 +83,4 @@ crashlytics-build.properties
.attach_pid*
.vscode/
.java-version
*Dockerfile

View File

@@ -83,6 +83,7 @@
</maven-checkstyle-plugin.failsOnViolation>
<maven-checkstyle-plugin.includeTestSourceDirectory>true
</maven-checkstyle-plugin.includeTestSourceDirectory>
<excludeITTests>**/*IT.java</excludeITTests>
</properties>
<modules>
@@ -358,13 +359,13 @@
<configuration>
<parallel>all</parallel>
<reuseForks>false</reuseForks>
<!-- Sets the VM argument line used when unit tests are run. -->
<argLine>${surefireArgLine}</argLine>
<!-- workaround for https://issues.apache.org/jira/projects/SUREFIRE/issues/SUREFIRE-1633?filter=allopenissues -->
<!-- we run tests with mvn -DtestsToRun=.... in the pipeline-->
<includes>
<include>${testsToRun}</include>
</includes>
<!-- Sets the VM argument line used when unit tests are run. -->
<argLine>${surefireArgLine}</argLine>
<excludes>
<exclude>${excludeITTests}</exclude>
</excludes>

View File

@@ -1,126 +0,0 @@
# Purpose
Explain how integration tests can be run against any k8s cluster.
One way of running such a kubernetes cluster locally which is leveraged by our CI setup is [microk8s](https://microk8s.io/)
The Kubernetes resources necessary to get the test application
onto the cluster are created using the [Fabric8 Maven Plugin](https://maven.fabric8.io/) and the
lifecycle of the test applications is controlled by [Arquillian Cube](http://arquillian.org/arquillian-cube/)
# Basics
With JKube and Arquillian Cube setup for our project we need to configure the following things in order to properly get
our test applications onto our cluster of choice:
* The `KUBECONFIG` environment variable needs to be set to the location of the Kubernetes configuration file
we will use to access our cluster (this can be skipped if this file is already present in the standard locations that kubectl assumes)
* The `jkube.docker.host` system property needs to be set to the URL where the docker daemon we will use to build images is listening
This can be skipped when we use the default unix socket on a Linux machine
* The Docker image registry were out built images will be stored needs to be set using the `image.registry` environment variable
# Instructions
Here we will describe the steps that are needed to setup microk8s and the maven command we will use to run the integration
tests against that microk8s cluster
## Running tests with microk8s
### Install microk8s
```bash
sudo snap install microk8s --classic --channel=1.11/stable
sleep 10
echo n | microk8s.enable dns registry istio
```
Ensure everything is running by inspecting the output of:
```bash
microk8s.kubectl get all --all-namespaces
```
It should look something like:
```
NAMESPACE NAME READY STATUS RESTARTS AGE
container-registry pod/registry-6bc95dfd76-274lc 1/1 Running 0 40s
kube-system pod/hostpath-provisioner-9979c7f64-f96tw 1/1 Running 0 41s
kube-system pod/kube-dns-864b8bdc77-68kmn 2/3 Running 0 41s
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
container-registry service/registry NodePort 10.152.183.175 <none> 5000:32000/TCP 50s
default service/kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 1m
kube-system service/kube-dns ClusterIP 10.152.183.10 <none> 53/UDP,53/TCP 56s
NAMESPACE NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
container-registry deployment.apps/registry 1 1 1 1 50s
kube-system deployment.apps/hostpath-provisioner 1 1 1 1 51s
kube-system deployment.apps/kube-dns 1 1 1 0 56s
NAMESPACE NAME DESIRED CURRENT READY AGE
container-registry replicaset.apps/registry-6bc95dfd76 1 1 1 41s
kube-system replicaset.apps/hostpath-provisioner-9979c7f64 1 1 1 41s
kube-system replicaset.apps/kube-dns-864b8bdc77 1 1 0 41s
```
Export the kube config file that will be used to access this cluster
```bash
microk8s.kubectl config view --raw > /tmp/kubeconfig
```
For the istio tests to work, we need a namespace that is properly configured for Istio injection.
Such a namespace called `istio-test` can easily be created using:
```bash
microk8s.kubectl create -f .circleci/istio-test-namespace.yml
```
### Launch tests
```bash
cd spring-cloud-kubernetes-integration-tests
KUBECONFIG=/tmp/kubeconfig mvn -Djkube.docker.host='unix:///var/snap/microk8s/current/docker.sock' clean package verify -Pk8s,it,spring
```
The command above will for each test project:
* Build the ubjerjar
* Build a docker image based on that uberjar
* Launch the Arquillian Cube tests which will
- Deploy the application to the cluster
- Launch the test code
- Undeploy the application
## Running tests with Docker Desktop
[Docker Desktop for Mac](https://docs.docker.com/docker-for-mac/) and [Docker Desktop for Windows](https://docs.docker.com/docker-for-windows/)
provide a Kubernetes server runs within a Docker container on your local system. This is similar to `microk8s` but is only currently available on Mac or Windows.
### Configure Docker Desktop
* Ensure you are running the Edge release of Docker Desktop
** For Mac `brew cask install docker-edge`
** For Windows `choco install docker-desktop --pre`
* Increase default resources as the defaults are not sufficient. Allocate 8GB of Ram
![Docker Resources](https://istio.io/docs/setup/kubernetes/platform-setup/docker/dockerprefs.png)
* [Enable Kubernetes cluster](https://docs.docker.com/docker-for-mac/#kubernetes)
* Run a local insecure docker registry
** `docker run -d -p 5000:5000 --restart=always --name registry registry:2`
* [Configure the Docker daemon to trust the local registry](https://docs.docker.com/docker-for-mac/#daemon)
* Export the docker config `kubectl config view --raw > /tmp/kubeconfig`
* Run the tests `KUBECONFIG=/tmp/kubeconfig mvn -Djkube.docker.host='unix:///var/snap/microk8s/current/docker.sock' clean package verify -Pk8s,it,spring`
## Launching one of the applications manually
Each of the test modules can also be launched manually. This can be very useful for debugging purposes.
For example to launch the `simple-core` application
```bash
cd spring-cloud-kubernetes-integration-tests/simple-core
KUBECONFIG=/tmp/kubeconfig mvn -Djkube.docker.host='unix:///var/snap/microk8s/current/docker.sock' clean package verify -Pk8s,it,spring
```
When it's time to take down the application, simply execute:
```bash
KUBECONFIG=/tmp/kubeconfig mvn k8s:undeploy -Pk8s
```

View File

@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>discovery-parent</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>discovery-client</artifactId>
<name>Spring Cloud Kubernetes :: Integration Tests :: Discovery Client</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-fabric8-discovery</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,8 +0,0 @@
management:
endpoint:
health:
show-details: always
endpoints:
web:
exposure:
include: "*"

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>discovery-parent</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>discovery-service-a</artifactId>
<name>Spring Cloud Kubernetes :: Integration Tests :: Discovery Service A</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>discovery-parent</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>discovery-service-b</artifactId>
<name>Spring Cloud Kubernetes :: Integration Tests :: Discovery Service B</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>discovery-parent</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>kubernetes-client-discovery</artifactId>
<name>Spring Cloud Kubernetes :: Integration Tests :: Kubernetes Client Discovery</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-client-discovery</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -1,51 +0,0 @@
/*
* Copyright 2013-2019 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.it;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class DiscoveryClientApplication {
@Autowired
private DiscoveryClient discoveryClient;
public static void main(String[] args) {
SpringApplication.run(DiscoveryClientApplication.class, args);
}
@GetMapping("/services")
public List<String> services() {
return this.discoveryClient.getServices();
}
@GetMapping("/services/{service}/instances")
public List<ServiceInstance> instances(@PathVariable("service") String service) {
return this.discoveryClient.getInstances(service);
}
}

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-integration-tests</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<name>Spring Cloud Kubernetes :: Integration Tests :: Discovery Parent</name>
<artifactId>discovery-parent</artifactId>
<packaging>pom</packaging>
<modules>
<module>discovery-service-a</module>
<module>discovery-service-b</module>
<module>discovery-client</module>
<module>kubernetes-client-discovery</module>
<module>tests</module>
</modules>
</project>

View File

@@ -1,128 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>discovery-parent</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>tests</artifactId>
<name>Spring Cloud Kubernetes :: Integration Tests :: Discovery Tests</name>
<dependencies>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>logging-interceptor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.arquillian.cube</groupId>
<artifactId>arquillian-cube-kubernetes</artifactId>
<version>${arquillian-cube.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>undertow-core</artifactId>
<groupId>io.undertow</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-standalone</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- This module only contains test code so we skip the spring boot plugin and FMP -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jkube</groupId>
<artifactId>kubernetes-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>it</id>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.jkube</groupId>
<artifactId>kubernetes-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
<profile>aggregate</profile>
</configuration>
<!--
We add the dependencies to the discovery modules that need to be deployed for the tests
to run.
This is done in order to make FMP pick up the generated Kubernetes
resources file of each module and create an "uber" resources file containing
resources for both modules (which is what the aggregate profile above does)
-->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>discovery-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>discovery-service-a</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>discovery-service-b</artifactId>
<version>${project.version}</version>
</dependency>
<!-- fmp seems to fail without this... -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@@ -1,65 +0,0 @@
/*
* Copyright 2013-2019 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.it;
import org.arquillian.cube.kubernetes.impl.requirement.RequiresKubernetes;
import org.hamcrest.core.StringContains;
import org.jboss.arquillian.junit.Arquillian;
import org.junit.Test;
import org.junit.runner.RunWith;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.core.Is.is;
@RequiresKubernetes
@RunWith(Arquillian.class)
public class ServicesIT {
private static final String HOST = System.getProperty("service.host");
private static final Integer PORT = Integer.valueOf(System.getProperty("service.port"));
private static final String PROTOCOL = "true".equalsIgnoreCase(System.getProperty("service.secure")) ? "https"
: "http";
@Test
public void testServicesEndpoint() {
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("services").then().statusCode(200)
.body(new StringContains(false, "service-a") {
@Override
protected boolean evalSubstringOf(String s) {
return s.contains("service-a") && s.contains("service-b");
}
});
}
@Test
public void testInstancesEndpoint() {
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("services/discovery-service-a/instances")
.then().statusCode(200).body("instanceId", hasSize(1))
.body("serviceId", hasItems("discovery-service-a"));
}
@Test
public void testHealthEndpoint() {
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).contentType("application/json")
.get("actuator/health").then().statusCode(200).body("components.discoveryComposite.status", is("UP"));
}
}

View File

@@ -1,10 +0,0 @@
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://jboss.org/schema/arquillian"
xsi:schemaLocation="http://jboss.org/schema/arquillian https://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<extension qualifier="kubernetes">
<property name="namespace.use.existing">default</property>
<property name="env.config.url">file:./target/classes/META-INF/jkube/kubernetes.yml</property>
</extension>
</arquillian>

View File

@@ -1,64 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-integration-tests</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<name>Spring Cloud Kubernetes :: Integration Tests :: Istio</name>
<artifactId>istio</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-fabric8-istio</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.arquillian.cube</groupId>
<artifactId>arquillian-cube-kubernetes</artifactId>
<version>${arquillian-cube.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>undertow-core</artifactId>
<groupId>io.undertow</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-standalone</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,10 +0,0 @@
# We need this fragment in order for the kubernetes client to talk to
# the Kubernetes API without caring about proper certificates
spec:
template:
spec:
containers:
- env:
- name: KUBERNETES_TRUST_CERTIFICATES
value: true

View File

@@ -1,15 +0,0 @@
# we are using a JKube fragment to ensure that NodePort is used correctly
kind: Service
apiVersion: v1
metadata:
name: ${project.artifactId}
labels:
app: ${project.artifactId}
spec:
selector:
app: ${project.artifactId}
ports:
- protocol: TCP
port: 8080
nodePort: ${nodeport.value}
type: NodePort

View File

@@ -1,45 +0,0 @@
/*
* Copyright 2013-2019 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.it;
import org.arquillian.cube.kubernetes.impl.requirement.RequiresKubernetes;
import org.hamcrest.core.StringContains;
import org.jboss.arquillian.junit.Arquillian;
import org.junit.Test;
import org.junit.runner.RunWith;
import static io.restassured.RestAssured.given;
@RequiresKubernetes
@RunWith(Arquillian.class)
public class ProfilesIT {
private static final String HOST = System.getProperty("service.host");
private static final Integer PORT = Integer
.valueOf(System.getProperty("service.port"));
private static final String PROTOCOL = "true"
.equalsIgnoreCase(System.getProperty("service.secure")) ? "https" : "http";
@Test
public void testProfileEndpoint() {
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("profiles")
.then().statusCode(200).body(new StringContains("istio"));
}
}

View File

@@ -1,10 +0,0 @@
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://jboss.org/schema/arquillian"
xsi:schemaLocation="http://jboss.org/schema/arquillian https://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<extension qualifier="kubernetes">
<property name="namespace.use.existing">istio-test</property>
<property name="env.config.url">file:./target/classes/META-INF/jkube/kubernetes.yml</property>
</extension>
</arquillian>

View File

@@ -1,46 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-kubernetes-integration-tests</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<name>Spring Cloud Kubernetes :: Integration Tests :: Load Balancer</name>
<artifactId>load-balancer</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-server-mock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.specto</groupId>
<artifactId>hoverfly-java-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.specto</groupId>
<artifactId>hoverfly-java</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,47 +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.fabric8.loadbalancer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@RestController
public class SimpleLoadBalancerApp {
public static void main(String[] args) {
SpringApplication.run(SimpleLoadBalancerApp.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplateBuilder().build();
}
@GetMapping("/greeting")
public String greeting() {
return "greeting";
}
}

View File

@@ -31,3 +31,38 @@ items:
- 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

View File

@@ -111,23 +111,6 @@
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-bom</artifactId>
<version>${arquillian.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttptests.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>logging-interceptor</artifactId>
<version>${okhttptests.version}</version>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-core</artifactId>
@@ -145,17 +128,18 @@
</dependencyManagement>
<modules>
<module>simple-core</module>
<module>simple-configmap</module>
<!-- <module>istio</module>-->
<module>discovery</module>
<module>load-balancer</module>
<!-- Add this module back once we convert everything over to kind -->
<!-- <module>spring-cloud-kubernetes-client-config-it</module>-->
<!-- <module>spring-cloud-kubernetes-client-loadbalancer-it</module>-->
<!-- <module>spring-cloud-kubernetes-client-reactive-discovery-client-it</module>-->
<!-- <module>spring-cloud-kubernetes-configuration-watcher-it</module>-->
<!-- <module>spring-cloud-kubernetes-configuration-watcher-it</module>-->
<!-- <module>spring-cloud-kubernetes-core-k8s-client-it</module>-->
<module>spring-cloud-kubernetes-fabric8-client-simple-core</module>
<module>spring-cloud-kubernetes-fabric8-client-configmap</module>
<module>spring-cloud-kubernetes-fabric8-istio-it</module>
<module>spring-cloud-kubernetes-fabric8-client-discovery</module>
<module>spring-cloud-kubernetes-fabric8-client-loadbalancer</module>
<module>spring-cloud-kubernetes-discovery-client-it</module>
<module>spring-cloud-kubernetes-reactive-discovery-client-it</module>
<module>spring-cloud-kubernetes-client-config-it</module>
<module>spring-cloud-kubernetes-client-loadbalancer-it</module>
<module>spring-cloud-kubernetes-client-reactive-discovery-client-it</module>
<module>spring-cloud-kubernetes-configuration-watcher-it</module>
<module>spring-cloud-kubernetes-core-k8s-client-it</module>
</modules>
</project>

View File

@@ -12,17 +12,13 @@ BIN_DIR="$(mktemp -d)"
# kind binary will be here
KIND="${BIN_DIR}/kind"
ISTIOCTL="${BIN_DIR}/istio-1.6.2/bin/istioctl"
ISTIO="${BIN_DIR}/istio"
CURRENT_DIR="$(pwd)"
MVN="${CURRENT_DIR}/../mvnw"
MVN_VERSION=$($MVN -q \
-Dexec.executable=echo \
-Dexec.args='${project.version}' \
--non-recursive \
exec:exec)
PROJECT_VERSION=$($MVN help:evaluate -Dexpression=project.version -q -DforceStdout)
ALL_INTEGRATION_PROJECTS=(
"spring-cloud-kubernetes-core-k8s-client-it"
@@ -30,8 +26,13 @@ ALL_INTEGRATION_PROJECTS=(
"spring-cloud-kubernetes-configuration-watcher-it"
"spring-cloud-kubernetes-client-loadbalancer-it"
"spring-cloud-kubernetes-client-reactive-discovery-client-it"
"spring-cloud-kubernetes-discoverclient-it"
"spring-cloud-kubernetes-reactive-discoveryclient-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[@]}})
@@ -44,9 +45,10 @@ DEFAULT_PULLING_IMAGES=(
)
PULLING_IMAGES=(${PULLING_IMAGES:-${DEFAULT_PULLING_IMAGES[@]}})
LOADING_IMAGES=(${LOADING_IMAGES:-${DEFAULT_PULLING_IMAGES[@]}} "docker.io/springcloud/spring-cloud-kubernetes-configuration-watcher:${MVN_VERSION}"
"docker.io/springcloud/spring-cloud-kubernetes-discoveryserver:${MVN_VERSION}")
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}"
@@ -82,6 +84,40 @@ install_kind_release() {
chmod +x "${KIND}"
}
# util to install a released istio version into ${BIN_DIR}
install_istio_release() {
ISTIO_VERSION="1.12.0"
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
@@ -95,6 +131,10 @@ main() {
# set KUBECONFIG to point to the cluster
kubectl cluster-info --context kind-kind
# istio
install_istio_release
enable_istio
#setup nginx ingress
# pulling necessary images for setting up the integration test environment
for i in "${PULLING_IMAGES[@]}"; do
@@ -108,8 +148,8 @@ main() {
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
@@ -128,7 +168,7 @@ main() {
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 $PROJECTS"
echo "${PROJECTS[@]}"
run_tests "${PROJECTS[@]}"
fi
@@ -137,13 +177,17 @@ main() {
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:${MVN_VERSION} -Dspring-boot.build-image.builder=paketobuildpacks/builder
"${KIND}" load docker-image docker.io/springcloud/$p:${MVN_VERSION}
${MVN} clean install -P it
-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
}

View File

@@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-integration-tests</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<name>Spring Cloud Kubernetes :: Integration Tests :: Simple Configmap</name>
<artifactId>simple-configmap</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>logging-interceptor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.arquillian.cube</groupId>
<artifactId>arquillian-cube-kubernetes</artifactId>
<version>${arquillian-cube.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>undertow-core</artifactId>
<groupId>io.undertow</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-standalone</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,57 +0,0 @@
/*
* Copyright 2013-2019 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.it;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
@EnableConfigurationProperties(DummyConfig.class)
public class SimpleConfigMapApplication {
@Autowired
private DummyConfig dummyConfig;
public static void main(String[] args) {
SpringApplication.run(SimpleConfigMapApplication.class, args);
}
@GetMapping("/greeting")
public Greeting greeting() {
return new Greeting(this.dummyConfig.getMessage());
}
public static class Greeting {
private final String message;
public Greeting(String message) {
this.message = message;
}
public String getMessage() {
return this.message;
}
}
}

View File

@@ -1,10 +0,0 @@
# We need this fragment in order for the kubernetes client to talk to
# the Kubernetes API without caring about proper certificates
spec:
template:
spec:
containers:
- env:
- name: KUBERNETES_TRUST_CERTIFICATES
value: true

View File

@@ -1,7 +0,0 @@
# We are using a JKube fragment to ensure that NodePort is used correctly
spec:
ports:
- protocol: TCP
port: 8080
nodePort: ${nodeport.value}
type: NodePort

View File

@@ -1,12 +0,0 @@
server:
port: 8080
# we enable some of the management endpoints to make it possible to restart the application
management:
endpoint:
restart:
enabled: true
health:
enabled: true
info:
enabled: true

View File

@@ -1,14 +0,0 @@
spring:
application:
name: sck-example
cloud:
kubernetes:
# enable reloading of the application when on the property sources has changed
reload:
enabled: true
mode: polling
period: 5000
config:
sources:
- name: ${spring.application.name}
namespace: default

View File

@@ -1,65 +0,0 @@
/*
* Copyright 2013-2019 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.it;
import org.arquillian.cube.kubernetes.annotations.KubernetesResource;
import org.arquillian.cube.kubernetes.impl.requirement.RequiresKubernetes;
import org.jboss.arquillian.junit.Arquillian;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import static io.restassured.RestAssured.given;
import static org.hamcrest.core.Is.is;
@RequiresKubernetes
@RunWith(Arquillian.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class GreetingIT {
private static final String HOST = System.getProperty("service.host");
private static final Integer PORT = Integer.valueOf(System.getProperty("service.port"));
private static final String PROTOCOL = "true".equalsIgnoreCase(System.getProperty("service.secure")) ? "https"
: "http";
@Test
public void firstTestThatTheDefaultMessageIsReturned() {
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting").then().statusCode(200)
.body("message", is("This is a dummy message"));
}
@Test
@KubernetesResource("classpath:config-map.yml")
public void thenApplyAConfigMapAndEnsureThatTheMessageIsUpdated() {
waitForApplicationToReload();
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting").then().statusCode(200)
.body("message", is("Hello from Spring Cloud Kubernetes!"));
}
private void waitForApplicationToReload() {
try {
Thread.sleep(15000);
}
catch (InterruptedException e) {
}
}
}

View File

@@ -1,10 +0,0 @@
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://jboss.org/schema/arquillian"
xsi:schemaLocation="http://jboss.org/schema/arquillian https://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<extension qualifier="kubernetes">
<property name="namespace.use.existing">default</property>
<property name="env.config.url">file:./target/classes/META-INF/jkube/kubernetes.yml</property>
</extension>
</arquillian>

View File

@@ -1,6 +0,0 @@
spring:
application:
name: sck-example
cloud:
kubernetes:
enabled: false

View File

@@ -1,8 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: sck-example
data:
application.properties: |-
config.message=Hello from Spring Cloud Kubernetes!
another.property=value

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="org.hibernate.validator"
level="info"/> <!-- Validator prints a lot of debug messages during integration tests -->
</configuration>

View File

@@ -1,10 +0,0 @@
# We need this fragment in order for the kubernetes client to talk to
# the Kubernetes API without caring about proper certificates
spec:
template:
spec:
containers:
- env:
- name: KUBERNETES_TRUST_CERTIFICATES
value: true

View File

@@ -1,15 +0,0 @@
# we are using a JKube fragment to ensure that NodePort is used correctly
kind: Service
apiVersion: v1
metadata:
name: ${project.artifactId}
labels:
app: ${project.artifactId}
spec:
selector:
app: ${project.artifactId}
ports:
- protocol: TCP
port: 8080
nodePort: ${nodeport.value}
type: NodePort

View File

@@ -1,50 +0,0 @@
/*
* Copyright 2013-2019 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.it;
import org.arquillian.cube.kubernetes.impl.requirement.RequiresKubernetes;
import org.jboss.arquillian.junit.Arquillian;
import org.junit.Test;
import org.junit.runner.RunWith;
import static io.restassured.RestAssured.given;
import static org.hamcrest.core.Is.is;
@RequiresKubernetes
@RunWith(Arquillian.class)
public class GreetingAndHealthIT {
private static final String HOST = System.getProperty("service.host");
private static final Integer PORT = Integer.valueOf(System.getProperty("service.port"));
private static final String PROTOCOL = "true".equalsIgnoreCase(System.getProperty("service.secure")) ? "https"
: "http";
@Test
public void testGreetingEndpoint() {
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting").then().statusCode(200)
.body("message", is("Hello from k8s"));
}
@Test
public void testHealthEndpoint() {
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).contentType("application/json")
.get("actuator/health").then().statusCode(200).body("components.kubernetes.details.inside", is(true));
}
}

View File

@@ -1,10 +0,0 @@
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://jboss.org/schema/arquillian"
xsi:schemaLocation="http://jboss.org/schema/arquillian https://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<extension qualifier="kubernetes">
<property name="namespace.use.existing">default</property>
<property name="env.config.url">file:./target/classes/META-INF/jkube/kubernetes.yml</property>
</extension>
</arquillian>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="org.hibernate.validator"
level="info"/> <!-- Validator prints a lot of debug messages during integration tests -->
</configuration>

View File

@@ -16,7 +16,6 @@
package org.springframework.cloud.kubernetes.client.config.it;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -31,8 +30,11 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
public class KubernetesConfigClientApplicationIt {
@Autowired
private MyConfigurationProperties configurationProperties;
private final MyConfigurationProperties configurationProperties;
public KubernetesConfigClientApplicationIt(MyConfigurationProperties configurationProperties) {
this.configurationProperties = configurationProperties;
}
@GetMapping("/myProperty")
public String myProperty() {
@@ -50,7 +52,7 @@ public class KubernetesConfigClientApplicationIt {
@Configuration
@EnableConfigurationProperties(MyConfigurationProperties.class)
class MyConfig {
static class MyConfig {
}

View File

@@ -31,9 +31,9 @@ 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.After;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.AfterEach;
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;
@@ -67,6 +67,7 @@ public class ConfigMapAndSecretIT {
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;
@@ -77,7 +78,7 @@ public class ConfigMapAndSecretIT {
private static K8SUtils k8SUtils;
@BeforeClass
@BeforeAll
public static void setup() throws Exception {
client = createApiClient();
api = new CoreV1Api();
@@ -86,7 +87,7 @@ public class ConfigMapAndSecretIT {
k8SUtils = new K8SUtils(api, appsApi);
}
@After
@AfterEach
public 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);
@@ -103,21 +104,18 @@ public class ConfigMapAndSecretIT {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
if (clientHttpResponse.getRawStatusCode() == 503) {
return false;
}
return true;
return clientHttpResponse.getRawStatusCode() != 503;
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
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))
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);
@@ -130,7 +128,7 @@ public class ConfigMapAndSecretIT {
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))
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");
@@ -140,7 +138,7 @@ public class ConfigMapAndSecretIT {
secretData.replace("my.config.mySecret", "p455w1rd".getBytes());
secret.setData(secretData);
api.replaceNamespacedSecret(APP_NAME, NAMESPACE, secret, null, null, null);
await().timeout(Duration.ofSeconds(60))
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");
@@ -184,7 +182,7 @@ public class ConfigMapAndSecretIT {
}
private static V1Deployment getConfigK8sClientItDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils
V1Deployment deployment = (V1Deployment) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-deployment.yaml");
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ getPomVersion();
@@ -193,7 +191,7 @@ public class ConfigMapAndSecretIT {
}
private static V1Deployment getConfigK8sClientItPollingDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils
V1Deployment deployment = (V1Deployment) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-polling-deployment.yaml");
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ getPomVersion();
@@ -202,27 +200,19 @@ public class ConfigMapAndSecretIT {
}
private static V1Service getConfigK8sClientItService() throws Exception {
V1Service service = (V1Service) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-service.yaml");
return service;
return (V1Service) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-service.yaml");
}
private static V1Ingress getConfigK8sClientItIngress() throws Exception {
V1Ingress ingress = (V1Ingress) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-ingress.yaml");
return ingress;
return (V1Ingress) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-ingress.yaml");
}
private static V1ConfigMap getConfigK8sClientItConfigMap() throws Exception {
V1ConfigMap configmap = (V1ConfigMap) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-configmap.yaml");
return configmap;
return (V1ConfigMap) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-configmap.yaml");
}
private static V1Secret getConfigK8sClientItCSecret() throws Exception {
V1Secret secret = (V1Secret) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-secret.yaml");
return secret;
return (V1Secret) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-secret.yaml");
}
}

View File

@@ -19,7 +19,6 @@ package org.springframework.cloud.kubernetes.client.loadbalancer.it;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
@@ -38,8 +37,11 @@ import org.springframework.web.client.RestTemplate;
@RestController
public class KubernetesClientLoadBalancerApplicationIt {
@Autowired
DiscoveryClient discoveryClient;
private final DiscoveryClient discoveryClient;
public KubernetesClientLoadBalancerApplicationIt(DiscoveryClient discoveryClien) {
this.discoveryClient = discoveryClien;
}
public static void main(String[] args) {
SpringApplication.run(KubernetesClientLoadBalancerApplicationIt.class, args);

View File

@@ -31,9 +31,9 @@ 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.After;
import org.junit.Before;
import org.junit.Test;
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;
@@ -73,7 +73,7 @@ public class LoadBalancerIT {
private K8SUtils k8SUtils;
@Before
@BeforeEach
public void setup() throws Exception {
this.client = createApiClient();
this.api = new CoreV1Api();
@@ -122,7 +122,7 @@ public class LoadBalancerIT {
networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null);
}
private void testLoadBalancer() throws Exception {
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();
@@ -130,14 +130,11 @@ public class LoadBalancerIT {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
if (clientHttpResponse.getRawStatusCode() == 503) {
return false;
}
return true;
return clientHttpResponse.getRawStatusCode() != 503;
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
public void handleError(ClientHttpResponse clientHttpResponse) {
}
});
@@ -152,7 +149,7 @@ public class LoadBalancerIT {
}
@After
@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);
@@ -174,14 +171,8 @@ public class LoadBalancerIT {
networkingApi.createNamespacedIngress(NAMESPACE, getLoadbalancerItIngress(), null, null, null);
}
private V1Service getLoadbalancerItService() throws Exception {
V1Service service = (V1Service) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-client-loadbalancer-it-service.yaml");
return service;
}
private V1Deployment getLoadbalancerServiceItDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils
V1Deployment deployment = (V1Deployment) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-client-loadbalancer-service-it-deployment.yaml");
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ getPomVersion();
@@ -190,7 +181,7 @@ public class LoadBalancerIT {
}
private V1Deployment getLoadbalancerPodItDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils
V1Deployment deployment = (V1Deployment) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-client-loadbalancer-service-it-deployment.yaml");
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ getPomVersion();
@@ -198,31 +189,32 @@ public class LoadBalancerIT {
return deployment;
}
private V1Ingress getLoadbalancerItIngress() throws Exception {
V1Ingress ingress = (V1Ingress) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-client-loadbalancer-it-ingress.yaml");
return ingress;
}
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");
}
private V1Service getLoadbalancerItService() throws Exception {
return (V1Service) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-client-loadbalancer-it-service.yaml");
}
private V1Ingress getWiremockIngress() throws Exception {
V1Ingress ingress = (V1Ingress) k8SUtils.readYamlFromClasspath("wiremock-ingress.yaml");
return ingress;
return (V1Ingress) K8SUtils.readYamlFromClasspath("wiremock-ingress.yaml");
}
private V1Service getWiremockAppService() throws Exception {
V1Service service = (V1Service) k8SUtils.readYamlFromClasspath("wiremock-service.yaml");
return service;
return (V1Service) K8SUtils.readYamlFromClasspath("wiremock-service.yaml");
}
private V1Deployment getWireockDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils.readYamlFromClasspath("wiremock-deployment.yaml");
return deployment;
return (V1Deployment) K8SUtils.readYamlFromClasspath("wiremock-deployment.yaml");
}
}

View File

@@ -16,9 +16,10 @@
package org.springframework.cloud.kubernetes.client.reactive.discovery.it;
import java.util.stream.Collectors;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.kubernetes.client.discovery.reactive.KubernetesInformerReactiveDiscoveryClient;
@@ -32,8 +33,12 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
public class KubernetesClientReactiveDiscoveryClientApplicationIt {
@Autowired
KubernetesInformerReactiveDiscoveryClient discoveryClient;
private final KubernetesInformerReactiveDiscoveryClient discoveryClient;
public KubernetesClientReactiveDiscoveryClientApplicationIt(
KubernetesInformerReactiveDiscoveryClient discoveryClient) {
this.discoveryClient = discoveryClient;
}
public static void main(String[] args) {
SpringApplication.run(KubernetesClientReactiveDiscoveryClientApplicationIt.class, args);
@@ -41,12 +46,7 @@ public class KubernetesClientReactiveDiscoveryClientApplicationIt {
@GetMapping("/services")
public Mono<String> services() {
return discoveryClient.getServices().reduce("", (a, b) -> {
if (a.isEmpty()) {
return b;
}
return a + "," + b;
});
return discoveryClient.getServices().collect(Collectors.joining(","));
}
}

View File

@@ -31,9 +31,9 @@ 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.After;
import org.junit.Before;
import org.junit.Test;
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;
@@ -73,7 +73,7 @@ public class ReactiveDiscoveryClientIT {
private K8SUtils k8SUtils;
@Before
@BeforeEach
public void setup() throws Exception {
this.client = createApiClient();
this.api = new CoreV1Api();
@@ -91,6 +91,16 @@ public class ReactiveDiscoveryClientIT {
}
@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 {
@@ -106,6 +116,25 @@ public class ReactiveDiscoveryClientIT {
}
}
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<String, Object> health = rest.getForObject("http://localhost:80/reactive-discovery-it/actuator/health",
Map.class);
Map<String, Object> components = (Map<String, Object>) health.get("components");
assertThat(components.containsKey("reactiveDiscoveryClients")).isTrue();
Map<String, Object> discoveryComposite = (Map<String, Object>) 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,
@@ -121,7 +150,7 @@ public class ReactiveDiscoveryClientIT {
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))
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);
@@ -136,63 +165,25 @@ public class ReactiveDiscoveryClientIT {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
if (clientHttpResponse.getRawStatusCode() == 503) {
return false;
}
return true;
return clientHttpResponse.getRawStatusCode() != 503;
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
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/reactive-discovery-it/actuator/health", String.class)
.getStatusCode().is2xxSuccessful());
Map<String, Object> health = rest.getForObject("http://localhost:80/reactive-discovery-it/actuator/health",
Map.class);
Map<String, Object> components = (Map) health.get("components");
assertThat(components.containsKey("reactiveDiscoveryClients")).isTrue();
Map<String, Object> discoveryComposite = (Map) components.get("discoveryComposite");
assertThat(discoveryComposite.get("status")).isEqualTo("UP");
}
@After
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);
}
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 V1Service getReactiveDiscoveryService() throws Exception {
V1Service service = (V1Service) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-client-reactive-discovery-it-service.yaml");
return service;
}
private V1Deployment getReactiveDiscoveryItDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils
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();
@@ -200,31 +191,32 @@ public class ReactiveDiscoveryClientIT {
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 {
V1Ingress ingress = (V1Ingress) k8SUtils
return (V1Ingress) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-client-reactive-discovery-it-ingress.yaml");
return ingress;
}
private void deployWiremock() throws Exception {
appsApi.createNamespacedDeployment(NAMESPACE, getWireockDeployment(), null, null, null);
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 {
V1Ingress ingress = (V1Ingress) k8SUtils.readYamlFromClasspath("wiremock-ingress.yaml");
return ingress;
return (V1Ingress) K8SUtils.readYamlFromClasspath("wiremock-ingress.yaml");
}
private V1Service getWiremockAppService() throws Exception {
V1Service service = (V1Service) k8SUtils.readYamlFromClasspath("wiremock-service.yaml");
return service;
return (V1Service) K8SUtils.readYamlFromClasspath("wiremock-service.yaml");
}
private V1Deployment getWireockDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils.readYamlFromClasspath("wiremock-deployment.yaml");
return deployment;
private V1Deployment getWiremockDeployment() throws Exception {
return (V1Deployment) K8SUtils.readYamlFromClasspath("wiremock-deployment.yaml");
}
}

View File

@@ -29,11 +29,9 @@ 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.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
@@ -51,7 +49,6 @@ import static org.springframework.cloud.kubernetes.integration.tests.commons.K8S
/**
* @author Ryan Baxter
*/
@RunWith(MockitoJUnitRunner.class)
public class ActuatorRefreshIT {
private static final String CONFIG_WATCHER_WIREMOCK_DEPLOYMENT_NAME = "config-watcher-wiremock-deployment";
@@ -80,7 +77,7 @@ public class ActuatorRefreshIT {
private K8SUtils k8SUtils;
@Before
@BeforeEach
public void setup() throws Exception {
this.client = createApiClient();
this.api = new CoreV1Api();
@@ -122,7 +119,7 @@ public class ActuatorRefreshIT {
verify(postRequestedFor(urlEqualTo("/actuator/refresh")));
}
@After
@AfterEach
public void after() throws Exception {
appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
@@ -149,20 +146,8 @@ public class ActuatorRefreshIT {
api.createNamespacedService(NAMESPACE, getConfigWatcherService(), null, null, null);
}
private V1Service getConfigWatcherService() throws Exception {
V1Service service = (V1Service) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-service.yaml");
return service;
}
private V1ConfigMap getConfigWatcherConfigMap() throws Exception {
V1ConfigMap configMap = (V1ConfigMap) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-configmap.yaml");
return configMap;
}
private V1Deployment getConfigWatcherDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils
V1Deployment deployment = (V1Deployment) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-http-deployment.yaml");
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ getPomVersion();
@@ -171,24 +156,30 @@ public class ActuatorRefreshIT {
}
private void deployWiremock() throws Exception {
appsApi.createNamespacedDeployment(NAMESPACE, getWireockDeployment(), null, null, null);
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");
}
private V1ConfigMap getConfigWatcherConfigMap() throws Exception {
return (V1ConfigMap) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-configmap.yaml");
}
private V1Ingress getWiremockIngress() throws Exception {
V1Ingress ingress = (V1Ingress) k8SUtils.readYamlFromClasspath("wiremock-ingress.yaml");
return ingress;
return (V1Ingress) K8SUtils.readYamlFromClasspath("wiremock-ingress.yaml");
}
private V1Service getWiremockAppService() throws Exception {
V1Service service = (V1Service) k8SUtils.readYamlFromClasspath("wiremock-service.yaml");
return service;
return (V1Service) K8SUtils.readYamlFromClasspath("wiremock-service.yaml");
}
private V1Deployment getWireockDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils.readYamlFromClasspath("wiremock-deployment.yaml");
return deployment;
private V1Deployment getWiremockDeployment() throws Exception {
return (V1Deployment) K8SUtils.readYamlFromClasspath("wiremock-deployment.yaml");
}
}

View File

@@ -30,11 +30,9 @@ 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.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
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;
@@ -50,10 +48,9 @@ import static org.springframework.cloud.kubernetes.integration.tests.commons.K8S
/**
* @author Kris Iyer
*/
@RunWith(MockitoJUnitRunner.class)
public class ActuatorRefreshKafkaIT {
private Log log = LogFactory.getLog(getClass());
private final Log log = LogFactory.getLog(getClass());
private static final String CONFIG_WATCHER_IT_IMAGE = "spring-cloud-kubernetes-configuration-watcher-it";
@@ -83,7 +80,7 @@ public class ActuatorRefreshKafkaIT {
private K8SUtils k8SUtils;
@Before
@BeforeEach
public void setup() throws Exception {
this.client = createApiClient();
this.api = new CoreV1Api();
@@ -115,14 +112,11 @@ public class ActuatorRefreshKafkaIT {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
log.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
if (clientHttpResponse.getRawStatusCode() == 503) {
return false;
}
return true;
return clientHttpResponse.getRawStatusCode() != 503;
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
public void handleError(ClientHttpResponse clientHttpResponse) {
}
});
@@ -141,7 +135,7 @@ public class ActuatorRefreshKafkaIT {
assertThat(rest.getForObject("http://localhost:80/it", Boolean.class)).isTrue();
}
@After
@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);
@@ -198,20 +192,8 @@ public class ActuatorRefreshKafkaIT {
System.out.println("created getKafkaDeployment");
}
private V1Service getConfigWatcherService() throws Exception {
V1Service service = (V1Service) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-service.yaml");
return service;
}
private V1ConfigMap getConfigWatcherConfigMap() throws Exception {
V1ConfigMap configMap = (V1ConfigMap) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-configmap.yaml");
return configMap;
}
private V1Deployment getConfigWatcherDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils
V1Deployment deployment = (V1Deployment) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-bus-kafka-deployment.yaml");
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ getPomVersion();
@@ -219,49 +201,48 @@ public class ActuatorRefreshKafkaIT {
return deployment;
}
private V1Service getItAppService() throws Exception {
String urlString = "spring-cloud-kubernetes-configuration-watcher-it-service.yaml";
V1Service service = (V1Service) k8SUtils.readYamlFromClasspath(urlString);
return service;
}
private V1Deployment getItDeployment() throws Exception {
String urlString = "spring-cloud-kubernetes-configuration-watcher-it-bus-kafka-deployment.yaml";
V1Deployment deployment = (V1Deployment) k8SUtils.readYamlFromClasspath(urlString);
V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath(urlString);
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ getPomVersion();
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
return deployment;
}
private V1Service getConfigWatcherService() throws Exception {
return (V1Service) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-service.yaml");
}
private V1ConfigMap getConfigWatcherConfigMap() throws Exception {
return (V1ConfigMap) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-configmap.yaml");
}
private V1Service getItAppService() throws Exception {
return (V1Service) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-it-service.yaml");
}
private V1Ingress getItIngress() throws Exception {
String urlString = "spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml";
V1Ingress ingress = (V1Ingress) k8SUtils.readYamlFromClasspath(urlString);
return ingress;
return (V1Ingress) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml");
}
private V1Deployment getKafkaDeployment() throws Exception {
String urlString = "kafka-deployment.yaml";
V1Deployment deployment = (V1Deployment) k8SUtils.readYamlFromClasspath(urlString);
return deployment;
return (V1Deployment) K8SUtils.readYamlFromClasspath("kafka-deployment.yaml");
}
private V1Service getKafkaService() throws Exception {
String urlString = "kafka-service.yaml";
V1Service service = (V1Service) k8SUtils.readYamlFromClasspath(urlString);
return service;
return (V1Service) K8SUtils.readYamlFromClasspath("kafka-service.yaml");
}
private V1Deployment getZookeeperDeployment() throws Exception {
String urlString = "zookeeper-deployment.yaml";
V1Deployment deployment = (V1Deployment) k8SUtils.readYamlFromClasspath(urlString);
return deployment;
return (V1Deployment) K8SUtils.readYamlFromClasspath("zookeeper-deployment.yaml");
}
private V1Service getZookeeperService() throws Exception {
String urlString = "zookeeper-service.yaml";
V1Service service = (V1Service) k8SUtils.readYamlFromClasspath(urlString);
return service;
return (V1Service) K8SUtils.readYamlFromClasspath("zookeeper-service.yaml");
}
}

View File

@@ -31,11 +31,9 @@ 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.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
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;
@@ -51,7 +49,6 @@ import static org.springframework.cloud.kubernetes.integration.tests.commons.K8S
/**
* @author Ryan Baxter
*/
@RunWith(MockitoJUnitRunner.class)
public class ActuatorRefreshRabbitMQIT {
private static final Log LOG = LogFactory.getLog(ActuatorRefreshRabbitMQIT.class);
@@ -80,7 +77,7 @@ public class ActuatorRefreshRabbitMQIT {
private K8SUtils k8SUtils;
@Before
@BeforeEach
public void setup() throws Exception {
this.client = createApiClient();
this.api = new CoreV1Api();
@@ -110,14 +107,11 @@ public class ActuatorRefreshRabbitMQIT {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
if (clientHttpResponse.getRawStatusCode() == 503) {
return false;
}
return true;
return clientHttpResponse.getRawStatusCode() != 503;
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
public void handleError(ClientHttpResponse clientHttpResponse) {
}
});
@@ -137,7 +131,7 @@ public class ActuatorRefreshRabbitMQIT {
assertThat(rest.getForObject("http://localhost:80/it", Boolean.class)).isTrue();
}
@After
@AfterEach
public 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);
@@ -187,23 +181,11 @@ public class ActuatorRefreshRabbitMQIT {
private void deployRabbitMQ() throws Exception {
api.createNamespacedService(NAMESPACE, getRabbitMQService(), null, null, null);
api.createNamespacedReplicationController(NAMESPACE, getRabbitMQRepplicationController(), null, null, null);
}
private V1Service getConfigWatcherService() throws Exception {
V1Service service = (V1Service) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-service.yaml");
return service;
}
private V1ConfigMap getConfigWatcherConfigMap() throws Exception {
V1ConfigMap configMap = (V1ConfigMap) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-configmap.yaml");
return configMap;
api.createNamespacedReplicationController(NAMESPACE, getRabbitMQReplicationController(), null, null, null);
}
private V1Deployment getConfigWatcherDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils
V1Deployment deployment = (V1Deployment) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-bus-amqp-deployment.yaml");
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ getPomVersion();
@@ -211,38 +193,40 @@ public class ActuatorRefreshRabbitMQIT {
return deployment;
}
private V1Service getItAppService() throws Exception {
String urlString = "spring-cloud-kubernetes-configuration-watcher-it-service.yaml";
V1Service service = (V1Service) k8SUtils.readYamlFromClasspath(urlString);
return service;
}
private V1Deployment getItDeployment() throws Exception {
String urlString = "spring-cloud-kubernetes-configuration-watcher-it-bus-amqp-deployment.yaml";
V1Deployment deployment = (V1Deployment) k8SUtils.readYamlFromClasspath(urlString);
V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath(urlString);
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
+ getPomVersion();
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
return deployment;
}
private V1Ingress getItIngress() throws Exception {
String urlString = "spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml";
V1Ingress ingress = (V1Ingress) k8SUtils.readYamlFromClasspath(urlString);
return ingress;
private V1Service getItAppService() throws Exception {
return (V1Service) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-it-service.yaml");
}
private V1ReplicationController getRabbitMQRepplicationController() throws Exception {
String urlString = "rabbitmq-controller.yaml";
V1ReplicationController replicationController = (V1ReplicationController) k8SUtils
.readYamlFromClasspath(urlString);
return replicationController;
private V1Service getConfigWatcherService() throws Exception {
return (V1Service) K8SUtils.readYamlFromClasspath("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 getItIngress() throws Exception {
return (V1Ingress) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-configuration-watcher-it-ingress.yaml");
}
private V1ReplicationController getRabbitMQReplicationController() throws Exception {
return (V1ReplicationController) K8SUtils.readYamlFromClasspath("rabbitmq-controller.yaml");
}
private V1Service getRabbitMQService() throws Exception {
String urlString = "rabbitmq-service.yaml";
V1Service service = (V1Service) k8SUtils.readYamlFromClasspath(urlString);
return service;
return (V1Service) K8SUtils.readYamlFromClasspath("rabbitmq-service.yaml");
}
}

View File

@@ -29,11 +29,9 @@ 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.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
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;
@@ -49,7 +47,6 @@ import static org.springframework.cloud.kubernetes.integration.tests.commons.K8S
/**
* @author Ryan Baxter
*/
@RunWith(MockitoJUnitRunner.class)
public class ActuatorEndpointIT {
private static final Log LOG = LogFactory.getLog(ActuatorEndpointIT.class);
@@ -72,7 +69,7 @@ public class ActuatorEndpointIT {
private static K8SUtils k8SUtils;
@BeforeClass
@BeforeAll
public static void setup() throws Exception {
client = createApiClient();
api = new CoreV1Api();
@@ -86,31 +83,12 @@ public class ActuatorEndpointIT {
k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_CLIENT_IT_DEPLOYMENT_NAME, NAMESPACE);
}
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);
}
private static V1Deployment getCoreK8sClientItDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-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 V1Service getCoreK8sClientItService() throws Exception {
V1Service service = (V1Service) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-it-service.yaml");
return service;
}
private static V1Ingress getCoreK8sClientItIngress() throws Exception {
V1Ingress ingress = (V1Ingress) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-it-ingress.yaml");
return ingress;
@AfterAll
public static 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);
networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null);
}
@Test
@@ -121,10 +99,7 @@ public class ActuatorEndpointIT {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
if (clientHttpResponse.getRawStatusCode() == 503) {
return false;
}
return true;
return clientHttpResponse.getRawStatusCode() != 503;
}
@Override
@@ -142,11 +117,11 @@ public class ActuatorEndpointIT {
+ rest.getForEntity("http://localhost:80/core-k8s-client-it/actuator/health", String.class));
Map<String, Object> health = rest.getForObject("http://localhost:80/core-k8s-client-it/actuator/health",
Map.class);
Map<String, Object> components = (Map) health.get("components");
Map<String, Object> components = (Map<String, Object>) health.get("components");
assertThat(components.containsKey("kubernetes")).isTrue();
Map<String, Object> kubernetes = (Map) components.get("kubernetes");
Map<String, Object> kubernetes = (Map<String, Object>) components.get("kubernetes");
assertThat(kubernetes.get("status")).isEqualTo("UP");
Map<String, Object> details = (Map) kubernetes.get("details");
Map<String, Object> details = (Map<String, Object>) kubernetes.get("details");
assertThat(details.containsKey("hostIp")).isTrue();
assertThat(details.containsKey("inside")).isTrue();
assertThat(details.containsKey("labels")).isTrue();
@@ -169,14 +144,11 @@ public class ActuatorEndpointIT {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
if (clientHttpResponse.getRawStatusCode() == 503) {
return false;
}
return true;
return clientHttpResponse.getRawStatusCode() != 503;
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
public void handleError(ClientHttpResponse clientHttpResponse) {
}
});
@@ -189,7 +161,7 @@ public class ActuatorEndpointIT {
LOG.debug("Response from /info endpoint: "
+ rest.getForEntity("http://localhost:80/core-k8s-client-it/actuator/info", String.class));
Map<String, Object> info = rest.getForObject("http://localhost:80/core-k8s-client-it/actuator/info", Map.class);
Map<String, Object> kubernetes = (Map) info.get("kubernetes");
Map<String, Object> kubernetes = (Map<String, Object>) info.get("kubernetes");
assertThat(kubernetes.containsKey("hostIp")).isTrue();
assertThat(kubernetes.containsKey("inside")).isTrue();
assertThat(kubernetes.containsKey("namespace")).isTrue();
@@ -199,12 +171,27 @@ public class ActuatorEndpointIT {
assertThat(kubernetes.containsKey("serviceAccount")).isTrue();
}
@AfterClass
public static 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);
networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null);
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);
}
private static V1Deployment getCoreK8sClientItDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) K8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-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 V1Service getCoreK8sClientItService() throws Exception {
return (V1Service) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-it-service.yaml");
}
private static V1Ingress getCoreK8sClientItIngress() throws Exception {
return (V1Ingress) K8SUtils.readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-it-ingress.yaml");
}
}

View File

@@ -105,39 +105,6 @@
<env.IMAGE>springcloud/${project.artifactId}:${project.version}</env.IMAGE>
</properties>
</profile>
<profile>
<id>jib</id>
<build>
<plugins>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>${jib.version}</version>
<configuration>
<from>
<image>${base.image}</image>
</from>
<to>
<image>spring-cloud/${project.artifactId}</image>
</to>
<container>
<user>nobody:nogroup</user>
<environment>
</environment>
</container>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>dockerBuild</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@@ -18,7 +18,6 @@ package org.springframework.cloud.kubernetes.discoveryclient.it;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
@@ -34,8 +33,11 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
public class KubernetesDiscoveryClientApplicationIt {
@Autowired
DiscoveryClient discoveryClient;
private final DiscoveryClient discoveryClient;
public KubernetesDiscoveryClientApplicationIt(DiscoveryClient discoveryClient) {
this.discoveryClient = discoveryClient;
}
public static void main(String[] args) {
SpringApplication.run(KubernetesDiscoveryClientApplicationIt.class, args);

View File

@@ -125,7 +125,7 @@ public class DiscoveryClientIT {
.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: " + result);
LOG.info("Services: " + Arrays.toString(result));
assertThat(Arrays.stream(result).anyMatch(s -> "spring-cloud-kubernetes-discoveryserver".equalsIgnoreCase(s)))
.isTrue();
@@ -138,14 +138,11 @@ public class DiscoveryClientIT {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
if (clientHttpResponse.getRawStatusCode() == 503) {
return false;
}
return true;
return clientHttpResponse.getRawStatusCode() != 503;
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
public void handleError(ClientHttpResponse clientHttpResponse) {
}
});
@@ -163,9 +160,9 @@ public class DiscoveryClientIT {
Map<String, Object> health = rest.getForObject("http://localhost:80/discoveryclient-it/actuator/health",
Map.class);
Map<String, Object> components = (Map) health.get("components");
Map<String, Object> components = (Map<String, Object>) health.get("components");
Map<String, Object> discoveryComposite = (Map) components.get("discoveryComposite");
Map<String, Object> discoveryComposite = (Map<String, Object>) components.get("discoveryComposite");
assertThat(discoveryComposite.get("status")).isEqualTo("UP");
}
@@ -186,12 +183,6 @@ public class DiscoveryClientIT {
networkingApi.createNamespacedIngress(NAMESPACE, getDiscoveryItIngress(), null, null, null);
}
private V1Service getDiscoveryService() throws Exception {
V1Service service = (V1Service) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-discoveryclient-it-service.yaml");
return service;
}
private V1Deployment getDiscoveryItDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-discoveryclient-it-deployment.yaml");
@@ -201,30 +192,12 @@ public class DiscoveryClientIT {
return deployment;
}
private V1Ingress getDiscoveryItIngress() throws Exception {
V1Ingress ingress = (V1Ingress) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-discoveryclient-it-ingress.yaml");
return ingress;
}
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 V1Ingress getDiscoveryServerIngress() throws Exception {
V1Ingress ingress = (V1Ingress) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-discoveryserver-ingress.yaml");
return ingress;
}
private static V1Service getDiscoveryServerService() throws Exception {
V1Service service = (V1Service) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-discoveryserver-service.yaml");
return service;
}
private static V1Deployment getDiscoveryServerDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils
.readYamlFromClasspath("spring-cloud-kubernetes-discoveryserver-deployment.yaml");
@@ -234,4 +207,20 @@ public class DiscoveryClientIT {
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");
}
}

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-integration-tests</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-kubernetes-fabric8-client-configmap</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8-all</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-test-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-transport-httpclient5</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>../src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<profiles>
<profile>
<id>imagename</id>
<activation>
<property>
<name>!env.IMAGE</name>
</property>
</activation>
<properties>
<env.IMAGE>springcloud/${project.artifactId}:${project.version}</env.IMAGE>
</properties>
</profile>
</profiles>
</project>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* 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.
@@ -14,38 +14,22 @@
* limitations under the License.
*/
package org.springframework.cloud.kubernetes.it;
package org.springframework.cloud.kubernetes.fabric8.configmap;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
/**
* @author wind57
*/
@SpringBootApplication
@RestController
public class SimpleSpringBootApplication {
@EnableConfigurationProperties(ConfigMapProperties.class)
public class ConfigMapApp {
public static void main(String[] args) {
SpringApplication.run(SimpleSpringBootApplication.class, args);
}
@GetMapping("/greeting")
public Greeting home() {
return new Greeting("Hello from Service A");
}
public static class Greeting {
private final String message;
public Greeting(String message) {
this.message = message;
}
public String getMessage() {
return this.message;
}
SpringApplication.run(ConfigMapApp.class, args);
}
}

View File

@@ -0,0 +1,39 @@
/*
* 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.fabric8.configmap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author wind57
*/
@RestController
public class ConfigMapController {
private final ConfigMapProperties properties;
public ConfigMapController(ConfigMapProperties properties) {
this.properties = properties;
}
@GetMapping("/key1")
public String key1() {
return properties.getKey1();
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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.fabric8.configmap;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author wind57
*/
@ConfigurationProperties("from.yaml")
public class ConfigMapProperties {
private String key1;
public String getKey1() {
return key1;
}
public void setKey1(String key1) {
this.key1 = key1;
}
}

View File

@@ -0,0 +1,7 @@
spring:
cloud:
kubernetes:
config:
sources:
- name: my-configmap
namespace: default

View File

@@ -0,0 +1,149 @@
/*
* 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.fabric8.configmap;
import java.io.FileInputStream;
import java.time.Duration;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.Deployment;
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.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import reactor.netty.http.client.HttpClient;
import reactor.util.retry.Retry;
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 {
private static final String NAMESPACE = "default";
private static KubernetesClient client;
private static String deploymentName;
private static String serviceName;
private static String ingressName;
private static String configMapName;
@BeforeAll
public static void setup() {
Config config = Config.autoConfigure(null);
client = new DefaultKubernetesClient(config);
deployManifests();
}
@AfterAll
public static void after() {
deleteManifests();
}
@Test
public void test() {
WebClient client = WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()))
.baseUrl("localhost/fabric8-configmap/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))
.block();
Assertions.assertEquals("value1", result);
}
private static void deleteManifests() {
try {
client.configMaps().inNamespace(NAMESPACE).withName(configMapName).delete();
client.apps().deployments().inNamespace(NAMESPACE).withName(deploymentName).delete();
client.services().inNamespace(NAMESPACE).withName(serviceName).delete();
client.network().v1().ingresses().inNamespace(NAMESPACE).withName(ingressName).delete();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void deployManifests() {
try {
ConfigMap configMap = client.configMaps().load(getConfigMap()).get();
configMapName = configMap.getMetadata().getName();
client.configMaps().create(configMap);
Deployment deployment = client.apps().deployments().load(getDeployment()).get();
String version = K8SUtils.getPomVersion();
String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage();
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version);
client.apps().deployments().inNamespace(NAMESPACE).create(deployment);
deploymentName = deployment.getMetadata().getName();
Service service = client.services().load(getService()).get();
serviceName = service.getMetadata().getName();
client.services().inNamespace(NAMESPACE).create(service);
Ingress ingress = client.network().v1().ingresses().load(getIngress()).get();
ingressName = ingress.getMetadata().getName();
client.network().v1().ingresses().inNamespace(NAMESPACE).create(ingress);
Fabric8Utils.waitForDeployment(client, "spring-cloud-kubernetes-fabric8-client-configmap-deployment",
NAMESPACE, 2, 600);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private static FileInputStream getService() throws Exception {
return Fabric8Utils.inputStream("fabric8-service.yaml");
}
private static FileInputStream getDeployment() throws Exception {
return Fabric8Utils.inputStream("fabric8-deployment.yaml");
}
private static FileInputStream getIngress() throws Exception {
return Fabric8Utils.inputStream("fabric8-ingress.yaml");
}
private static FileInputStream getConfigMap() throws Exception {
return Fabric8Utils.inputStream("fabric8-configmap.yaml");
}
}

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
namespace: default
data:
application.yaml: |
from:
yaml:
key1: value1

View File

@@ -0,0 +1,28 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-kubernetes-fabric8-client-configmap-deployment
spec:
selector:
matchLabels:
app: spring-cloud-kubernetes-fabric8-client-configmap
template:
metadata:
labels:
app: spring-cloud-kubernetes-fabric8-client-configmap
spec:
serviceAccountName: spring-cloud-kubernetes-serviceaccount
containers:
- name: spring-cloud-kubernetes-fabric8-client-configmap
image: docker.io/springcloud/spring-cloud-kubernetes-fabric8-client-configmap
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
port: 8080
path: /actuator/health/readiness
livenessProbe:
httpGet:
port: 8080
path: /actuator/health/liveness
ports:
- containerPort: 8080

View File

@@ -0,0 +1,18 @@
apiVersion: networking.k8s.io/v1
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(/|$)(.*)
pathType: Prefix
backend:
service:
name: spring-cloud-kubernetes-fabric8-client-configmap
port:
number: 8080

View File

@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: spring-cloud-kubernetes-fabric8-client-configmap
name: spring-cloud-kubernetes-fabric8-client-configmap
spec:
ports:
- name: http
port: 8080
targetPort: 8080
selector:
app: spring-cloud-kubernetes-fabric8-client-configmap
type: ClusterIP

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-integration-tests</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-kubernetes-fabric8-client-discovery</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-fabric8-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-test-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-transport-httpclient5</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>../src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<profiles>
<profile>
<id>imagename</id>
<activation>
<property>
<name>!env.IMAGE</name>
</property>
</activation>
<properties>
<env.IMAGE>springcloud/${project.artifactId}:${project.version}</env.IMAGE>
</properties>
</profile>
</profiles>
</project>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* 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.
@@ -14,42 +14,19 @@
* limitations under the License.
*/
package org.springframework.cloud.kubernetes.it;
package org.springframework.cloud.kubernetes.fabric8.configmap;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author wind57
*/
@SpringBootApplication
@RestController
public class SimpleCoreApplication {
public class Fabric8DiscoveryApp {
public static void main(String[] args) {
SpringApplication.run(SimpleCoreApplication.class, args);
}
@Value("${greeting.message}")
private String message;
@GetMapping("/greeting")
public Greeting home() {
return new Greeting(message);
}
public static class Greeting {
private final String message;
public Greeting(String message) {
this.message = message;
}
public String getMessage() {
return this.message;
}
SpringApplication.run(Fabric8DiscoveryApp.class, args);
}
}

View File

@@ -0,0 +1,42 @@
/*
* 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.fabric8.configmap;
import java.util.List;
import org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author wind57
*/
@RestController
public class Fabric8DiscoveryController {
private final KubernetesDiscoveryClient discoveryClient;
public Fabric8DiscoveryController(KubernetesDiscoveryClient discoveryClient) {
this.discoveryClient = discoveryClient;
}
@GetMapping("/services")
public List<String> allServices() {
return discoveryClient.getServices();
}
}

View File

@@ -0,0 +1,183 @@
/*
* 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.fabric8.configmap;
import java.io.FileInputStream;
import java.time.Duration;
import java.util.List;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.Deployment;
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.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import reactor.netty.http.client.HttpClient;
import reactor.util.retry.Retry;
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 {
private static final String NAMESPACE = "default";
private static KubernetesClient client;
private static String deploymentName;
private static String serviceName;
private static String ingressName;
private static String mockServiceName;
private static String mockDeploymentName;
@BeforeAll
public static void setup() {
Config config = Config.autoConfigure(null);
client = new DefaultKubernetesClient(config);
deployManifests();
deployMockManifests();
}
@AfterAll
public static void after() {
deleteManifests();
}
@Test
public void test() {
WebClient client = WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()))
.baseUrl("localhost/fabric8-discovery/services").build();
@SuppressWarnings("unchecked")
List<String> result = (List<String>) client.method(HttpMethod.GET).retrieve().bodyToMono(List.class)
.retryWhen(Retry.fixedDelay(15, Duration.ofSeconds(1))
.filter(x -> ((WebClientResponseException) x).getStatusCode().value() == 503))
.block();
Assertions.assertEquals(result.size(), 3);
Assertions.assertTrue(result.contains("kubernetes"));
Assertions.assertTrue(result.contains("spring-cloud-kubernetes-fabric8-client-discovery"));
Assertions.assertTrue(result.contains("servicea-wiremock"));
}
private static void deleteManifests() {
try {
client.apps().deployments().inNamespace(NAMESPACE).withName(deploymentName).delete();
client.services().inNamespace(NAMESPACE).withName(serviceName).delete();
client.network().v1().ingresses().inNamespace(NAMESPACE).withName(ingressName).delete();
client.services().inNamespace(NAMESPACE).withName(mockServiceName).delete();
client.apps().deployments().inNamespace(NAMESPACE).withName(mockDeploymentName).delete();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void deployManifests() {
try {
Deployment deployment = client.apps().deployments().load(getDeployment()).get();
String version = K8SUtils.getPomVersion();
String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage();
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version);
client.apps().deployments().inNamespace(NAMESPACE).create(deployment);
deploymentName = deployment.getMetadata().getName();
Service service = client.services().load(getService()).get();
serviceName = service.getMetadata().getName();
client.services().inNamespace(NAMESPACE).create(service);
Ingress ingress = client.network().v1().ingresses().load(getIngress()).get();
ingressName = ingress.getMetadata().getName();
client.network().v1().ingresses().inNamespace(NAMESPACE).create(ingress);
Fabric8Utils.waitForDeployment(client, "spring-cloud-kubernetes-fabric8-client-discovery-deployment",
NAMESPACE, 2, 600);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void deployMockManifests() {
try {
Deployment deployment = client.apps().deployments().load(getMockDeployment()).get();
client.apps().deployments().inNamespace(NAMESPACE).create(deployment);
mockDeploymentName = deployment.getMetadata().getName();
Service service = client.services().load(getMockService()).get();
mockServiceName = service.getMetadata().getName();
client.services().inNamespace(NAMESPACE).create(service);
Fabric8Utils.waitForDeployment(client, "servicea-wiremock-deployment", NAMESPACE, 2, 600);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private static FileInputStream getService() throws Exception {
return Fabric8Utils.inputStream("fabric8-discovery-service.yaml");
}
private static FileInputStream getDeployment() throws Exception {
return Fabric8Utils.inputStream("fabric8-discovery-deployment.yaml");
}
private static FileInputStream getIngress() throws Exception {
return Fabric8Utils.inputStream("fabric8-discovery-ingress.yaml");
}
private static FileInputStream getMockService() throws Exception {
return Fabric8Utils.inputStream("fabric8-discovery-wiremock-service.yaml");
}
private static FileInputStream getMockDeployment() throws Exception {
return Fabric8Utils.inputStream("fabric8-discovery-wiremock-deployment.yaml");
}
}

View File

@@ -0,0 +1,28 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-kubernetes-fabric8-client-discovery-deployment
spec:
selector:
matchLabels:
app: spring-cloud-kubernetes-fabric8-client-discovery
template:
metadata:
labels:
app: spring-cloud-kubernetes-fabric8-client-discovery
spec:
serviceAccountName: spring-cloud-kubernetes-serviceaccount
containers:
- name: spring-cloud-kubernetes-fabric8-client-discovery
image: docker.io/springcloud/spring-cloud-kubernetes-fabric8-client-discovery
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
port: 8080
path: /actuator/health/readiness
livenessProbe:
httpGet:
port: 8080
path: /actuator/health/liveness
ports:
- containerPort: 8080

View File

@@ -0,0 +1,18 @@
apiVersion: networking.k8s.io/v1
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(/|$)(.*)
pathType: Prefix
backend:
service:
name: spring-cloud-kubernetes-fabric8-client-discovery
port:
number: 8080

View File

@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: spring-cloud-kubernetes-fabric8-client-discovery
name: spring-cloud-kubernetes-fabric8-client-discovery
spec:
ports:
- name: http
port: 8080
targetPort: 8080
selector:
app: spring-cloud-kubernetes-fabric8-client-discovery
type: ClusterIP

View File

@@ -0,0 +1,27 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: servicea-wiremock-deployment
spec:
selector:
matchLabels:
app: servicea-wiremock
template:
metadata:
labels:
app: servicea-wiremock
spec:
containers:
- name: servicea-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

View File

@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: servicea-wiremock
name: servicea-wiremock
spec:
ports:
- name: http
port: 8080
targetPort: 8080
selector:
app: servicea-wiremock
type: ClusterIP

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-integration-tests</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-kubernetes-fabric8-client-loadbalancer</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-fabric8-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-test-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-transport-httpclient5</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>../src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<profiles>
<profile>
<id>imagename</id>
<activation>
<property>
<name>!env.IMAGE</name>
</property>
</activation>
<properties>
<env.IMAGE>springcloud/${project.artifactId}:${project.version}</env.IMAGE>
</properties>
</profile>
</profiles>
</project>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* 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.
@@ -14,38 +14,53 @@
* limitations under the License.
*/
package org.springframework.cloud.kubernetes.it;
package org.springframework.cloud.kubernetes.fabric8.cliend.loadbalancer;
import java.net.URI;
import java.util.List;
import java.util.Map;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
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.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
@SpringBootApplication
@RestController
public class DiscoveryClientApplication {
public class Fabric8ClientLoadbalancerApp {
@Autowired
private DiscoveryClient discoveryClient;
private final DiscoveryClient discoveryClient;
public Fabric8ClientLoadbalancerApp(DiscoveryClient discoveryClient) {
this.discoveryClient = discoveryClient;
}
public static void main(String[] args) {
SpringApplication.run(DiscoveryClientApplication.class, args);
SpringApplication.run(Fabric8ClientLoadbalancerApp.class, args);
}
@Bean
@LoadBalanced
WebClient.Builder builder() {
return WebClient.builder();
}
@GetMapping("/servicea")
public Mono<Map> greeting() {
return builder().build().method(HttpMethod.GET).uri(URI.create("http://servicea-wiremock/__admin/mappings"))
.retrieve().bodyToMono(Map.class);
}
@GetMapping("/services")
public List<String> services() {
return this.discoveryClient.getServices();
}
@GetMapping("/services/{service}/instances")
public List<ServiceInstance> instances(@PathVariable("service") String service) {
return this.discoveryClient.getInstances(service);
return discoveryClient.getServices();
}
}

View File

@@ -0,0 +1,251 @@
/*
* 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.loadbalancer.it;
import java.io.FileInputStream;
import java.time.Duration;
import java.util.Map;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.Deployment;
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.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import reactor.netty.http.client.HttpClient;
import reactor.util.retry.Retry;
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;
/**
* @author wind57
*/
public class Fabric8ClientLoadbalancerIT {
private static final String NAMESPACE = "default";
private static KubernetesClient client;
private static String deploymentName;
private static String serviceName;
private static String ingressName;
private static String mockServiceName;
private static String mockDeploymentName;
private static String mockIngressName;
@BeforeEach
public void setup() {
Config config = Config.autoConfigure(null);
client = new DefaultKubernetesClient(config);
deployMockManifests();
}
@AfterEach
public void after() {
deleteManifests();
}
@Test
public void testLoadBalancerServiceMode() {
deployServiceManifests();
WebClient client = WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()))
.baseUrl("localhost/loadbalancer-it/servicea").build();
@SuppressWarnings("unchecked")
Map<String, String> mapResult = (Map<String, String>) client.method(HttpMethod.GET).retrieve()
.bodyToMono(Map.class).retryWhen(Retry.fixedDelay(15, Duration.ofSeconds(1))
.filter(x -> ((WebClientResponseException) x).getStatusCode().value() == 503))
.block();
assertThat(mapResult.containsKey("mappings")).isTrue();
assertThat(mapResult.containsKey("meta")).isTrue();
}
@Test
public void testLoadBalancerPodMode() {
deployPodManifests();
WebClient client = WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()))
.baseUrl("localhost/loadbalancer-it/servicea").build();
@SuppressWarnings("unchecked")
Map<String, String> mapResult = (Map<String, String>) client.method(HttpMethod.GET).retrieve()
.bodyToMono(Map.class).retryWhen(Retry.fixedDelay(15, Duration.ofSeconds(1))
.filter(x -> ((WebClientResponseException) x).getStatusCode().value() == 503))
.block();
assertThat(mapResult.containsKey("mappings")).isTrue();
assertThat(mapResult.containsKey("meta")).isTrue();
}
private static void deleteManifests() {
try {
client.apps().deployments().inNamespace(NAMESPACE).withName(deploymentName).delete();
client.services().inNamespace(NAMESPACE).withName(serviceName).delete();
client.network().v1().ingresses().inNamespace(NAMESPACE).withName(ingressName).delete();
client.services().inNamespace(NAMESPACE).withName(mockServiceName).delete();
client.apps().deployments().inNamespace(NAMESPACE).withName(mockDeploymentName).delete();
client.network().v1().ingresses().inNamespace(NAMESPACE).withName(mockIngressName).delete();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void deployServiceManifests() {
try {
Deployment deployment = client.apps().deployments().load(getServiceDeployment()).get();
String version = K8SUtils.getPomVersion();
String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage();
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version);
client.apps().deployments().inNamespace(NAMESPACE).create(deployment);
deploymentName = deployment.getMetadata().getName();
Service service = client.services().load(getService()).get();
serviceName = service.getMetadata().getName();
client.services().inNamespace(NAMESPACE).create(service);
Ingress ingress = client.network().v1().ingresses().load(getIngress()).get();
ingressName = ingress.getMetadata().getName();
client.network().v1().ingresses().inNamespace(NAMESPACE).create(ingress);
Fabric8Utils.waitForDeployment(client, "spring-cloud-kubernetes-fabric8-client-loadbalancer-deployment",
NAMESPACE, 2, 600);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void deployPodManifests() {
try {
Deployment deployment = client.apps().deployments().load(getPodDeployment()).get();
String version = K8SUtils.getPomVersion();
String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage();
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version);
client.apps().deployments().inNamespace(NAMESPACE).create(deployment);
deploymentName = deployment.getMetadata().getName();
Service service = client.services().load(getService()).get();
serviceName = service.getMetadata().getName();
client.services().inNamespace(NAMESPACE).create(service);
Ingress ingress = client.network().v1().ingresses().load(getIngress()).get();
ingressName = ingress.getMetadata().getName();
client.network().v1().ingresses().inNamespace(NAMESPACE).create(ingress);
Fabric8Utils.waitForDeployment(client, "spring-cloud-kubernetes-fabric8-client-loadbalancer-deployment",
NAMESPACE, 2, 600);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void deployMockManifests() {
try {
Deployment deployment = client.apps().deployments().load(getMockDeployment()).get();
client.apps().deployments().inNamespace(NAMESPACE).create(deployment);
mockDeploymentName = deployment.getMetadata().getName();
Service service = client.services().load(getMockService()).get();
mockServiceName = service.getMetadata().getName();
client.services().inNamespace(NAMESPACE).create(service);
Ingress ingress = client.network().v1().ingresses().load(getMockIngress()).get();
mockIngressName = ingress.getMetadata().getName();
Fabric8Utils.waitForDeployment(client, "servicea-wiremock-deployment", NAMESPACE, 2, 600);
Fabric8Utils.waitForEndpoint(client, "servicea-wiremock", NAMESPACE, 2, 600);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private static FileInputStream getIngress() throws Exception {
return Fabric8Utils.inputStream("spring-cloud-kubernetes-fabric8-client-loadbalancer-ingress.yaml");
}
private static FileInputStream getService() throws Exception {
return Fabric8Utils.inputStream("spring-cloud-kubernetes-fabric8-client-loadbalancer-service.yaml");
}
private static FileInputStream getPodDeployment() throws Exception {
return Fabric8Utils.inputStream("spring-cloud-kubernetes-fabric8-client-loadbalancer-pod-deployment.yaml");
}
private static FileInputStream getServiceDeployment() throws Exception {
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 FileInputStream getMockService() throws Exception {
return Fabric8Utils.inputStream("wiremock-service.yaml");
}
private static FileInputStream getMockDeployment() throws Exception {
return Fabric8Utils.inputStream("wiremock-deployment.yaml");
}
}

View File

@@ -0,0 +1,21 @@
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: /loadbalancer-it(/|$)(.*)
pathType: Prefix
backend:
service:
name: spring-cloud-kubernetes-fabric8-client-loadbalancer
port:
number: 8080

View File

@@ -0,0 +1,31 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-kubernetes-fabric8-client-loadbalancer-deployment
spec:
selector:
matchLabels:
app: spring-cloud-kubernetes-fabric8-client-loadbalancer
template:
metadata:
labels:
app: spring-cloud-kubernetes-fabric8-client-loadbalancer
spec:
serviceAccountName: spring-cloud-kubernetes-serviceaccount
containers:
- name: spring-cloud-kubernetes-fabric8-client-loadbalancer
env:
- name: SPRING_CLOUD_KUBERNETES_LOADBALANCER_MODE
value: POD
image: docker.io/springcloud/spring-cloud-kubernetes-fabric8-client-loadbalancer
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
port: 8080
path: /actuator/health/readiness
livenessProbe:
httpGet:
port: 8080
path: /actuator/health/liveness
ports:
- containerPort: 8080

View File

@@ -0,0 +1,31 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-kubernetes-fabric8-client-loadbalancer-deployment
spec:
selector:
matchLabels:
app: spring-cloud-kubernetes-fabric8-client-loadbalancer
template:
metadata:
labels:
app: spring-cloud-kubernetes-fabric8-client-loadbalancer
spec:
serviceAccountName: spring-cloud-kubernetes-serviceaccount
containers:
- name: spring-cloud-kubernetes-fabric8-client-loadbalancer
env:
- name: SPRING_CLOUD_KUBERNETES_LOADBALANCER_MODE
value: SERVICE
image: docker.io/springcloud/spring-cloud-kubernetes-fabric8-client-loadbalancer
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
port: 8080
path: /actuator/health/readiness
livenessProbe:
httpGet:
port: 8080
path: /actuator/health/liveness
ports:
- containerPort: 8080

View File

@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: spring-cloud-kubernetes-fabric8-client-loadbalancer
name: spring-cloud-kubernetes-fabric8-client-loadbalancer
spec:
ports:
- name: http
port: 8080
targetPort: 8080
selector:
app: spring-cloud-kubernetes-fabric8-client-loadbalancer
type: ClusterIP

View File

@@ -0,0 +1,27 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: servicea-wiremock-deployment
spec:
selector:
matchLabels:
app: servicea-wiremock
template:
metadata:
labels:
app: servicea-wiremock
spec:
containers:
- name: servicea-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

View File

@@ -0,0 +1,19 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wiremock-ingress
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- path: /wiremock(/|$)(.*)
pathType: Prefix
backend:
service:
name: servicea-wiremock
port:
number: 8080

View File

@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: servicea-wiremock
name: servicea-wiremock
spec:
ports:
- name: http
port: 8080
targetPort: 8080
selector:
app: servicea-wiremock
type: ClusterIP

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-integration-tests</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-kubernetes-fabric8-client-simple-core</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8-all</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-test-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-transport-httpclient5</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>../src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<profiles>
<profile>
<id>imagename</id>
<activation>
<property>
<name>!env.IMAGE</name>
</property>
</activation>
<properties>
<env.IMAGE>springcloud/${project.artifactId}:${project.version}</env.IMAGE>
</properties>
</profile>
</profiles>
</project>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* 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.
@@ -14,38 +14,21 @@
* limitations under the License.
*/
package org.springframework.cloud.kubernetes.it;
package org.springframework.cloud.kubernetes.fabric8.simple.core;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
/**
* @author wind57
*/
@EnableConfigurationProperties(SimpleCoreProperties.class)
@SpringBootApplication
@RestController
public class SimpleSpringBootApplication {
public class SimpleCoreApp {
public static void main(String[] args) {
SpringApplication.run(SimpleSpringBootApplication.class, args);
}
@GetMapping("/greeting")
public Greeting home() {
return new Greeting("Hello from Service B");
}
public static class Greeting {
private final String message;
public Greeting(String message) {
this.message = message;
}
public String getMessage() {
return this.message;
}
SpringApplication.run(SimpleCoreApp.class, args);
}
}

View File

@@ -0,0 +1,39 @@
/*
* 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.fabric8.simple.core;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author wind57
*/
@RestController
public class SimpleCoreController {
private final SimpleCoreProperties properties;
public SimpleCoreController(SimpleCoreProperties properties) {
this.properties = properties;
}
@GetMapping("/message")
public String message() {
return properties.getMessage();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* 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.
@@ -14,17 +14,20 @@
* limitations under the License.
*/
package org.springframework.cloud.kubernetes.it;
package org.springframework.cloud.kubernetes.fabric8.simple.core;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "config")
public class DummyConfig {
/**
* @author wind57
*/
@ConfigurationProperties("greeting")
public class SimpleCoreProperties {
private String message = "This is a dummy message";
private String message;
public String getMessage() {
return this.message;
return message;
}
public void setMessage(String message) {

Some files were not shown because too many files have changed in this diff Show More