diff --git a/spring-cloud-kubernetes-integration-tests/pom.xml b/spring-cloud-kubernetes-integration-tests/pom.xml
index 1a290e9d..b0a4cfb5 100644
--- a/spring-cloud-kubernetes-integration-tests/pom.xml
+++ b/spring-cloud-kubernetes-integration-tests/pom.xml
@@ -62,13 +62,12 @@
spring-cloud-kubernetes-configuration-watcher-it
spring-cloud-kubernetes-core-k8s-client-it
spring-cloud-kubernetes-client-secrets-event-reload
- spring-cloud-kubernetes-client-configmap-event-reload
+ spring-cloud-kubernetes-client-event-and-polling-reload
spring-cloud-kubernetes-client-configmap-event-reload-multiple-apps
spring-cloud-kubernetes-client-secrets-event-reload-multiple-apps
spring-cloud-kubernetes-fabric8-client-catalog-watcher
spring-cloud-kubernetes-client-catalog-watcher
spring-cloud-kubernetes-client-discovery-it
spring-cloud-kubernetes-fabric8-client-discovery-with-bootstrap
- spring-cloud-kubernetes-client-configmap-polling-reload
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/pom.xml
deleted file mode 100644
index 8537ed58..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/pom.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-
-
-
- spring-cloud-kubernetes-integration-tests
- org.springframework.cloud
- 3.1.0-SNAPSHOT
-
- 4.0.0
-
- spring-cloud-kubernetes-client-configmap-event-reload
-
-
-
- org.springframework.cloud
- spring-cloud-starter-kubernetes-client-config
-
-
- org.springframework.boot
- spring-boot-starter-webflux
-
-
- org.springframework.boot
- spring-boot-starter-actuator
-
-
- org.springframework.cloud
- spring-cloud-starter-bootstrap
-
-
-
- org.springframework.cloud
- spring-cloud-kubernetes-test-support
-
-
-
-
-
-
-
- ../src/main/resources
- true
-
-
- src/main/resources
- true
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
- docker.io/springcloud/${project.artifactId}:${project.version}
-
-
-
- build-image
-
- ${skip.build.image}
-
- package
-
- build-image
-
-
-
- repackage
- package
-
- repackage
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
- true
-
-
-
-
-
- org.apache.maven.plugins
- maven-failsafe-plugin
-
-
-
- integration-test
-
-
-
-
-
- ${testsToRun}
-
-
-
-
-
-
-
-
-
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/service.yaml
deleted file mode 100644
index 096e2130..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/service.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- labels:
- app: spring-cloud-kubernetes-client-configmap-event-reload
- name: spring-cloud-kubernetes-client-configmap-event-reload
-spec:
- ports:
- - name: http
- port: 8080
- targetPort: 8080
- selector:
- app: spring-cloud-kubernetes-client-configmap-event-reload
- type: ClusterIP
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/ConfigMapApp.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/ConfigMapApp.java
deleted file mode 100644
index 08f70657..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/ConfigMapApp.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2013-2023 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.configmap.polling.reload;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-
-/**
- * @author wind57
- */
-
-@SpringBootApplication
-@EnableConfigurationProperties(ConfigMapProperties.class)
-public class ConfigMapApp {
-
- public static void main(String[] args) {
- SpringApplication.run(ConfigMapApp.class, args);
- }
-
-}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/ConfigMapController.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/ConfigMapController.java
deleted file mode 100644
index 7d8cbedf..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/ConfigMapController.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2013-2023 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.configmap.polling.reload;
-
-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("/key")
- public String key() {
- return properties.getKey();
- }
-
-}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/BootstrapEnabledPollingReloadConfigMapMountIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/BootstrapEnabledPollingReloadConfigMapMountIT.java
deleted file mode 100644
index 091179ee..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/BootstrapEnabledPollingReloadConfigMapMountIT.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright 2013-2023 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.configmap.polling.reload;
-
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-
-import io.kubernetes.client.openapi.apis.CoreV1Api;
-import io.kubernetes.client.openapi.models.V1ConfigMap;
-import io.kubernetes.client.openapi.models.V1Deployment;
-import io.kubernetes.client.openapi.models.V1EnvVar;
-import io.kubernetes.client.openapi.models.V1Ingress;
-import io.kubernetes.client.openapi.models.V1Service;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.testcontainers.containers.Container;
-import org.testcontainers.k3s.K3sContainer;
-import reactor.netty.http.client.HttpClient;
-import reactor.util.retry.Retry;
-import reactor.util.retry.RetryBackoffSpec;
-
-import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
-import org.springframework.cloud.kubernetes.integration.tests.commons.Phase;
-import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.client.reactive.ReactorClientHttpConnector;
-import org.springframework.web.reactive.function.client.WebClient;
-
-import static org.awaitility.Awaitility.await;
-
-/**
- * @author wind57
- */
-class BootstrapEnabledPollingReloadConfigMapMountIT {
-
- private static final String IMAGE_NAME = "spring-cloud-kubernetes-client-configmap-polling-reload";
-
- private static final String NAMESPACE = "default";
-
- private static Util util;
-
- private static CoreV1Api coreV1Api;
-
- private static final K3sContainer K3S = Commons.container();
-
- @BeforeAll
- static void beforeAll() throws Exception {
- K3S.start();
- Commons.validateImage(IMAGE_NAME, K3S);
- Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S);
- util = new Util(K3S);
- coreV1Api = new CoreV1Api();
- util.setUp(NAMESPACE);
- manifests(Phase.CREATE);
- }
-
- @AfterAll
- static void after() throws Exception {
- manifests(Phase.DELETE);
- Commons.cleanUp(IMAGE_NAME, K3S);
- Commons.systemPrune();
- }
-
- /**
- *
- * - we have bootstrap enabled, which means we will 'locate' property sources
- * from config maps.
- * - there are no explicit config maps to search for, but what we will also read,
- * is 'spring.cloud.kubernetes.config.paths', which we have set to
- * '/tmp/application.properties'
- * in this test. That is populated by the volumeMounts (see deployment-mount.yaml)
- * - we first assert that we are actually reading the path based source via (1), (2) and (3).
- *
- * - we then change the config map content, wait for k8s to pick it up and replace them
- * - our polling will then detect that change, and trigger a reload.
- *
- */
- @Test
- void test() throws Exception {
- String logs = logs();
- // (1)
- Assertions.assertTrue(logs.contains("paths property sources : [/tmp/application.properties]"));
- // (2)
- Assertions.assertTrue(logs.contains("will add file-based property source : /tmp/application.properties"));
- // (3)
- WebClient webClient = builder().baseUrl("http://localhost/key").build();
- String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
- .block();
-
- // we first read the initial value from the configmap
- Assertions.assertEquals("as-mount-initial", result);
-
- // replace data in configmap and wait for k8s to pick it up
- // our polling will detect that and restart the app
- V1ConfigMap configMap = (V1ConfigMap) util.yaml("configmap-mount.yaml");
- configMap.setData(Map.of("application.properties", "from.properties.key=as-mount-changed"));
- coreV1Api.replaceNamespacedConfigMap("poll-reload-as-mount", NAMESPACE, configMap, null, null, null, null);
-
- await().timeout(Duration.ofSeconds(180)).until(() -> webClient.method(HttpMethod.GET).retrieve()
- .bodyToMono(String.class).retryWhen(retrySpec()).block().equals("as-mount-changed"));
-
- }
-
- private static void manifests(Phase phase) {
-
- V1Deployment deployment = (V1Deployment) util.yaml("deployment-mount.yaml");
- V1Service service = (V1Service) util.yaml("service.yaml");
- V1Ingress ingress = (V1Ingress) util.yaml("ingress.yaml");
- V1ConfigMap configMap = (V1ConfigMap) util.yaml("configmap-mount.yaml");
-
- List existing = new ArrayList<>(
- Optional.ofNullable(deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv())
- .orElse(new ArrayList<>()));
-
- // bootstrap is enabled, which means that in 'application-with-bootstrap.yaml',
- // config-data support is disabled.
- V1EnvVar mountActiveProfile = new V1EnvVar().name("SPRING_PROFILES_ACTIVE").value("with-bootstrap");
- V1EnvVar disableBootstrap = new V1EnvVar().name("SPRING_CLOUD_BOOTSTRAP_ENABLED").value("TRUE");
-
- V1EnvVar debugLevelReloadCommons = new V1EnvVar()
- .name("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS_CONFIG_RELOAD").value("DEBUG");
- V1EnvVar debugLevelConfig = new V1EnvVar()
- .name("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS_CONFIG").value("DEBUG");
- V1EnvVar debugLevelCommons = new V1EnvVar().name("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS")
- .value("DEBUG");
-
- existing.add(mountActiveProfile);
- existing.add(disableBootstrap);
- existing.add(debugLevelReloadCommons);
- existing.add(debugLevelCommons);
- existing.add(debugLevelConfig);
- deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(existing);
-
- if (phase.equals(Phase.CREATE)) {
- util.createAndWait(NAMESPACE, configMap, null);
- util.createAndWait(NAMESPACE, null, deployment, service, ingress, true);
- }
- else {
- util.deleteAndWait(NAMESPACE, configMap, null);
- util.deleteAndWait(NAMESPACE, deployment, service, ingress);
- }
-
- }
-
- private WebClient.Builder builder() {
- return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
- }
-
- private RetryBackoffSpec retrySpec() {
- return Retry.fixedDelay(60, Duration.ofSeconds(1)).filter(Objects::nonNull);
- }
-
- private String logs() {
- try {
- String appPodName = K3S.execInContainer("sh", "-c",
- "kubectl get pods -l app=" + IMAGE_NAME + " -o=name --no-headers | tr -d '\n'").getStdout();
-
- Container.ExecResult execResult = K3S.execInContainer("sh", "-c", "kubectl logs " + appPodName.trim());
- return execResult.getStdout();
- }
- catch (Exception e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- }
- }
-
-}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/PollingReloadConfigMapMountIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/PollingReloadConfigMapMountIT.java
deleted file mode 100644
index 34c9e4f4..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/PollingReloadConfigMapMountIT.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright 2013-2023 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.configmap.polling.reload;
-
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-
-import io.kubernetes.client.openapi.apis.CoreV1Api;
-import io.kubernetes.client.openapi.models.V1ConfigMap;
-import io.kubernetes.client.openapi.models.V1Deployment;
-import io.kubernetes.client.openapi.models.V1EnvVar;
-import io.kubernetes.client.openapi.models.V1Ingress;
-import io.kubernetes.client.openapi.models.V1Service;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.testcontainers.containers.Container;
-import org.testcontainers.k3s.K3sContainer;
-import reactor.netty.http.client.HttpClient;
-import reactor.util.retry.Retry;
-import reactor.util.retry.RetryBackoffSpec;
-
-import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
-import org.springframework.cloud.kubernetes.integration.tests.commons.Phase;
-import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.client.reactive.ReactorClientHttpConnector;
-import org.springframework.web.reactive.function.client.WebClient;
-
-import static org.awaitility.Awaitility.await;
-
-/**
- * @author wind57
- */
-class PollingReloadConfigMapMountIT {
-
- private static final String IMAGE_NAME = "spring-cloud-kubernetes-client-configmap-polling-reload";
-
- private static final String NAMESPACE = "default";
-
- private static Util util;
-
- private static CoreV1Api coreV1Api;
-
- private static final K3sContainer K3S = Commons.container();
-
- @BeforeAll
- static void beforeAll() throws Exception {
- K3S.start();
- Commons.validateImage(IMAGE_NAME, K3S);
- Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S);
- util = new Util(K3S);
- coreV1Api = new CoreV1Api();
- util.setUp(NAMESPACE);
- manifests(Phase.CREATE);
- }
-
- @AfterAll
- static void after() throws Exception {
- manifests(Phase.DELETE);
- Commons.cleanUp(IMAGE_NAME, K3S);
- Commons.systemPrune();
- }
-
- /**
- *
- * - we have "spring.config.import: kubernetes", which means we will 'locate' property sources
- * from config maps.
- * - the property above means that at the moment we will be searching for config maps that only
- * match the application name, in this specific test there is no such config map.
- * - what we will also read, is 'spring.cloud.kubernetes.config.paths', which we have set to
- * '/tmp/application.properties'
- * in this test. That is populated by the volumeMounts (see deployment-mount.yaml)
- * - we first assert that we are actually reading the path based source via (1), (2) and (3).
- *
- * - we then change the config map content, wait for k8s to pick it up and replace them
- * - our polling will then detect that change, and trigger a reload.
- *
- */
- @Test
- void test() throws Exception {
- String logs = logs();
- // (1)
- Assertions.assertTrue(logs.contains("paths property sources : [/tmp/application.properties]"));
- // (2)
- Assertions.assertTrue(logs.contains("will add file-based property source : /tmp/application.properties"));
- // (3)
- WebClient webClient = builder().baseUrl("http://localhost/key").build();
- String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
- .block();
-
- // we first read the initial value from the configmap
- Assertions.assertEquals("as-mount-initial", result);
-
- // replace data in configmap and wait for k8s to pick it up
- // our polling will detect that and restart the app
- V1ConfigMap configMap = (V1ConfigMap) util.yaml("configmap-mount.yaml");
- configMap.setData(Map.of("application.properties", "from.properties.key=as-mount-changed"));
- coreV1Api.replaceNamespacedConfigMap("poll-reload-as-mount", NAMESPACE, configMap, null, null, null, null);
-
- await().timeout(Duration.ofSeconds(180)).until(() -> webClient.method(HttpMethod.GET).retrieve()
- .bodyToMono(String.class).retryWhen(retrySpec()).block().equals("as-mount-changed"));
-
- }
-
- private static void manifests(Phase phase) {
-
- V1Deployment deployment = (V1Deployment) util.yaml("deployment-mount.yaml");
- V1Service service = (V1Service) util.yaml("service.yaml");
- V1Ingress ingress = (V1Ingress) util.yaml("ingress.yaml");
- V1ConfigMap configMap = (V1ConfigMap) util.yaml("configmap-mount.yaml");
-
- List existing = new ArrayList<>(
- Optional.ofNullable(deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv())
- .orElse(new ArrayList<>()));
-
- // bootstrap is disabled, which means that in 'application-mount.yaml',
- // config-data support is enabled.
- V1EnvVar mountActiveProfile = new V1EnvVar().name("SPRING_PROFILES_ACTIVE").value("mount");
- V1EnvVar disableBootstrap = new V1EnvVar().name("SPRING_CLOUD_BOOTSTRAP_ENABLED").value("FALSE");
-
- V1EnvVar debugLevelReloadCommons = new V1EnvVar()
- .name("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS_CONFIG_RELOAD").value("DEBUG");
- V1EnvVar debugLevelConfig = new V1EnvVar()
- .name("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS_CONFIG").value("DEBUG");
- V1EnvVar debugLevelCommons = new V1EnvVar().name("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS")
- .value("DEBUG");
-
- existing.add(mountActiveProfile);
- existing.add(disableBootstrap);
- existing.add(debugLevelReloadCommons);
- existing.add(debugLevelCommons);
- existing.add(debugLevelConfig);
- deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(existing);
-
- if (phase.equals(Phase.CREATE)) {
- util.createAndWait(NAMESPACE, configMap, null);
- util.createAndWait(NAMESPACE, null, deployment, service, ingress, true);
- }
- else {
- util.deleteAndWait(NAMESPACE, configMap, null);
- util.deleteAndWait(NAMESPACE, deployment, service, ingress);
- }
-
- }
-
- private WebClient.Builder builder() {
- return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
- }
-
- private RetryBackoffSpec retrySpec() {
- return Retry.fixedDelay(60, Duration.ofSeconds(1)).filter(Objects::nonNull);
- }
-
- private String logs() {
- try {
- String appPodName = K3S.execInContainer("sh", "-c",
- "kubectl get pods -l app=" + IMAGE_NAME + " -o=name --no-headers | tr -d '\n'").getStdout();
-
- Container.ExecResult execResult = K3S.execInContainer("sh", "-c", "kubectl logs " + appPodName.trim());
- return execResult.getStdout();
- }
- catch (Exception e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- }
- }
-
-}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/deployment-mount.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/deployment-mount.yaml
deleted file mode 100644
index 9f3f4724..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/deployment-mount.yaml
+++ /dev/null
@@ -1,43 +0,0 @@
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: spring-cloud-kubernetes-client-configmap-deployment-polling-reload
-spec:
- selector:
- matchLabels:
- app: spring-cloud-kubernetes-client-configmap-polling-reload
- template:
- metadata:
- labels:
- app: spring-cloud-kubernetes-client-configmap-polling-reload
- spec:
- serviceAccountName: spring-cloud-kubernetes-serviceaccount
- containers:
- - name: spring-cloud-kubernetes-client-configmap-polling-reload
- image: docker.io/springcloud/spring-cloud-kubernetes-client-configmap-polling-reload
- imagePullPolicy: IfNotPresent
- readinessProbe:
- httpGet:
- port: 8080
- path: /actuator/health/readiness
- initialDelaySeconds: 10
- periodSeconds: 2
- failureThreshold: 3
- livenessProbe:
- httpGet:
- port: 8080
- path: /actuator/health/liveness
- initialDelaySeconds: 10
- periodSeconds: 2
- failureThreshold: 3
- ports:
- - containerPort: 8080
-
- volumeMounts:
- - name: config-map-volume
- mountPath: /tmp
-
- volumes:
- - name: config-map-volume
- configMap:
- name: poll-reload-as-mount
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/ingress.yaml
deleted file mode 100644
index 64f5bf4c..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/ingress.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: spring-cloud-kubernetes-client-configmap-ingress-polling-reload
- namespace: default
-spec:
- rules:
- - http:
- paths:
- - path: /
- pathType: Prefix
- backend:
- service:
- name: spring-cloud-kubernetes-client-configmap-polling-reload
- port:
- number: 8080
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/logback-test.xml
deleted file mode 100644
index ee243343..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
- %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
-
-
-
-
-
-
-
-
-
-
-
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/service.yaml
deleted file mode 100644
index 19d5acda..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/service.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- labels:
- app: spring-cloud-kubernetes-client-configmap-polling-reload
- name: spring-cloud-kubernetes-client-configmap-polling-reload
-spec:
- ports:
- - name: http
- port: 8080
- targetPort: 8080
- selector:
- app: spring-cloud-kubernetes-client-configmap-polling-reload
- type: ClusterIP
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/pom.xml
similarity index 98%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/pom.xml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/pom.xml
index cbcb9b0a..952f0cd5 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/pom.xml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/pom.xml
@@ -9,7 +9,7 @@
3.1.0-SNAPSHOT
- spring-cloud-kubernetes-client-configmap-polling-reload
+ spring-cloud-kubernetes-client-event-and-polling-reload
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/App.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/App.java
similarity index 87%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/App.java
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/App.java
index 8cb37a95..f8ea374d 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/App.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/App.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.client.configmap.event.reload;
+package org.springframework.cloud.kubernetes.client.configmap.reload;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -24,7 +24,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
* @author wind57
*/
@SpringBootApplication
-@EnableConfigurationProperties({ LeftProperties.class, RightProperties.class, RightWithLabelsProperties.class })
+@EnableConfigurationProperties({ LeftProperties.class, RightProperties.class, RightWithLabelsProperties.class,
+ ConfigMapProperties.class })
public class App {
public static void main(String[] args) {
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/ConfigMapProperties.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/ConfigMapProperties.java
similarity index 92%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/ConfigMapProperties.java
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/ConfigMapProperties.java
index c4c11b43..224773de 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/polling/reload/ConfigMapProperties.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/ConfigMapProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.client.configmap.polling.reload;
+package org.springframework.cloud.kubernetes.client.configmap.reload;
import org.springframework.boot.context.properties.ConfigurationProperties;
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/Controller.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/Controller.java
similarity index 80%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/Controller.java
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/Controller.java
index ae0b6cbd..dec721af 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/Controller.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/Controller.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.client.configmap.event.reload;
+package org.springframework.cloud.kubernetes.client.configmap.reload;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -31,11 +31,14 @@ public class Controller {
private final RightWithLabelsProperties rightWithLabelsProperties;
+ private final ConfigMapProperties configMapProperties;
+
public Controller(LeftProperties leftProperties, RightProperties rightProperties,
- RightWithLabelsProperties rightWithLabelsProperties) {
+ RightWithLabelsProperties rightWithLabelsProperties, ConfigMapProperties configMapProperties) {
this.leftProperties = leftProperties;
this.rightProperties = rightProperties;
this.rightWithLabelsProperties = rightWithLabelsProperties;
+ this.configMapProperties = configMapProperties;
}
@GetMapping("/left")
@@ -53,4 +56,9 @@ public class Controller {
return rightWithLabelsProperties.getValue();
}
+ @GetMapping("/mount")
+ public String key() {
+ return configMapProperties.getKey();
+ }
+
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/LeftProperties.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/LeftProperties.java
similarity index 92%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/LeftProperties.java
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/LeftProperties.java
index 99a35713..fd7a7ef6 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/LeftProperties.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/LeftProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.client.configmap.event.reload;
+package org.springframework.cloud.kubernetes.client.configmap.reload;
import org.springframework.boot.context.properties.ConfigurationProperties;
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/RightProperties.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/RightProperties.java
similarity index 92%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/RightProperties.java
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/RightProperties.java
index 6987674e..52049303 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/RightProperties.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/RightProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.client.configmap.event.reload;
+package org.springframework.cloud.kubernetes.client.configmap.reload;
import org.springframework.boot.context.properties.ConfigurationProperties;
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/RightWithLabelsProperties.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/RightWithLabelsProperties.java
similarity index 92%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/RightWithLabelsProperties.java
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/RightWithLabelsProperties.java
index fc8e19dd..a7c519b2 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/RightWithLabelsProperties.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/reload/RightWithLabelsProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.client.configmap.event.reload;
+package org.springframework.cloud.kubernetes.client.configmap.reload;
import org.springframework.boot.context.properties.ConfigurationProperties;
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/resources/application-mount.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/application-mount.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/resources/application-mount.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/application-mount.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/resources/application-one.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/application-one.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/resources/application-one.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/application-one.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/resources/application-three.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/application-three.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/resources/application-three.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/application-three.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/resources/application-two.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/application-two.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/resources/application-two.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/application-two.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/resources/application-with-bootstrap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/application-with-bootstrap.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/resources/application-with-bootstrap.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/application-with-bootstrap.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/resources/bootstrap-one.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/bootstrap-one.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/resources/bootstrap-one.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/bootstrap-one.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/resources/bootstrap-three.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/bootstrap-three.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/resources/bootstrap-three.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/bootstrap-three.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/resources/bootstrap-two.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/bootstrap-two.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/main/resources/bootstrap-two.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/bootstrap-two.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/resources/bootstrap-with-bootstrap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/bootstrap-with-bootstrap.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/main/resources/bootstrap-with-bootstrap.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/main/resources/bootstrap-with-bootstrap.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/BootstrapEnabledPollingReloadConfigMapMountDelegate.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/BootstrapEnabledPollingReloadConfigMapMountDelegate.java
new file mode 100644
index 00000000..f82fe5b3
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/BootstrapEnabledPollingReloadConfigMapMountDelegate.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2013-2023 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.configmap.reload;
+
+import java.time.Duration;
+import java.util.Map;
+
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1ConfigMap;
+import org.junit.jupiter.api.Assertions;
+import org.testcontainers.k3s.K3sContainer;
+
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
+import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util;
+import org.springframework.http.HttpMethod;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import static org.awaitility.Awaitility.await;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.builder;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.patchSix;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.retrySpec;
+
+/**
+ * @author wind57
+ */
+final class BootstrapEnabledPollingReloadConfigMapMountDelegate {
+
+ private static final String NAMESPACE = "default";
+
+ /**
+ *
+ * - we have bootstrap enabled, which means we will 'locate' property sources
+ * from config maps.
+ * - there are no explicit config maps to search for, but what we will also read,
+ * is 'spring.cloud.kubernetes.config.paths', which we have set to
+ * '/tmp/application.properties'
+ * in this test. That is populated by the volumeMounts (see deployment-mount.yaml)
+ * - we first assert that we are actually reading the path based source via (1), (2) and (3).
+ *
+ * - we then change the config map content, wait for k8s to pick it up and replace them
+ * - our polling will then detect that change, and trigger a reload.
+ *
+ */
+ static void testBootstrapEnabledPollingReloadConfigMapMount(String deploymentName, K3sContainer k3sContainer,
+ Util util, String imageName) throws Exception {
+
+ recreateMountConfigMap(util);
+ patchSix(deploymentName, "default", imageName);
+
+ // (1)
+ Commons.waitForLogStatement("paths property sources : [/tmp/application.properties]", k3sContainer,
+ deploymentName);
+
+ // (2)
+ Commons.waitForLogStatement("will add file-based property source : /tmp/application.properties", k3sContainer,
+ deploymentName);
+
+ // (3)
+ WebClient webClient = builder().baseUrl("http://localhost/mount").build();
+ String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
+ .block();
+
+ // we first read the initial value from the configmap
+ Assertions.assertEquals("as-mount-initial", result);
+
+ // replace data in configmap and wait for k8s to pick it up
+ // our polling will detect that and restart the app
+ V1ConfigMap configMap = (V1ConfigMap) util.yaml("configmap-mount.yaml");
+ configMap.setData(Map.of("application.properties", "from.properties.key=as-mount-changed"));
+ new CoreV1Api().replaceNamespacedConfigMap("poll-reload-as-mount", NAMESPACE, configMap, null, null, null,
+ null);
+
+ await().timeout(Duration.ofSeconds(180)).until(() -> webClient.method(HttpMethod.GET).retrieve()
+ .bodyToMono(String.class).retryWhen(retrySpec()).block().equals("as-mount-changed"));
+
+ }
+
+ private static void recreateMountConfigMap(Util util) {
+ V1ConfigMap mountConfigMap = (V1ConfigMap) util.yaml("configmap-mount.yaml");
+
+ util.deleteAndWait("default", mountConfigMap, null);
+ util.createAndWait("default", mountConfigMap, null);
+ }
+
+}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/DataChangesInConfigMapReloadDelegate.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/DataChangesInConfigMapReloadDelegate.java
similarity index 73%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/DataChangesInConfigMapReloadDelegate.java
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/DataChangesInConfigMapReloadDelegate.java
index b23e2961..d4fc12ae 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/DataChangesInConfigMapReloadDelegate.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/DataChangesInConfigMapReloadDelegate.java
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.client.configmap.event.reload;
+package org.springframework.cloud.kubernetes.client.configmap.reload;
import java.time.Duration;
import java.util.Map;
-import java.util.Objects;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.apis.CoreV1Api;
@@ -26,30 +25,27 @@ import io.kubernetes.client.openapi.models.V1ConfigMap;
import io.kubernetes.client.openapi.models.V1ConfigMapBuilder;
import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder;
import org.junit.jupiter.api.Assertions;
-import org.testcontainers.containers.Container;
import org.testcontainers.k3s.K3sContainer;
-import reactor.netty.http.client.HttpClient;
-import reactor.util.retry.Retry;
-import reactor.util.retry.RetryBackoffSpec;
import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
import org.springframework.http.HttpMethod;
-import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import static org.awaitility.Awaitility.await;
-import static org.springframework.cloud.kubernetes.client.configmap.event.reload.ConfigMapEventReloadITUtil.patchFour;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.builder;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.logs;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.patchFour;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.retrySpec;
-class DataChangesInConfigMapReloadDelegate {
-
- private static final String IMAGE_NAME = "spring-cloud-kubernetes-client-configmap-event-reload";
+/**
+ * @author wind57
+ */
+final class DataChangesInConfigMapReloadDelegate {
private static final String NAMESPACE = "default";
private static final String LEFT_NAMESPACE = "left";
- private static final K3sContainer K3S = Commons.container();
-
/**
*
* - configMap with no labels and data: left.value = left-initial exists in namespace left
@@ -61,11 +57,11 @@ class DataChangesInConfigMapReloadDelegate {
* - then we change data inside the config map, and we must see the updated value
*
*/
- static void testSimple(String dockerImage) {
+ static void testSimple(String dockerImage, String deploymentName, K3sContainer k3sContainer) {
- patchFour("spring-cloud-kubernetes-client-configmap-deployment-event-reload", NAMESPACE, dockerImage);
+ patchFour(deploymentName, NAMESPACE, dockerImage);
Commons.assertReloadLogStatements("added configmap informer for namespace",
- "added secret informer for namespace", IMAGE_NAME);
+ "added secret informer for namespace", deploymentName);
WebClient webClient = builder().baseUrl("http://localhost/" + LEFT_NAMESPACE).build();
String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
@@ -89,7 +85,7 @@ class DataChangesInConfigMapReloadDelegate {
return "left-initial".equals(innerResult);
});
- String logs = logs();
+ String logs = logs(deploymentName, k3sContainer);
Assertions.assertTrue(logs.contains("ConfigMap left-configmap was updated in namespace left"));
Assertions.assertTrue(logs.contains("data in configmap has not changed, will not reload"));
@@ -110,28 +106,6 @@ class DataChangesInConfigMapReloadDelegate {
}
- private static String logs() {
- try {
- String appPodName = K3S.execInContainer("sh", "-c",
- "kubectl get pods -l app=" + IMAGE_NAME + " -o=name --no-headers | tr -d '\n'").getStdout();
-
- Container.ExecResult execResult = K3S.execInContainer("sh", "-c", "kubectl logs " + appPodName.trim());
- return execResult.getStdout();
- }
- catch (Exception e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- }
- }
-
- private static WebClient.Builder builder() {
- return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
- }
-
- private static RetryBackoffSpec retrySpec() {
- return Retry.fixedDelay(120, Duration.ofSeconds(2)).filter(Objects::nonNull);
- }
-
private static void replaceConfigMap(V1ConfigMap configMap) {
try {
new CoreV1Api().replaceNamespacedConfigMap("left-configmap", LEFT_NAMESPACE, configMap, null, null, null,
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/ConfigMapEventReloadIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/K8sClientConfigMapReloadIT.java
similarity index 86%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/ConfigMapEventReloadIT.java
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/K8sClientConfigMapReloadIT.java
index c61cd821..903b1182 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/ConfigMapEventReloadIT.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/K8sClientConfigMapReloadIT.java
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.client.configmap.event.reload;
+package org.springframework.cloud.kubernetes.client.configmap.reload;
import java.time.Duration;
import java.util.Map;
-import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
@@ -36,29 +35,31 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.testcontainers.k3s.K3sContainer;
-import reactor.netty.http.client.HttpClient;
-import reactor.util.retry.Retry;
-import reactor.util.retry.RetryBackoffSpec;
import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
import org.springframework.cloud.kubernetes.integration.tests.commons.Phase;
import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util;
import org.springframework.http.HttpMethod;
-import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import static org.awaitility.Awaitility.await;
-import static org.springframework.cloud.kubernetes.client.configmap.event.reload.ConfigMapEventReloadITUtil.patchOne;
-import static org.springframework.cloud.kubernetes.client.configmap.event.reload.ConfigMapEventReloadITUtil.patchThree;
-import static org.springframework.cloud.kubernetes.client.configmap.event.reload.ConfigMapEventReloadITUtil.patchTwo;
-import static org.springframework.cloud.kubernetes.client.configmap.event.reload.DataChangesInConfigMapReloadDelegate.testSimple;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.BootstrapEnabledPollingReloadConfigMapMountDelegate.testBootstrapEnabledPollingReloadConfigMapMount;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.DataChangesInConfigMapReloadDelegate.testSimple;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.builder;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.patchOne;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.patchThree;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.patchTwo;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.retrySpec;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.PollingReloadConfigMapMountDelegate.testPollingReloadConfigMapMount;
/**
* @author wind57
*/
-class ConfigMapEventReloadIT {
+class K8sClientConfigMapReloadIT {
- private static final String IMAGE_NAME = "spring-cloud-kubernetes-client-configmap-event-reload";
+ private static final String IMAGE_NAME = "spring-cloud-kubernetes-client-event-and-polling-reload";
+
+ private static final String DEPLOYMENT_NAME = "spring-k8s-client-reload";
private static final String DOCKER_IMAGE = "docker.io/springcloud/" + IMAGE_NAME + ":" + Commons.pomVersion();
@@ -79,6 +80,7 @@ class ConfigMapEventReloadIT {
util.createNamespace("left");
util.createNamespace("right");
util.setUpClusterWide(NAMESPACE, Set.of("left", "right"));
+ util.setUp(NAMESPACE);
api = new CoreV1Api();
}
@@ -104,7 +106,7 @@ class ConfigMapEventReloadIT {
void testInformFromOneNamespaceEventNotTriggered() throws Exception {
manifests(Phase.CREATE);
Commons.assertReloadLogStatements("added configmap informer for namespace",
- "added secret informer for namespace", IMAGE_NAME);
+ "added secret informer for namespace", "spring-k8s-client-reload");
WebClient webClient = builder().baseUrl("http://localhost/left").build();
String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
@@ -133,10 +135,19 @@ class ConfigMapEventReloadIT {
// left configmap has not changed, no restart of app has happened
Assertions.assertEquals("left-initial", result);
+ testAllOther();
+
+ }
+
+ // since we patch each deployment with "replace" strategy, any of the above can be
+ // commented out and debugged individually.
+ private void testAllOther() throws Exception {
testInformFromOneNamespaceEventTriggered();
testInform();
testInformFromOneNamespaceEventTriggeredSecretsDisabled();
- testSimple(DOCKER_IMAGE);
+ testSimple(DOCKER_IMAGE, DEPLOYMENT_NAME, K3S);
+ testPollingReloadConfigMapMount(DEPLOYMENT_NAME, K3S, util, DOCKER_IMAGE);
+ testBootstrapEnabledPollingReloadConfigMapMount(DEPLOYMENT_NAME, K3S, util, DOCKER_IMAGE);
}
@@ -150,9 +161,9 @@ class ConfigMapEventReloadIT {
*/
void testInformFromOneNamespaceEventTriggered() throws Exception {
recreateConfigMaps();
- patchOne("spring-cloud-kubernetes-client-configmap-deployment-event-reload", NAMESPACE, DOCKER_IMAGE);
+ patchOne(DEPLOYMENT_NAME, NAMESPACE, DOCKER_IMAGE);
Commons.assertReloadLogStatements("added configmap informer for namespace",
- "added secret informer for namespace", IMAGE_NAME);
+ "added secret informer for namespace", DEPLOYMENT_NAME);
// read the value from the right-configmap
WebClient webClient = builder().baseUrl("http://localhost/right").build();
@@ -192,10 +203,10 @@ class ConfigMapEventReloadIT {
recreateConfigMaps();
V1ConfigMap rightWithLabelConfigMap = (V1ConfigMap) util.yaml("right-configmap-with-label.yaml");
util.createAndWait("right", rightWithLabelConfigMap, null);
- patchTwo("spring-cloud-kubernetes-client-configmap-deployment-event-reload", NAMESPACE, DOCKER_IMAGE);
+ patchTwo(DEPLOYMENT_NAME, NAMESPACE, DOCKER_IMAGE);
Commons.assertReloadLogStatements("added configmap informer for namespace",
- "added secret informer for namespace", IMAGE_NAME);
+ "added secret informer for namespace", DEPLOYMENT_NAME);
// read the initial value from the right-configmap
WebClient rightWebClient = builder().baseUrl("http://localhost/right").build();
@@ -261,9 +272,9 @@ class ConfigMapEventReloadIT {
*/
void testInformFromOneNamespaceEventTriggeredSecretsDisabled() throws Exception {
recreateConfigMaps();
- patchThree("spring-cloud-kubernetes-client-configmap-deployment-event-reload", NAMESPACE, DOCKER_IMAGE);
+ patchThree(DEPLOYMENT_NAME, NAMESPACE, DOCKER_IMAGE);
Commons.assertReloadLogStatements("added configmap informer for namespace",
- "added secret informer for namespace", IMAGE_NAME);
+ "added secret informer for namespace", DEPLOYMENT_NAME);
// read the value from the right-configmap
WebClient webClient = builder().baseUrl("http://localhost/right").build();
@@ -307,18 +318,21 @@ class ConfigMapEventReloadIT {
V1ConfigMap leftConfigMap = (V1ConfigMap) util.yaml("left-configmap.yaml");
V1ConfigMap rightConfigMap = (V1ConfigMap) util.yaml("right-configmap.yaml");
+ V1ConfigMap mountConfigMap = (V1ConfigMap) util.yaml("configmap-mount.yaml");
V1Deployment deployment = (V1Deployment) util.yaml("deployment.yaml");
V1Service service = (V1Service) util.yaml("service.yaml");
V1Ingress ingress = (V1Ingress) util.yaml("ingress.yaml");
if (phase.equals(Phase.CREATE)) {
+ util.createAndWait(NAMESPACE, mountConfigMap, null);
util.createAndWait("left", leftConfigMap, null);
util.createAndWait("right", rightConfigMap, null);
util.createAndWait(NAMESPACE, null, deployment, service, ingress, true);
}
if (phase.equals(Phase.DELETE)) {
+ util.deleteAndWait(NAMESPACE, mountConfigMap, null);
util.deleteAndWait("left", leftConfigMap, null);
util.deleteAndWait("right", rightConfigMap, null);
util.deleteAndWait(NAMESPACE, deployment, service, ingress);
@@ -331,14 +345,6 @@ class ConfigMapEventReloadIT {
}
- private WebClient.Builder builder() {
- return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
- }
-
- private RetryBackoffSpec retrySpec() {
- return Retry.fixedDelay(120, Duration.ofSeconds(1)).filter(Objects::nonNull);
- }
-
private static void replaceConfigMap(V1ConfigMap configMap, String name) throws ApiException {
api.replaceNamespacedConfigMap(name, "right", configMap, null, null, null, null);
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/ConfigMapEventReloadITUtil.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/K8sClientReloadITUtil.java
similarity index 50%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/ConfigMapEventReloadITUtil.java
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/K8sClientReloadITUtil.java
index 7d16ae06..8922dd82 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/event/reload/ConfigMapEventReloadITUtil.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/K8sClientReloadITUtil.java
@@ -14,21 +14,31 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.client.configmap.event.reload;
+package org.springframework.cloud.kubernetes.client.configmap.reload;
+import java.time.Duration;
import java.util.Map;
+import java.util.Objects;
+
+import org.testcontainers.containers.Container;
+import org.testcontainers.k3s.K3sContainer;
+import reactor.netty.http.client.HttpClient;
+import reactor.util.retry.Retry;
+import reactor.util.retry.RetryBackoffSpec;
+
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.web.reactive.function.client.WebClient;
import static org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util.patchWithReplace;
/**
* @author wind57
*/
-final class ConfigMapEventReloadITUtil {
+final class K8sClientReloadITUtil {
- private static final Map POD_LABELS = Map.of("app",
- "spring-cloud-kubernetes-client-configmap-event-reload");
+ private static final Map POD_LABELS = Map.of("app", "spring-k8s-client-reload");
- private ConfigMapEventReloadITUtil() {
+ private K8sClientReloadITUtil() {
}
@@ -38,7 +48,7 @@ final class ConfigMapEventReloadITUtil {
"template": {
"spec": {
"containers": [{
- "name": "spring-cloud-kubernetes-client-configmap-event-reload",
+ "name": "spring-k8s-client-reload",
"image": "image_name_here",
"livenessProbe": {
"failureThreshold": 3,
@@ -70,6 +80,10 @@ final class ConfigMapEventReloadITUtil {
{
"name": "LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD",
"value": "DEBUG"
+ },
+ {
+ "name": "SPRING_CLOUD_BOOTSTRAP_ENABLED",
+ "value": "TRUE"
}
]
}]
@@ -85,7 +99,7 @@ final class ConfigMapEventReloadITUtil {
"template": {
"spec": {
"containers": [{
- "name": "spring-cloud-kubernetes-client-configmap-event-reload",
+ "name": "spring-k8s-client-reload",
"image": "image_name_here",
"livenessProbe": {
"failureThreshold": 3,
@@ -117,6 +131,10 @@ final class ConfigMapEventReloadITUtil {
{
"name": "LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD",
"value": "DEBUG"
+ },
+ {
+ "name": "SPRING_CLOUD_BOOTSTRAP_ENABLED",
+ "value": "TRUE"
}
]
}]
@@ -132,7 +150,7 @@ final class ConfigMapEventReloadITUtil {
"template": {
"spec": {
"containers": [{
- "name": "spring-cloud-kubernetes-client-configmap-event-reload",
+ "name": "spring-k8s-client-reload",
"image": "image_name_here",
"livenessProbe": {
"failureThreshold": 3,
@@ -168,6 +186,10 @@ final class ConfigMapEventReloadITUtil {
{
"name": "SPRING_CLOUD_KUBERNETES_SECRETS_ENABLED",
"value": "FALSE"
+ },
+ {
+ "name": "SPRING_CLOUD_BOOTSTRAP_ENABLED",
+ "value": "TRUE"
}
]
}]
@@ -183,10 +205,10 @@ final class ConfigMapEventReloadITUtil {
"template": {
"spec": {
"containers": [{
- "name": "spring-cloud-kubernetes-client-configmap-event-reload",
+ "name": "spring-k8s-client-reload",
"image": "image_name_here",
"livenessProbe": {
- "failureThreshold": 3,
+ "failureThreshold": 3,
"httpGet": {
"path": "/actuator/health/liveness",
"port": 8080,
@@ -219,6 +241,158 @@ final class ConfigMapEventReloadITUtil {
{
"name": "SPRING_CLOUD_KUBERNETES_SECRETS_ENABLED",
"value": "FALSE"
+ },
+ {
+ "name": "SPRING_CLOUD_BOOTSTRAP_ENABLED",
+ "value": "TRUE"
+ }
+ ]
+ }]
+ }
+ }
+ }
+ }
+ """;
+
+ private static final String BODY_FIVE = """
+ {
+ "spec": {
+ "template": {
+ "spec": {
+ "volumes": [
+ {
+ "configMap": {
+ "defaultMode": 420,
+ "name": "poll-reload-as-mount"
+ },
+ "name": "config-map-volume"
+ }
+ ],
+ "containers": [{
+ "name": "spring-k8s-client-reload",
+ "image": "image_name_here",
+ "volumeMounts": [
+ {
+ "mountPath": "/tmp",
+ "name": "config-map-volume"
+ }
+ ],
+ "livenessProbe": {
+ "failureThreshold": 3,
+ "httpGet": {
+ "path": "/actuator/health/liveness",
+ "port": 8080,
+ "scheme": "HTTP"
+ },
+ "periodSeconds": 10,
+ "successThreshold": 1,
+ "timeoutSeconds": 1
+ },
+ "readinessProbe": {
+ "failureThreshold": 3,
+ "httpGet": {
+ "path": "/actuator/health/readiness",
+ "port": 8080,
+ "scheme": "HTTP"
+ },
+ "periodSeconds": 10,
+ "successThreshold": 1,
+ "timeoutSeconds": 1
+ },
+ "env": [
+ {
+ "name": "SPRING_PROFILES_ACTIVE",
+ "value": "mount"
+ },
+ {
+ "name": "SPRING_CLOUD_BOOTSTRAP_ENABLED",
+ "value": "FALSE"
+ },
+ {
+ "name": "LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS_CONFIG_RELOAD",
+ "value": "DEBUG"
+ },
+ {
+ "name": "LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS_CONFIG",
+ "value": "DEBUG"
+ },
+ {
+ "name": "LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS",
+ "value": "DEBUG"
+ }
+ ]
+ }]
+ }
+ }
+ }
+ }
+ """;
+
+ private static final String BODY_SIX = """
+ {
+ "spec": {
+ "template": {
+ "spec": {
+ "volumes": [
+ {
+ "configMap": {
+ "defaultMode": 420,
+ "name": "poll-reload-as-mount"
+ },
+ "name": "config-map-volume"
+ }
+ ],
+ "containers": [{
+ "name": "spring-k8s-client-reload",
+ "image": "image_name_here",
+ "volumeMounts": [
+ {
+ "mountPath": "/tmp",
+ "name": "config-map-volume"
+ }
+ ],
+ "livenessProbe": {
+ "failureThreshold": 3,
+ "httpGet": {
+ "path": "/actuator/health/liveness",
+ "port": 8080,
+ "scheme": "HTTP"
+ },
+ "periodSeconds": 10,
+ "successThreshold": 1,
+ "timeoutSeconds": 1
+ },
+ "readinessProbe": {
+ "failureThreshold": 3,
+ "httpGet": {
+ "path": "/actuator/health/readiness",
+ "port": 8080,
+ "scheme": "HTTP"
+ },
+ "periodSeconds": 10,
+ "successThreshold": 1,
+ "timeoutSeconds": 1
+ },
+ "env": [
+ {
+ "name": "SPRING_PROFILES_ACTIVE",
+ "value": "with-bootstrap"
+ },
+ {
+ "name": "SPRING_CLOUD_BOOTSTRAP_ENABLED",
+ "value": "TRUE"
+ },
+ {
+ "name": "LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS_CONFIG_RELOAD",
+ "value": "DEBUG"
+ },
+ {
+ "name": "LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS_CONFIG",
+ "value": "DEBUG"
+ },
+ {
+ "name": "LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS",
+ "value": "DEBUG"
}
]
}]
@@ -244,4 +418,37 @@ final class ConfigMapEventReloadITUtil {
patchWithReplace(imageName, deploymentName, namespace, BODY_FOUR, POD_LABELS);
}
+ static void patchFive(String deploymentName, String namespace, String imageName) {
+ patchWithReplace(imageName, deploymentName, namespace, BODY_FIVE, POD_LABELS);
+ }
+
+ static void patchSix(String deploymentName, String namespace, String imageName) {
+ patchWithReplace(imageName, deploymentName, namespace, BODY_SIX, POD_LABELS);
+ }
+
+ static WebClient.Builder builder() {
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
+ }
+
+ static RetryBackoffSpec retrySpec() {
+ return Retry.fixedDelay(120, Duration.ofSeconds(1)).filter(Objects::nonNull);
+ }
+
+ static String logs(String appLabelValue, K3sContainer k3sContainer) {
+ try {
+ String appPodName = k3sContainer
+ .execInContainer("sh", "-c",
+ "kubectl get pods -l app=" + appLabelValue + " -o=name --no-headers | tr -d '\n'")
+ .getStdout();
+
+ Container.ExecResult execResult = k3sContainer.execInContainer("sh", "-c",
+ "kubectl logs " + appPodName.trim());
+ return execResult.getStdout();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/PollingReloadConfigMapMountDelegate.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/PollingReloadConfigMapMountDelegate.java
new file mode 100644
index 00000000..8bae0696
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/PollingReloadConfigMapMountDelegate.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2013-2023 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.configmap.reload;
+
+import java.time.Duration;
+import java.util.Map;
+
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1ConfigMap;
+import org.junit.jupiter.api.Assertions;
+import org.testcontainers.k3s.K3sContainer;
+
+import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
+import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util;
+import org.springframework.http.HttpMethod;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import static org.awaitility.Awaitility.await;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.builder;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.patchFive;
+import static org.springframework.cloud.kubernetes.client.configmap.reload.K8sClientReloadITUtil.retrySpec;
+
+/**
+ * @author wind57
+ */
+final class PollingReloadConfigMapMountDelegate {
+
+ private PollingReloadConfigMapMountDelegate() {
+
+ }
+
+ /**
+ *
+ * - we have "spring.config.import: kubernetes", which means we will 'locate' property sources
+ * from config maps.
+ * - the property above means that at the moment we will be searching for config maps that only
+ * match the application name, in this specific test there is no such config map.
+ * - what we will also read, is 'spring.cloud.kubernetes.config.paths', which we have set to
+ * '/tmp/application.properties'
+ * in this test. That is populated by the volumeMounts (see BODY_FIVE)
+ * - we first assert that we are actually reading the path based source via (1), (2) and (3).
+ *
+ * - we then change the config map content, wait for k8s to pick it up and replace them
+ * - our polling will then detect that change, and trigger a reload.
+ *
+ */
+ static void testPollingReloadConfigMapMount(String deploymentName, K3sContainer k3sContainer, Util util,
+ String imageName) throws Exception {
+
+ patchFive(deploymentName, "default", imageName);
+
+ // (1)
+ Commons.waitForLogStatement("paths property sources : [/tmp/application.properties]", k3sContainer,
+ deploymentName);
+
+ // (2)
+ Commons.waitForLogStatement("will add file-based property source : /tmp/application.properties", k3sContainer,
+ deploymentName);
+
+ // (3)
+ WebClient webClient = builder().baseUrl("http://localhost/mount").build();
+ String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
+ .block();
+
+ // we first read the initial value from the configmap
+ Assertions.assertEquals("as-mount-initial", result);
+
+ // replace data in configmap and wait for k8s to pick it up
+ // our polling will detect that and restart the app
+ V1ConfigMap configMap = (V1ConfigMap) util.yaml("configmap-mount.yaml");
+ configMap.setData(Map.of("application.properties", "from.properties.key=as-mount-changed"));
+ new CoreV1Api().replaceNamespacedConfigMap("poll-reload-as-mount", "default", configMap, null, null, null,
+ null);
+
+ await().timeout(Duration.ofSeconds(180)).until(() -> webClient.method(HttpMethod.GET).retrieve()
+ .bodyToMono(String.class).retryWhen(retrySpec()).block().equals("as-mount-changed"));
+
+ }
+
+}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/configmap-mount.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/configmap-mount.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/configmap-mount.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/configmap-mount.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/deployment.yaml
similarity index 72%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/deployment.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/deployment.yaml
index 81c754c2..80f242df 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/deployment.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/deployment.yaml
@@ -1,20 +1,20 @@
apiVersion: apps/v1
kind: Deployment
metadata:
- name: spring-cloud-kubernetes-client-configmap-deployment-event-reload
+ name: spring-k8s-client-reload
spec:
selector:
matchLabels:
- app: spring-cloud-kubernetes-client-configmap-event-reload
+ app: spring-k8s-client-reload
template:
metadata:
labels:
- app: spring-cloud-kubernetes-client-configmap-event-reload
+ app: spring-k8s-client-reload
spec:
serviceAccountName: spring-cloud-kubernetes-serviceaccount
containers:
- - name: spring-cloud-kubernetes-client-configmap-event-reload
- image: docker.io/springcloud/spring-cloud-kubernetes-client-configmap-event-reload
+ - name: spring-k8s-client-reload
+ image: docker.io/springcloud/spring-cloud-kubernetes-client-event-and-polling-reload
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
@@ -31,3 +31,5 @@ spec:
value: one
- name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD
value: DEBUG
+ - name: SPRING_CLOUD_BOOTSTRAP_ENABLED
+ value: "TRUE"
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/ingress.yaml
similarity index 64%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/ingress.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/ingress.yaml
index c571ad9a..4beef36c 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/ingress.yaml
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/ingress.yaml
@@ -1,7 +1,7 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
- name: spring-cloud-kubernetes-client-configmap-ingress-event-reload
+ name: spring-k8s-client-ingress-reload
namespace: default
spec:
rules:
@@ -11,6 +11,6 @@ spec:
pathType: Prefix
backend:
service:
- name: spring-cloud-kubernetes-client-configmap-event-reload
+ name: spring-k8s-client-reload
port:
number: 8080
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/left-configmap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/left-configmap.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/left-configmap.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/left-configmap.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/logback-test.xml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/logback-test.xml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/logback-test.xml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/right-configmap-with-label.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/right-configmap-with-label.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/right-configmap-with-label.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/right-configmap-with-label.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/right-configmap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/right-configmap.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/right-configmap.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/right-configmap.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/service.yaml
new file mode 100644
index 00000000..fae9311f
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ app: spring-k8s-client-reload
+ name: spring-k8s-client-reload
+spec:
+ ports:
+ - name: http
+ port: 8080
+ targetPort: 8080
+ selector:
+ app: spring-k8s-client-reload
+ type: ClusterIP