From dd8ed8c298956431d6ea362e6a06e9b9016d57ce Mon Sep 17 00:00:00 2001 From: erabii Date: Sat, 7 Oct 2023 21:52:31 +0300 Subject: [PATCH] Fabric8 it part 5 (#1470) --- .../pom.xml | 1 - .../cloud/kubernetes/fabric8/reload/App.java | 2 +- .../kubernetes/fabric8/reload/Controller.java | 11 +- .../fabric8/reload/SecretProperties.java} | 8 +- .../resources/application-with-secret.yaml} | 0 ...edPollingReloadConfigMapMountDelegate.java | 4 +- .../ConfigMapMountPollingReloadDelegate.java | 4 +- .../ConfigMapPollingReloadDelegate.java | 8 +- .../fabric8/reload/Fabric8EventReloadIT.java | 44 ++-- .../reload/SecretsEventsReloadDelegate.java | 100 +++++++++ .../kubernetes/fabric8/reload/TestUtil.java | 27 ++- .../src/test/resources/secret.yaml | 4 +- .../pom.xml | 108 --------- .../secrets/event/reload/SecretsApp.java | 35 --- .../event/reload/SecretsController.java | 39 ---- .../reload/DataChangesInSecretsReloadIT.java | 210 ------------------ .../event/reload/SecretsEventsReloadIT.java | 184 --------------- .../src/test/resources/deployment.yaml | 31 --- .../src/test/resources/ingress.yaml | 16 -- .../src/test/resources/logback-test.xml | 15 -- .../src/test/resources/service.yaml | 14 -- 21 files changed, 178 insertions(+), 687 deletions(-) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsProperties.java => spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/reload/SecretProperties.java} (79%) rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/main/resources/application.yaml => spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-with-secret.yaml} (100%) create mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/SecretsEventsReloadDelegate.java rename spring-cloud-kubernetes-integration-tests/{spring-cloud-kubernetes-fabric8-client-secrets-event-reload => spring-cloud-kubernetes-fabric8-client-reload}/src/test/resources/secret.yaml (51%) delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/pom.xml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsApp.java delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsController.java delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/DataChangesInSecretsReloadIT.java delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsEventsReloadIT.java delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/deployment.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/ingress.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/logback-test.xml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-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 f905e5a6..b8dd8d7a 100644 --- a/spring-cloud-kubernetes-integration-tests/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/pom.xml @@ -51,7 +51,6 @@ spring-cloud-kubernetes-fabric8-istio-it spring-cloud-kubernetes-fabric8-client-discovery spring-cloud-kubernetes-fabric8-client-loadbalancer - spring-cloud-kubernetes-fabric8-client-secrets-event-reload spring-cloud-kubernetes-fabric8-client-reload spring-cloud-kubernetes-discoveryclient-it diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/reload/App.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/reload/App.java index 29771fb8..f6a855be 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/reload/App.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/reload/App.java @@ -25,7 +25,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties */ @SpringBootApplication @EnableConfigurationProperties({ LeftProperties.class, RightProperties.class, RightWithLabelsProperties.class, - ConfigMapProperties.class }) + ConfigMapProperties.class, SecretProperties.class }) public class App { public static void main(String[] args) { diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/reload/Controller.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/reload/Controller.java index 8087f875..e79c04ba 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/reload/Controller.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/reload/Controller.java @@ -33,12 +33,16 @@ public class Controller { private final ConfigMapProperties configMapProperties; + private final SecretProperties secretProperties; + public Controller(LeftProperties leftProperties, RightProperties rightProperties, - RightWithLabelsProperties rightWithLabelsProperties, ConfigMapProperties configMapProperties) { + RightWithLabelsProperties rightWithLabelsProperties, ConfigMapProperties configMapProperties, + SecretProperties secretProperties) { this.leftProperties = leftProperties; this.rightProperties = rightProperties; this.rightWithLabelsProperties = rightWithLabelsProperties; this.configMapProperties = configMapProperties; + this.secretProperties = secretProperties; } @GetMapping("/left") @@ -61,4 +65,9 @@ public class Controller { return configMapProperties.getKey(); } + @GetMapping("/key-from-secret") + public String keyFromSecret() { + return secretProperties.getKey(); + } + } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsProperties.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/reload/SecretProperties.java similarity index 79% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsProperties.java rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/reload/SecretProperties.java index 99419fff..3b9f3a10 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsProperties.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/reload/SecretProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 the original author or authors. + * 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. @@ -14,15 +14,15 @@ * limitations under the License. */ -package org.springframework.cloud.kubernetes.fabric8.secrets.event.reload; +package org.springframework.cloud.kubernetes.fabric8.reload; import org.springframework.boot.context.properties.ConfigurationProperties; /** * @author wind57 */ -@ConfigurationProperties("from.properties") -public class SecretsProperties { +@ConfigurationProperties("from.secret.properties") +public class SecretProperties { private String key; diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/main/resources/application.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-with-secret.yaml similarity index 100% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/main/resources/application.yaml rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-with-secret.yaml diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/BootstrapEnabledPollingReloadConfigMapMountDelegate.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/BootstrapEnabledPollingReloadConfigMapMountDelegate.java index 24a5e0dc..450494e4 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/BootstrapEnabledPollingReloadConfigMapMountDelegate.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/BootstrapEnabledPollingReloadConfigMapMountDelegate.java @@ -58,8 +58,8 @@ final class BootstrapEnabledPollingReloadConfigMapMountDelegate { appLabelValue); // (3) WebClient webClient = TestUtil.builder().baseUrl("http://localhost/key").build(); - String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(TestUtil.retrySpec()) - .block(); + String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) + .retryWhen(TestUtil.retrySpec()).block(); // we first read the initial value from the configmap Assertions.assertEquals("as-mount-initial", result); diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/ConfigMapMountPollingReloadDelegate.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/ConfigMapMountPollingReloadDelegate.java index d91978c6..2642296b 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/ConfigMapMountPollingReloadDelegate.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/ConfigMapMountPollingReloadDelegate.java @@ -62,8 +62,8 @@ final class ConfigMapMountPollingReloadDelegate { appLabelValue); // (3) WebClient webClient = TestUtil.builder().baseUrl("http://localhost/key").build(); - String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(TestUtil.retrySpec()) - .block(); + String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) + .retryWhen(TestUtil.retrySpec()).block(); // we first read the initial value from the configmap Assertions.assertEquals("as-mount-initial", result); diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/ConfigMapPollingReloadDelegate.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/ConfigMapPollingReloadDelegate.java index 6f5499cd..5e6861c8 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/ConfigMapPollingReloadDelegate.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/ConfigMapPollingReloadDelegate.java @@ -38,8 +38,8 @@ final class ConfigMapPollingReloadDelegate { static void testConfigMapPollingReload(KubernetesClient client) { WebClient webClient = TestUtil.builder().baseUrl("http://localhost/key").build(); - String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(TestUtil.retrySpec()) - .block(); + String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) + .retryWhen(TestUtil.retrySpec()).block(); // we first read the initial value from the configmap Assertions.assertEquals("as-mount-initial", result); @@ -53,8 +53,8 @@ final class ConfigMapPollingReloadDelegate { client.configMaps().inNamespace("default").resource(map).createOrReplace(); await().ignoreException(HttpServerErrorException.BadGateway.class).timeout(Duration.ofSeconds(120)) - .until(() -> webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(TestUtil.retrySpec()) - .block().equals("after-change")); + .until(() -> webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) + .retryWhen(TestUtil.retrySpec()).block().equals("after-change")); } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/Fabric8EventReloadIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/Fabric8EventReloadIT.java index a2974be4..98ba5cef 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/Fabric8EventReloadIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/Fabric8EventReloadIT.java @@ -24,6 +24,7 @@ import java.util.Set; import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.ConfigMapBuilder; import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.fabric8.kubernetes.api.model.Secret; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.networking.v1.Ingress; @@ -102,15 +103,16 @@ class Fabric8EventReloadIT { "added secret informer for namespace", IMAGE_NAME); WebClient webClient = TestUtil.builder().baseUrl("http://localhost/left").build(); - String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(TestUtil.retrySpec()) - .block(); + String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) + .retryWhen(TestUtil.retrySpec()).block(); // we first read the initial value from the left-configmap Assertions.assertEquals("left-initial", result); // then read the value from the right-configmap webClient = TestUtil.builder().baseUrl("http://localhost/right").build(); - result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(TestUtil.retrySpec()).block(); + result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(TestUtil.retrySpec()) + .block(); Assertions.assertEquals("right-initial", result); // then deploy a new version of right-configmap @@ -137,6 +139,7 @@ class Fabric8EventReloadIT { testConfigMapPollingReload(); testConfigMapMountPollingReload(); testPollingReloadConfigMapWithBootstrap(); + testSecretReload(); } /** @@ -150,7 +153,7 @@ class Fabric8EventReloadIT { */ void testInformFromOneNamespaceEventTriggered() { - TestUtil.reCreateConfigMaps(util, client); + TestUtil.reCreateSources(util, client); TestUtil.patchOne(util, DOCKER_IMAGE, IMAGE_NAME, NAMESPACE); Commons.assertReloadLogStatements("added configmap informer for namespace", @@ -158,8 +161,8 @@ class Fabric8EventReloadIT { // read the value from the right-configmap WebClient webClient = TestUtil.builder().baseUrl("http://localhost/right").build(); - String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(TestUtil.retrySpec()) - .block(); + String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) + .retryWhen(TestUtil.retrySpec()).block(); Assertions.assertEquals("right-initial", result); // then deploy a new version of right-configmap @@ -192,7 +195,7 @@ class Fabric8EventReloadIT { */ void testInform() { - TestUtil.reCreateConfigMaps(util, client); + TestUtil.reCreateSources(util, client); TestUtil.patchTwo(util, DOCKER_IMAGE, IMAGE_NAME, NAMESPACE); Commons.assertReloadLogStatements("added configmap informer for namespace", @@ -246,8 +249,8 @@ class Fabric8EventReloadIT { // right-configmap now will see the new value also, but only because the other // configmap has triggered the restart - rightResult = rightWebClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(TestUtil.retrySpec()) - .block(); + rightResult = rightWebClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) + .retryWhen(TestUtil.retrySpec()).block(); Assertions.assertEquals("right-after-change", rightResult); } @@ -263,7 +266,7 @@ class Fabric8EventReloadIT { */ void testInformFromOneNamespaceEventTriggeredSecretsDisabled() { - TestUtil.reCreateConfigMaps(util, client); + TestUtil.reCreateSources(util, client); TestUtil.patchThree(util, DOCKER_IMAGE, IMAGE_NAME, NAMESPACE); Commons.assertReloadLogStatements("added configmap informer for namespace", @@ -271,8 +274,8 @@ class Fabric8EventReloadIT { // read the value from the right-configmap WebClient webClient = TestUtil.builder().baseUrl("http://localhost/right").build(); - String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(TestUtil.retrySpec()) - .block(); + String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) + .retryWhen(TestUtil.retrySpec()).block(); Assertions.assertEquals("right-initial", result); // then deploy a new version of right-configmap @@ -295,7 +298,7 @@ class Fabric8EventReloadIT { } void testDataChangesInConfigMap() { - TestUtil.reCreateConfigMaps(util, client); + TestUtil.reCreateSources(util, client); TestUtil.patchFour(util, DOCKER_IMAGE, IMAGE_NAME, NAMESPACE); DataChangesInConfigMapReloadDelegate.testDataChangesInConfigMap(client, K3S, IMAGE_NAME); } @@ -306,18 +309,23 @@ class Fabric8EventReloadIT { } void testConfigMapMountPollingReload() { - TestUtil.reCreateConfigMaps(util, client); + TestUtil.reCreateSources(util, client); TestUtil.patchSix(util, DOCKER_IMAGE, IMAGE_NAME, NAMESPACE); ConfigMapMountPollingReloadDelegate.testConfigMapMountPollingReload(client, util, K3S, IMAGE_NAME); } void testPollingReloadConfigMapWithBootstrap() { - TestUtil.reCreateConfigMaps(util, client); + TestUtil.reCreateSources(util, client); TestUtil.patchSeven(util, DOCKER_IMAGE, IMAGE_NAME, NAMESPACE); BootstrapEnabledPollingReloadConfigMapMountDelegate.testPollingReloadConfigMapWithBootstrap(client, util, K3S, IMAGE_NAME); } + void testSecretReload() { + TestUtil.patchEight(util, DOCKER_IMAGE, IMAGE_NAME, NAMESPACE); + SecretsEventsReloadDelegate.testSecretReload(client, K3S, IMAGE_NAME); + } + private static void manifests(Phase phase) { InputStream deploymentStream = util.inputStream("deployment.yaml"); @@ -327,6 +335,7 @@ class Fabric8EventReloadIT { InputStream rightConfigMapStream = util.inputStream("right-configmap.yaml"); InputStream rightWithLabelConfigMapStream = util.inputStream("right-configmap-with-label.yaml"); InputStream configMapAsStream = util.inputStream("configmap.yaml"); + InputStream secretAsStream = util.inputStream("secret.yaml"); Deployment deployment = Serialization.unmarshal(deploymentStream, Deployment.class); @@ -336,19 +345,20 @@ class Fabric8EventReloadIT { ConfigMap rightConfigMap = Serialization.unmarshal(rightConfigMapStream, ConfigMap.class); ConfigMap rightWithLabelConfigMap = Serialization.unmarshal(rightWithLabelConfigMapStream, ConfigMap.class); ConfigMap configMap = Serialization.unmarshal(configMapAsStream, ConfigMap.class); + Secret secret = Serialization.unmarshal(secretAsStream, Secret.class); if (phase.equals(Phase.CREATE)) { util.createAndWait("left", leftConfigMap, null); util.createAndWait("right", rightConfigMap, null); util.createAndWait("right", rightWithLabelConfigMap, null); - util.createAndWait(NAMESPACE, configMap, null); + util.createAndWait(NAMESPACE, configMap, secret); util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); } else { util.deleteAndWait("left", leftConfigMap, null); util.deleteAndWait("right", rightConfigMap, null); util.deleteAndWait("right", rightWithLabelConfigMap, null); - util.deleteAndWait(NAMESPACE, configMap, null); + util.deleteAndWait(NAMESPACE, configMap, secret); util.deleteAndWait(NAMESPACE, deployment, service, ingress); } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/SecretsEventsReloadDelegate.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/SecretsEventsReloadDelegate.java new file mode 100644 index 00000000..8217d475 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/SecretsEventsReloadDelegate.java @@ -0,0 +1,100 @@ +/* + * Copyright 2013-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.kubernetes.fabric8.reload; + +import java.time.Duration; +import java.util.Base64; +import java.util.Map; + +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.fabric8.kubernetes.api.model.Secret; +import io.fabric8.kubernetes.api.model.SecretBuilder; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.junit.jupiter.api.Assertions; +import org.testcontainers.k3s.K3sContainer; + +import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; +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.fabric8.reload.TestUtil.builder; +import static org.springframework.cloud.kubernetes.fabric8.reload.TestUtil.retrySpec; + +/** + * @author wind57 + */ +final class SecretsEventsReloadDelegate { + + /** + *
+	 *     - secret with no labels and data: from.secret.properties.key = secret-initial exists in namespace default
+	 *     - we assert that we can read it correctly first, by invoking localhost/key.
+	 *
+	 *     - then we change the secret by adding a label, this in turn does not
+	 *       change the result of localhost/key, because the data has not changed.
+	 *
+	 *     - then we change data inside the secret, and we must see the updated value.
+	 * 
+ */ + static void testSecretReload(KubernetesClient client, K3sContainer container, String appLabelValue) { + Commons.assertReloadLogStatements("added secret informer for namespace", + "added configmap informer for namespace", appLabelValue); + + WebClient webClient = builder().baseUrl("http://localhost/key-from-secret").build(); + String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec()) + .block(); + Assertions.assertEquals("secret-initial", result); + + Secret secret = new SecretBuilder() + .withMetadata(new ObjectMetaBuilder().withLabels(Map.of("letter", "a")).withNamespace("default") + .withName("event-reload").build()) + .withData(Map.of("application.properties", + Base64.getEncoder().encodeToString("from.secret.properties.key=secret-initial".getBytes()))) + .build(); + client.secrets().inNamespace("default").resource(secret).createOrReplace(); + + await().pollInterval(Duration.ofSeconds(3)).atMost(Duration.ofSeconds(90)).until(() -> { + WebClient innerWebClient = builder().baseUrl("http://localhost/key-from-secret").build(); + String innerResult = innerWebClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) + .retryWhen(retrySpec()).block(); + return "secret-initial".equals(innerResult); + }); + + Commons.waitForLogStatement("Secret event-reload was updated in namespace default", container, appLabelValue); + Commons.waitForLogStatement("data in secret has not changed, will not reload", container, appLabelValue); + + // change data + secret = new SecretBuilder() + .withMetadata(new ObjectMetaBuilder().withNamespace("default").withName("event-reload").build()) + .withData(Map.of("application.properties", + Base64.getEncoder() + .encodeToString("from.secret.properties.key=secret-initial-changed".getBytes()))) + .build(); + + client.secrets().inNamespace("default").resource(secret).createOrReplace(); + + await().pollInterval(Duration.ofSeconds(3)).atMost(Duration.ofSeconds(90)).until(() -> { + WebClient innerWebClient = builder().baseUrl("http://localhost/key-from-secret").build(); + String innerResult = innerWebClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) + .retryWhen(retrySpec()).block(); + return "secret-initial-changed".equals(innerResult); + }); + + } + +} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/TestUtil.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/TestUtil.java index 50df50dd..0c328192 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/TestUtil.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/reload/TestUtil.java @@ -299,11 +299,32 @@ final class TestUtil { } """; + private static final String BODY_EIGHT = """ + { + "spec": { + "template": { + "spec": { + "containers": [{ + "name": "spring-cloud-kubernetes-fabric8-client-configmap-event-reload", + "image": "image_name_here", + "env": [ + { + "name": "SPRING_PROFILES_ACTIVE", + "value": "with-secret" + } + ] + }] + } + } + } + } + """; + private TestUtil() { } - static void reCreateConfigMaps(Util util, KubernetesClient client) { + static void reCreateSources(Util util, KubernetesClient client) { InputStream leftConfigMapStream = util.inputStream("left-configmap.yaml"); InputStream rightConfigMapStream = util.inputStream("right-configmap.yaml"); InputStream configMapStream = util.inputStream("configmap.yaml"); @@ -349,6 +370,10 @@ final class TestUtil { util.patchWithReplace(dockerImage, deploymentName, namespace, BODY_SEVEN, POD_LABELS); } + static void patchEight(Util util, String dockerImage, String deploymentName, String namespace) { + util.patchWithReplace(dockerImage, deploymentName, namespace, BODY_EIGHT, POD_LABELS); + } + static WebClient.Builder builder() { return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create())); } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/secret.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/resources/secret.yaml similarity index 51% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/secret.yaml rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/resources/secret.yaml index 9ad19aad..260f7910 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/secret.yaml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/resources/secret.yaml @@ -4,6 +4,6 @@ metadata: name: event-reload namespace: default data: - # from.properties.key=initial + # from.secret.properties.key=secret-initial application.properties: | - ZnJvbS5wcm9wZXJ0aWVzLmtleT1pbml0aWFs + ZnJvbS5zZWNyZXQucHJvcGVydGllcy5rZXk9c2VjcmV0LWluaXRpYWw= diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/pom.xml deleted file mode 100644 index 07784467..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/pom.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - - org.springframework.cloud - spring-cloud-kubernetes-integration-tests - 3.0.5-SNAPSHOT - - 4.0.0 - - spring-cloud-kubernetes-fabric8-client-secrets-event-reload - - - - - org.springframework.cloud - spring-cloud-kubernetes-fabric8-config - - - org.springframework.boot - spring-boot-starter-webflux - - - org.springframework.boot - spring-boot-starter-actuator - - - - 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-fabric8-client-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsApp.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsApp.java deleted file mode 100644 index cc49b3e4..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsApp.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2013-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.kubernetes.fabric8.secrets.event.reload; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.properties.EnableConfigurationProperties; - -/** - * @author wind57 - */ - -@SpringBootApplication -@EnableConfigurationProperties(SecretsProperties.class) -public class SecretsApp { - - public static void main(String[] args) { - SpringApplication.run(SecretsApp.class, args); - } - -} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsController.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsController.java deleted file mode 100644 index 5c3d3dda..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsController.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2013-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.kubernetes.fabric8.secrets.event.reload; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author wind57 - */ -@RestController -public class SecretsController { - - private final SecretsProperties properties; - - public SecretsController(SecretsProperties properties) { - this.properties = properties; - } - - @GetMapping("/key") - public String key() { - return properties.getKey(); - } - -} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/DataChangesInSecretsReloadIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/DataChangesInSecretsReloadIT.java deleted file mode 100644 index 25a68172..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/DataChangesInSecretsReloadIT.java +++ /dev/null @@ -1,210 +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.fabric8.secrets.event.reload; - -import java.io.InputStream; -import java.time.Duration; -import java.util.ArrayList; -import java.util.Base64; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import io.fabric8.kubernetes.api.model.EnvVar; -import io.fabric8.kubernetes.api.model.EnvVarBuilder; -import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; -import io.fabric8.kubernetes.api.model.Secret; -import io.fabric8.kubernetes.api.model.SecretBuilder; -import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.api.model.apps.Deployment; -import io.fabric8.kubernetes.api.model.networking.v1.Ingress; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.utils.Serialization; -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.fabric8_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 DataChangesInSecretsReloadIT { - - private static final String IMAGE_NAME = "spring-cloud-kubernetes-fabric8-client-secrets-event-reload"; - - private static final String NAMESPACE = "default"; - - private static KubernetesClient client; - - private static Util util; - - 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); - client = util.client(); - util.setUp(NAMESPACE); - } - - @AfterAll - static void after() throws Exception { - Commons.cleanUp(IMAGE_NAME, K3S); - Commons.systemPrune(); - } - - /** - *
-	 *     - secret with no labels and data: from.properties.key = initial exists in namespace default
-	 *     - we assert that we can read it correctly first, by invoking localhost/key.
-	 *
-	 *     - then we change the secret by adding a label, this in turn does not
-	 *       change the result of localhost/key, because the data has not changed.
-	 *
-	 *     - then we change data inside the secret, and we must see the updated value.
-	 * 
- */ - @Test - void testSimple() { - manifests(Phase.CREATE); - Commons.assertReloadLogStatements("added secret informer for namespace", - "added configmap informer for namespace", IMAGE_NAME); - - WebClient webClient = builder().baseUrl("http://localhost/key").build(); - String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec()) - .block(); - Assertions.assertEquals("initial", result); - - Secret secret = new SecretBuilder() - .withMetadata(new ObjectMetaBuilder().withLabels(Map.of("letter", "a")).withNamespace(NAMESPACE) - .withName("event-reload").build()) - .withData(Map.of("application.properties", - Base64.getEncoder().encodeToString("from.properties.key=initial".getBytes()))) - .build(); - client.secrets().inNamespace(NAMESPACE).resource(secret).createOrReplace(); - - await().pollInterval(Duration.ofSeconds(3)).atMost(Duration.ofSeconds(90)).until(() -> { - WebClient innerWebClient = builder().baseUrl("http://localhost/key").build(); - String innerResult = innerWebClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) - .retryWhen(retrySpec()).block(); - return "initial".equals(innerResult); - }); - - String logs = logs(); - Assertions.assertTrue(logs.contains("Secret event-reload was updated in namespace default")); - Assertions.assertTrue(logs.contains("data in secret has not changed, will not reload")); - - // change data - secret = new SecretBuilder() - .withMetadata(new ObjectMetaBuilder().withNamespace(NAMESPACE).withName("event-reload").build()) - .withData(Map.of("application.properties", - Base64.getEncoder().encodeToString("from.properties.key=initial-changed".getBytes()))) - .build(); - - client.secrets().inNamespace(NAMESPACE).resource(secret).createOrReplace(); - - await().pollInterval(Duration.ofSeconds(3)).atMost(Duration.ofSeconds(90)).until(() -> { - WebClient innerWebClient = builder().baseUrl("http://localhost/key").build(); - String innerResult = innerWebClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class) - .retryWhen(retrySpec()).block(); - return "initial-changed".equals(innerResult); - }); - - manifests(Phase.DELETE); - } - - private static void manifests(Phase phase) { - - InputStream deploymentStream = util.inputStream("deployment.yaml"); - InputStream serviceStream = util.inputStream("service.yaml"); - InputStream ingressStream = util.inputStream("ingress.yaml"); - InputStream secretAsStream = util.inputStream("secret.yaml"); - - Deployment deployment = Serialization.unmarshal(deploymentStream, Deployment.class); - - List envVars = new ArrayList<>( - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv()); - EnvVar activeProfileProperty = new EnvVarBuilder().withName("SPRING_PROFILES_ACTIVE").withValue("one").build(); - envVars.add(activeProfileProperty); - - EnvVar configMapsDisabledEnvVar = new EnvVarBuilder().withName("SPRING_CLOUD_KUBERNETES_CONFIG_ENABLED") - .withValue("FALSE").build(); - - EnvVar debugLevel = new EnvVarBuilder() - .withName("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD").withName("DEBUG") - .build(); - envVars.add(debugLevel); - - envVars.add(configMapsDisabledEnvVar); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(envVars); - - Service service = Serialization.unmarshal(serviceStream, Service.class); - Ingress ingress = Serialization.unmarshal(ingressStream, Ingress.class); - Secret secret = Serialization.unmarshal(secretAsStream, Secret.class); - - if (phase.equals(Phase.CREATE)) { - util.createAndWait(NAMESPACE, null, secret); - util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); - } - else { - util.deleteAndWait(NAMESPACE, null, secret); - util.deleteAndWait(NAMESPACE, deployment, service, ingress); - } - - } - - 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); - } - } - - private WebClient.Builder builder() { - return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create())); - } - - private RetryBackoffSpec retrySpec() { - return Retry.fixedDelay(120, Duration.ofSeconds(2)).filter(Objects::nonNull); - } - -} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsEventsReloadIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsEventsReloadIT.java deleted file mode 100644 index 97bb53ec..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/secrets/event/reload/SecretsEventsReloadIT.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2013-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.kubernetes.fabric8.secrets.event.reload; - -import java.io.InputStream; -import java.time.Duration; -import java.util.ArrayList; -import java.util.Base64; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import io.fabric8.kubernetes.api.model.EnvVar; -import io.fabric8.kubernetes.api.model.EnvVarBuilder; -import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; -import io.fabric8.kubernetes.api.model.Secret; -import io.fabric8.kubernetes.api.model.SecretBuilder; -import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.api.model.apps.Deployment; -import io.fabric8.kubernetes.api.model.networking.v1.Ingress; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.utils.Serialization; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.testcontainers.k3s.K3sContainer; -import reactor.netty.http.client.HttpClient; -import reactor.util.retry.Retry; -import reactor.util.retry.RetryBackoffSpec; - -import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; -import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_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 SecretsEventsReloadIT { - - private static final String IMAGE_NAME = "spring-cloud-kubernetes-fabric8-client-secrets-event-reload"; - - private static final String NAMESPACE = "default"; - - private static KubernetesClient client; - - private static Util util; - - 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); - client = util.client(); - util.setUp(NAMESPACE); - } - - @AfterAll - static void after() throws Exception { - Commons.cleanUp(IMAGE_NAME, K3S); - Commons.systemPrune(); - } - - @Test - void testSimple() { - manifests(Phase.CREATE, false); - Commons.assertReloadLogStatements("added secret informer for namespace", - "added configmap informer for namespace", IMAGE_NAME); - 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 secret - Assertions.assertEquals("initial", result); - - // then deploy a new version of the secret - // since we poll and have reload in place, the new property must be visible - Secret secret = new SecretBuilder() - .withMetadata(new ObjectMetaBuilder().withNamespace("default").withName("event-reload").build()) - .withData(Map.of("application.properties", - Base64.getEncoder().encodeToString("from.properties.key=after-change".getBytes()))) - .build(); - - client.secrets().inNamespace("default").resource(secret).createOrReplace(); - - await().timeout(Duration.ofSeconds(120)).until(() -> webClient.method(HttpMethod.GET).retrieve() - .bodyToMono(String.class).retryWhen(retrySpec()).block().equals("after-change")); - - manifests(Phase.DELETE, false); - } - - @Test - void testSimpleConfigMapsDisabled() { - manifests(Phase.CREATE, true); - Commons.assertReloadLogStatements("added secret informer for namespace", - "added configmap informer for namespace", IMAGE_NAME); - 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 secret - Assertions.assertEquals("initial", result); - - // then deploy a new version of the secret - // since we poll and have reload in place, the new property must be visible - Secret secret = new SecretBuilder() - .withMetadata(new ObjectMetaBuilder().withNamespace("default").withName("event-reload").build()) - .withData(Map.of("application.properties", - Base64.getEncoder().encodeToString("from.properties.key=after-change".getBytes()))) - .build(); - - client.secrets().inNamespace("default").resource(secret).createOrReplace(); - - await().timeout(Duration.ofSeconds(120)).until(() -> webClient.method(HttpMethod.GET).retrieve() - .bodyToMono(String.class).retryWhen(retrySpec()).block().equals("after-change")); - - manifests(Phase.DELETE, true); - - } - - private static void manifests(Phase phase, boolean configMapsDisabled) { - - InputStream deploymentStream = util.inputStream("deployment.yaml"); - InputStream serviceStream = util.inputStream("service.yaml"); - InputStream ingressStream = util.inputStream("ingress.yaml"); - InputStream secretStream = util.inputStream("secret.yaml"); - - Deployment deployment = Serialization.unmarshal(deploymentStream, Deployment.class); - Service service = Serialization.unmarshal(serviceStream, Service.class); - Ingress ingress = Serialization.unmarshal(ingressStream, Ingress.class); - Secret secret = Serialization.unmarshal(secretStream, Secret.class); - - if (configMapsDisabled) { - List envVars = new ArrayList<>( - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv()); - EnvVar configMapsDisabledEnvVar = new EnvVarBuilder().withName("SPRING_CLOUD_KUBERNETES_CONFIG_ENABLED") - .withValue("FALSE").build(); - envVars.add(configMapsDisabledEnvVar); - deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(envVars); - } - - if (phase.equals(Phase.CREATE)) { - util.createAndWait(NAMESPACE, null, secret); - util.createAndWait(NAMESPACE, null, deployment, service, ingress, true); - } - else { - util.deleteAndWait(NAMESPACE, null, secret); - util.deleteAndWait(NAMESPACE, deployment, service, ingress); - } - - } - - 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); - } - -} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/deployment.yaml deleted file mode 100644 index ce326181..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/deployment.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: spring-cloud-kubernetes-fabric8-client-secrets-deployment-event-reload -spec: - selector: - matchLabels: - app: spring-cloud-kubernetes-fabric8-client-secrets-event-reload - template: - metadata: - labels: - app: spring-cloud-kubernetes-fabric8-client-secrets-event-reload - spec: - serviceAccountName: spring-cloud-kubernetes-serviceaccount - containers: - - name: spring-cloud-kubernetes-fabric8-client-secrets-event-reload - image: docker.io/springcloud/spring-cloud-kubernetes-fabric8-client-secrets-event-reload - imagePullPolicy: IfNotPresent - readinessProbe: - httpGet: - port: 8080 - path: /actuator/health/readiness - livenessProbe: - httpGet: - port: 8080 - path: /actuator/health/liveness - ports: - - containerPort: 8080 - env: - - name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_FABRIC8_CONFIG_RELOAD - value: DEBUG diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/ingress.yaml deleted file mode 100644 index 19e5d0df..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/ingress.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: spring-cloud-kubernetes-fabric8-client-secrets-ingress-event-reload - namespace: default -spec: - rules: - - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: spring-cloud-kubernetes-fabric8-client-secrets-event-reload - port: - number: 8080 diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/logback-test.xml deleted file mode 100644 index ee243343..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-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-fabric8-client-secrets-event-reload/src/test/resources/service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/service.yaml deleted file mode 100644 index 239bc00b..00000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-secrets-event-reload/src/test/resources/service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: spring-cloud-kubernetes-fabric8-client-secrets-event-reload - name: spring-cloud-kubernetes-fabric8-client-secrets-event-reload -spec: - ports: - - name: http - port: 8080 - targetPort: 8080 - selector: - app: spring-cloud-kubernetes-fabric8-client-secrets-event-reload - type: ClusterIP