From 600eb34717d7f659520ed777b3171f0ec8e708a5 Mon Sep 17 00:00:00 2001 From: erabii Date: Sun, 17 Sep 2023 23:08:26 +0300 Subject: [PATCH] Merge k8s client event polling reload ITs (9) (#1428) --- .../pom.xml | 3 +- .../pom.xml | 112 --------- .../src/test/resources/service.yaml | 14 -- .../polling/reload/ConfigMapApp.java | 35 --- .../polling/reload/ConfigMapController.java | 39 --- ...pEnabledPollingReloadConfigMapMountIT.java | 187 --------------- .../reload/PollingReloadConfigMapMountIT.java | 188 --------------- .../src/test/resources/deployment-mount.yaml | 43 ---- .../src/test/resources/ingress.yaml | 16 -- .../src/test/resources/logback-test.xml | 15 -- .../src/test/resources/service.yaml | 14 -- .../pom.xml | 2 +- .../client/configmap}/reload/App.java | 5 +- .../reload/ConfigMapProperties.java | 2 +- .../client/configmap}/reload/Controller.java | 12 +- .../configmap}/reload/LeftProperties.java | 2 +- .../configmap}/reload/RightProperties.java | 2 +- .../reload/RightWithLabelsProperties.java | 2 +- .../src/main/resources/application-mount.yaml | 0 .../src/main/resources/application-one.yaml | 0 .../src/main/resources/application-three.yaml | 0 .../src/main/resources/application-two.yaml | 0 .../resources/application-with-bootstrap.yaml | 0 .../src/main/resources/bootstrap-one.yaml | 0 .../src/main/resources/bootstrap-three.yaml | 0 .../src/main/resources/bootstrap-two.yaml | 0 .../resources/bootstrap-with-bootstrap.yaml | 0 ...edPollingReloadConfigMapMountDelegate.java | 99 ++++++++ .../DataChangesInConfigMapReloadDelegate.java | 52 +--- .../reload/K8sClientConfigMapReloadIT.java} | 62 ++--- .../reload/K8sClientReloadITUtil.java} | 227 +++++++++++++++++- .../PollingReloadConfigMapMountDelegate.java | 94 ++++++++ .../src/test/resources/configmap-mount.yaml | 0 .../src/test/resources/deployment.yaml | 12 +- .../src/test/resources/ingress.yaml | 4 +- .../src/test/resources/left-configmap.yaml | 0 .../src/test/resources/logback-test.xml | 0 .../resources/right-configmap-with-label.yaml | 0 .../src/test/resources/right-configmap.yaml | 0 .../src/test/resources/service.yaml | 14 ++ 40 files changed, 499 insertions(+), 758 deletions(-) delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/pom.xml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-event-reload/src/test/resources/service.yaml delete mode 100644 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 delete mode 100644 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 delete mode 100644 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 delete mode 100644 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 delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/deployment-mount.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/ingress.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/logback-test.xml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-configmap-polling-reload/src/test/resources/service.yaml rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-polling-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/pom.xml (98%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event => spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap}/reload/App.java (87%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/polling => spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap}/reload/ConfigMapProperties.java (92%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event => spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap}/reload/Controller.java (80%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event => spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap}/reload/LeftProperties.java (92%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event => spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap}/reload/RightProperties.java (92%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap/event => spring-cloud-kubernetes-client-event-and-polling-reload/src/main/java/org/springframework/cloud/kubernetes/client/configmap}/reload/RightWithLabelsProperties.java (92%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-polling-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/main/resources/application-mount.yaml (100%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/main/resources/application-one.yaml (100%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/main/resources/application-three.yaml (100%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/main/resources/application-two.yaml (100%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-polling-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/main/resources/application-with-bootstrap.yaml (100%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/main/resources/bootstrap-one.yaml (100%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/main/resources/bootstrap-three.yaml (100%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/main/resources/bootstrap-two.yaml (100%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-polling-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/main/resources/bootstrap-with-bootstrap.yaml (100%) create mode 100644 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 rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/event => spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap}/reload/DataChangesInConfigMapReloadDelegate.java (73%) rename 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 => spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/K8sClientConfigMapReloadIT.java} (86%) rename 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 => spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/configmap/reload/K8sClientReloadITUtil.java} (50%) create mode 100644 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 rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-polling-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/test/resources/configmap-mount.yaml (100%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/test/resources/deployment.yaml (72%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/test/resources/ingress.yaml (64%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/test/resources/left-configmap.yaml (100%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/test/resources/logback-test.xml (100%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/test/resources/right-configmap-with-label.yaml (100%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-client-configmap-event-reload => spring-cloud-kubernetes-client-event-and-polling-reload}/src/test/resources/right-configmap.yaml (100%) create mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/service.yaml diff --git a/spring-cloud-kubernetes-integration-tests/pom.xml b/spring-cloud-kubernetes-integration-tests/pom.xml index 25a98b50..fcf4adaa 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 1cd48c71..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.0.5-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 eb72f1fd..dfc5d039 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.0.5-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