Merge branch '3.2.x'

This commit is contained in:
Ryan Baxter
2025-03-10 16:04:38 -04:00
21 changed files with 87 additions and 354 deletions

View File

@@ -106,7 +106,7 @@
<module>spring-cloud-kubernetes-k8s-client-kafka-configmap-reload</module>
<!-- config watcher reload, using rabbitmq and secret -->
<module>spring-cloud-kubernetes-k8s-client-rabbitmq-secret-reload-multiple-apps</module>
<module>spring-cloud-kubernetes-k8s-client-rabbitmq-secret-reload</module>
</modules>
</project>

View File

@@ -1,57 +0,0 @@
/*
* Copyright 2013-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.kubernetes.configuration.watcher.appB;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author wind57
*/
@SpringBootApplication
@RestController
public class AppBTestApplication implements ApplicationListener<RefreshRemoteApplicationEvent> {
private final Log LOG = LogFactory.getLog(getClass());
private boolean value = false;
public static void main(String[] args) {
SpringApplication.run(AppBTestApplication.class, args);
}
@GetMapping("/app-b")
public boolean index() {
LOG.info("Current value: " + value);
return value;
}
@Override
public void onApplicationEvent(RefreshRemoteApplicationEvent refreshRemoteApplicationEvent) {
LOG.info("Received remote refresh event from origin: " + refreshRemoteApplicationEvent.getOriginService()
+ " to destination : " + refreshRemoteApplicationEvent.getDestinationService());
this.value = true;
}
}

View File

@@ -1,24 +0,0 @@
#logging:
# level:
# org.springframework: DEBUG
#
spring:
application:
name: spring-cloud-kubernetes-client-configuration-watcher-secret-app-b
cloud:
bus:
refresh:
enabled: false
enabled: true
destination: multiple-apps
stream:
default-binder: rabbit
autoconfigure:
exclude: org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration
management:
endpoint:
health:
probes:
enabled: true
server:
port: 8081

View File

@@ -1,72 +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-k8s-client-rabbitmq-secret-reload-multiple-apps</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>3.3.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>rabbitmq-secret-test-app</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-test-support</artifactId>
</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>
<!-- no need to build image for this module -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>build-image</id>
<configuration>
<skip>true</skip>
</configuration>
</execution>
<execution>
<id>repackage</id>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,32 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-b-deployment
spec:
selector:
matchLabels:
app: app-b
template:
metadata:
labels:
app: app-b
spec:
containers:
- name: app-b
image: docker.io/springcloud/rabbitmq-secret-app-b
imagePullPolicy: IfNotPresent
env:
- name: SPRING_PROFILES_ACTIVE
value: bus-amqp
- name: SPRING_RABBITMQ_HOST
value: rabbitmq-service
readinessProbe:
httpGet:
port: 8081
path: /actuator/health/readiness
livenessProbe:
httpGet:
port: 8081
path: /actuator/health/liveness
ports:
- containerPort: 8081

View File

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

View File

@@ -1,14 +0,0 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: spring-cloud-kubernetes-configuration-watcher
name: spring-cloud-kubernetes-configuration-watcher
spec:
ports:
- name: http
port: 8888
targetPort: 8888
selector:
app: spring-cloud-kubernetes-configuration-watcher
type: ClusterIP

View File

@@ -1,26 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: it-ingress-multiple-apps
namespace: default
spec:
rules:
- http:
paths:
- path: /app-a
pathType: Prefix
backend:
service:
name: app-a
port:
number: 8080
- http:
paths:
- path: /app-b
pathType: Prefix
backend:
service:
name: app-b
port:
number: 8081

View File

@@ -9,12 +9,11 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-kubernetes-k8s-client-rabbitmq-secret-reload-multiple-apps</artifactId>
<artifactId>spring-cloud-kubernetes-k8s-client-rabbitmq-secret-reload</artifactId>
<packaging>pom</packaging>
<modules>
<module>rabbitmq-secret-app-a</module>
<module>rabbitmq-secret-app-b</module>
<module>rabbitmq-secret-app</module>
<module>rabbitmq-secret-test-app</module>
</modules>

View File

@@ -3,14 +3,14 @@
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-k8s-client-rabbitmq-secret-reload-multiple-apps</artifactId>
<artifactId>spring-cloud-kubernetes-k8s-client-rabbitmq-secret-reload</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>3.3.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>rabbitmq-secret-app-b</artifactId>
<artifactId>rabbitmq-secret-app</artifactId>
<dependencies>
<dependency>
@@ -28,18 +28,4 @@
</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>
</project>

View File

@@ -31,17 +31,17 @@ import org.springframework.web.bind.annotation.RestController;
*/
@SpringBootApplication
@RestController
public class AppATestApplication implements ApplicationListener<RefreshRemoteApplicationEvent> {
public class AppTestApplication implements ApplicationListener<RefreshRemoteApplicationEvent> {
private final Log LOG = LogFactory.getLog(getClass());
private boolean value = false;
public static void main(String[] args) {
SpringApplication.run(AppATestApplication.class, args);
SpringApplication.run(AppTestApplication.class, args);
}
@GetMapping("/app-a")
@GetMapping("/app")
public boolean index() {
LOG.info("Current value: " + value);
return value;

View File

@@ -1,16 +1,13 @@
#logging:
# level:
# org.springframework: DEBUG
#
spring:
application:
name: spring-cloud-kubernetes-client-configuration-watcher-secret-app-a
name: non-app
cloud:
bus:
refresh:
enabled: false
enabled: true
destination: multiple-apps
destination: app
id: app
stream:
default-binder: rabbit
autoconfigure:

View File

@@ -3,27 +3,33 @@
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-k8s-client-rabbitmq-secret-reload-multiple-apps</artifactId>
<artifactId>spring-cloud-kubernetes-k8s-client-rabbitmq-secret-reload</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>3.3.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>rabbitmq-secret-app-a</artifactId>
<properties>
<spring-boot.repackage.skip>true</spring-boot.repackage.skip>
<spring-boot.build-image.skip>true</spring-boot.build-image.skip>
</properties>
<artifactId>rabbitmq-secret-test-app</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-test-support</artifactId>
</dependency>
</dependencies>
@@ -31,15 +37,10 @@
<build>
<resources>
<resource>
<directory>../src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<directory>../../src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>

View File

@@ -47,16 +47,12 @@ import static org.awaitility.Awaitility.await;
/**
* @author wind57
*/
class ConfigurationWatcherMultipleAppIT {
class ConfigurationWatcherBusAmqpIT {
private static final String CONFIG_WATCHER_APP_A_IMAGE = "rabbitmq-secret-app-a";
private static final String CONFIG_WATCHER_APP_B_IMAGE = "rabbitmq-secret-app-b";
private static final String CONFIG_WATCHER_APP_IMAGE = "rabbitmq-secret-app";
private static final String SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME = "spring-cloud-kubernetes-configuration-watcher";
private static final String SECRET_NAME = "multiple-apps";
private static final String NAMESPACE = "default";
private static final K3sContainer K3S = Commons.container();
@@ -70,11 +66,8 @@ class ConfigurationWatcherMultipleAppIT {
Commons.validateImage(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, K3S);
Commons.loadSpringCloudKubernetesImage(SPRING_CLOUD_K8S_CONFIG_WATCHER_APP_NAME, K3S);
Commons.validateImage(CONFIG_WATCHER_APP_A_IMAGE, K3S);
Commons.loadSpringCloudKubernetesImage(CONFIG_WATCHER_APP_A_IMAGE, K3S);
Commons.validateImage(CONFIG_WATCHER_APP_B_IMAGE, K3S);
Commons.loadSpringCloudKubernetesImage(CONFIG_WATCHER_APP_B_IMAGE, K3S);
Commons.validateImage(CONFIG_WATCHER_APP_IMAGE, K3S);
Commons.loadSpringCloudKubernetesImage(CONFIG_WATCHER_APP_IMAGE, K3S);
Images.loadRabbitmq(K3S);
@@ -86,7 +79,6 @@ class ConfigurationWatcherMultipleAppIT {
void setup() {
util.rabbitMq(NAMESPACE, Phase.CREATE);
appA(Phase.CREATE);
appB(Phase.CREATE);
configWatcher(Phase.CREATE);
}
@@ -94,7 +86,6 @@ class ConfigurationWatcherMultipleAppIT {
void after() {
util.rabbitMq(NAMESPACE, Phase.DELETE);
appA(Phase.DELETE);
appB(Phase.DELETE);
configWatcher(Phase.DELETE);
}
@@ -104,52 +95,34 @@ class ConfigurationWatcherMultipleAppIT {
// secret has one label, one that says that we should refresh
// and one annotation that says that we should refresh some specific services
V1Secret secret = new V1SecretBuilder().editOrNewMetadata()
.withName(SECRET_NAME)
.withName("secret")
.addToLabels("spring.cloud.kubernetes.secret", "true")
.addToAnnotations("spring.cloud.kubernetes.secret.apps",
"spring-cloud-kubernetes-client-configuration-watcher-secret-app-a, "
+ "spring-cloud-kubernetes-client-configuration-watcher-secret-app-b")
.addToAnnotations("spring.cloud.kubernetes.secret.apps", "app")
.endMetadata()
.build();
util.createAndWait(NAMESPACE, null, secret);
WebClient.Builder builderA = builder();
WebClient serviceClientA = builderA.baseUrl("http://localhost:80/app-a").build();
WebClient.Builder builder = builder();
WebClient serviceClient = builder.baseUrl("http://localhost:80/app").build();
WebClient.Builder builderB = builder();
WebClient serviceClientB = builderB.baseUrl("http://localhost:80/app-b").build();
Boolean[] valueA = new Boolean[1];
Boolean[] value = new Boolean[1];
await().pollInterval(Duration.ofSeconds(3)).atMost(Duration.ofSeconds(240)).until(() -> {
valueA[0] = serviceClientA.method(HttpMethod.GET)
value[0] = serviceClient.method(HttpMethod.GET)
.retrieve()
.bodyToMono(Boolean.class)
.retryWhen(retrySpec())
.block();
return valueA[0];
return value[0];
});
Assertions.assertTrue(valueA[0]);
Boolean[] valueB = new Boolean[1];
await().pollInterval(Duration.ofSeconds(3)).atMost(Duration.ofSeconds(240)).until(() -> {
valueB[0] = serviceClientB.method(HttpMethod.GET)
.retrieve()
.bodyToMono(Boolean.class)
.retryWhen(retrySpec())
.block();
return valueB[0];
});
Assertions.assertTrue(valueB[0]);
Assertions.assertTrue(value[0]);
util.deleteAndWait(NAMESPACE, null, secret);
}
private void appA(Phase phase) {
V1Deployment deployment = (V1Deployment) util.yaml("app-a/app-a-deployment.yaml");
V1Service service = (V1Service) util.yaml("app-a/app-a-service.yaml");
V1Ingress ingress = (V1Ingress) util
.yaml("ingress/spring-cloud-kubernetes-configuration-watcher-multiple-apps-ingress.yaml");
V1Deployment deployment = (V1Deployment) util.yaml("app/app-deployment.yaml");
V1Service service = (V1Service) util.yaml("app/app-service.yaml");
V1Ingress ingress = (V1Ingress) util.yaml("ingress/ingress.yaml");
if (phase.equals(Phase.CREATE)) {
util.createAndWait(NAMESPACE, null, deployment, service, ingress, true);
@@ -159,23 +132,9 @@ class ConfigurationWatcherMultipleAppIT {
}
}
private void appB(Phase phase) {
V1Deployment deployment = (V1Deployment) util.yaml("app-b/app-b-deployment.yaml");
V1Service service = (V1Service) util.yaml("app-b/app-b-service.yaml");
if (phase.equals(Phase.CREATE)) {
util.createAndWait(NAMESPACE, null, deployment, service, null, true);
}
else if (phase.equals(Phase.DELETE)) {
util.deleteAndWait(NAMESPACE, deployment, service, null);
}
}
private void configWatcher(Phase phase) {
V1Deployment deployment = (V1Deployment) util
.yaml("config-watcher/spring-cloud-kubernetes-configuration-watcher-it-bus-amqp-deployment.yaml");
V1Service service = (V1Service) util
.yaml("config-watcher/spring-cloud-kubernetes-configuration-watcher-service.yaml");
V1Deployment deployment = (V1Deployment) util.yaml("config-watcher/watcher-deployment.yaml");
V1Service service = (V1Service) util.yaml("config-watcher/watcher-service.yaml");
if (phase.equals(Phase.CREATE)) {
util.createAndWait(NAMESPACE, null, deployment, service, null, true);

View File

@@ -1,19 +1,19 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-a-deployment
name: app-deployment
spec:
selector:
matchLabels:
app: app-a
app: app
template:
metadata:
labels:
app: app-a
app: app
spec:
containers:
- name: app-a
image: docker.io/springcloud/rabbitmq-secret-app-a
- name: app
image: docker.io/springcloud/rabbitmq-secret-app
imagePullPolicy: IfNotPresent
env:
- name: SPRING_PROFILES_ACTIVE

View File

@@ -1,19 +1,19 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-kubernetes-configuration-watcher-deployment
name: watcher-deployment
spec:
selector:
matchLabels:
app: spring-cloud-kubernetes-configuration-watcher
app: configuration-watcher
template:
metadata:
labels:
app: spring-cloud-kubernetes-configuration-watcher
app: configuration-watcher
spec:
serviceAccountName: spring-cloud-kubernetes-serviceaccount
containers:
- name: spring-cloud-kubernetes-configuration-watcher
- name: configuration-watcher
image: docker.io/springcloud/spring-cloud-kubernetes-configuration-watcher
imagePullPolicy: IfNotPresent
env:
@@ -22,7 +22,7 @@ spec:
- name: SPRING_RABBITMQ_HOST
value: rabbitmq-service
- name: SPRING_CLOUD_BUS_DESTINATION
value: multiple-apps
value: app
- name: SPRING_CLOUD_KUBERNETES_CONFIGURATION_WATCHER_REFRESHDELAY
value: "1"
readinessProbe:

View File

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

View File

@@ -0,0 +1,16 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: it-ingress
namespace: default
spec:
rules:
- http:
paths:
- path: /app
pathType: Prefix
backend:
service:
name: app
port:
number: 8080