POD_LABELS = Map.of("app", "spring-k8s-client-reload");
- private K8sClientReloadITUtil() {
-
+ private K8sClientConfigMapReloadITUtil() {
}
private static final String BODY_ONE = """
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
index 8bae0696..8bc99f43 100644
--- 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
@@ -30,9 +30,6 @@ 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
@@ -61,7 +58,7 @@ final class PollingReloadConfigMapMountDelegate {
static void testPollingReloadConfigMapMount(String deploymentName, K3sContainer k3sContainer, Util util,
String imageName) throws Exception {
- patchFive(deploymentName, "default", imageName);
+ K8sClientConfigMapReloadITUtil.patchFive(deploymentName, "default", imageName);
// (1)
Commons.waitForLogStatement("paths property sources : [/tmp/application.properties]", k3sContainer,
@@ -72,9 +69,9 @@ final class PollingReloadConfigMapMountDelegate {
deploymentName);
// (3)
- WebClient webClient = builder().baseUrl("http://localhost/mount").build();
- String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class).retryWhen(retrySpec())
- .block();
+ WebClient webClient = K8sClientConfigMapReloadITUtil.builder().baseUrl("http://localhost/mount").build();
+ String result = webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class)
+ .retryWhen(K8sClientConfigMapReloadITUtil.retrySpec()).block();
// we first read the initial value from the configmap
Assertions.assertEquals("as-mount-initial", result);
@@ -86,8 +83,9 @@ final class PollingReloadConfigMapMountDelegate {
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"));
+ await().timeout(Duration.ofSeconds(180))
+ .until(() -> webClient.method(HttpMethod.GET).retrieve().bodyToMono(String.class)
+ .retryWhen(K8sClientConfigMapReloadITUtil.retrySpec()).block().equals("as-mount-changed"));
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/reload/DataChangesInSecretsReloadDelegate.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/reload/DataChangesInSecretsReloadDelegate.java
new file mode 100644
index 00000000..71178fae
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/reload/DataChangesInSecretsReloadDelegate.java
@@ -0,0 +1,110 @@
+/*
+ * 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.secrets.reload;
+
+import java.time.Duration;
+import java.util.Map;
+
+import io.kubernetes.client.openapi.ApiException;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder;
+import io.kubernetes.client.openapi.models.V1Secret;
+import io.kubernetes.client.openapi.models.V1SecretBuilder;
+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.client.secrets.reload.K8sClientSecretsReloadITUtil.builder;
+import static org.springframework.cloud.kubernetes.client.secrets.reload.K8sClientSecretsReloadITUtil.retrySpec;
+
+final class DataChangesInSecretsReloadDelegate {
+
+ private static final String NAMESPACE = "default";
+
+ /**
+ *
+ * - 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.
+ *
+ */
+ static void testDataChangesInSecretsReload(K3sContainer k3sContainer, String deploymentName) {
+ Commons.assertReloadLogStatements("added secret informer for namespace",
+ "added configmap informer for namespace", deploymentName);
+
+ 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 left-configmap, but without changing its data,
+ // only add a label
+ V1Secret secret = new V1SecretBuilder()
+ .withMetadata(new V1ObjectMetaBuilder().withLabels(Map.of("new-label", "abc")).withNamespace(NAMESPACE)
+ .withName("event-reload").build())
+ .withData(Map.of("application.properties", "from.properties.key=initial".getBytes())).build();
+
+ replaceSecret(secret, "event-reload");
+
+ 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);
+ });
+
+ Commons.waitForLogStatement("Secret event-reload was updated in namespace default", k3sContainer,
+ deploymentName);
+ Commons.waitForLogStatement("data in secret has not changed, will not reload", k3sContainer, deploymentName);
+
+ // change data
+ secret = new V1SecretBuilder()
+ .withMetadata(new V1ObjectMetaBuilder().withLabels(Map.of("new-label", "abc")).withNamespace(NAMESPACE)
+ .withName("event-reload").build())
+ .withData(Map.of("application.properties", "from.properties.key=change-initial".getBytes())).build();
+
+ replaceSecret(secret, "event-reload");
+
+ 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 "change-initial".equals(innerResult);
+ });
+
+ }
+
+ private static void replaceSecret(V1Secret secret, String name) {
+ try {
+ new CoreV1Api().replaceNamespacedSecret(name, NAMESPACE, secret, null, null, null, null);
+ }
+ catch (ApiException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/event/reload/SecretsEventReloadIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/reload/K8sClientSecretsReloadIT.java
similarity index 71%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/event/reload/SecretsEventReloadIT.java
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/reload/K8sClientSecretsReloadIT.java
index 64fe5a56..905afb39 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/event/reload/SecretsEventReloadIT.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/reload/K8sClientSecretsReloadIT.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2020 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,18 +14,13 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.client.secrets.event.reload;
+package org.springframework.cloud.kubernetes.client.secrets.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.V1Deployment;
-import io.kubernetes.client.openapi.models.V1EnvVar;
import io.kubernetes.client.openapi.models.V1Ingress;
import io.kubernetes.client.openapi.models.V1Secret;
import io.kubernetes.client.openapi.models.V1Service;
@@ -33,30 +28,34 @@ import org.junit.jupiter.api.AfterAll;
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.secrets.reload.DataChangesInSecretsReloadDelegate.testDataChangesInSecretsReload;
+import static org.springframework.cloud.kubernetes.client.secrets.reload.K8sClientSecretsReloadITUtil.builder;
+import static org.springframework.cloud.kubernetes.client.secrets.reload.K8sClientSecretsReloadITUtil.patchOne;
+import static org.springframework.cloud.kubernetes.client.secrets.reload.K8sClientSecretsReloadITUtil.retrySpec;
/**
* @author wind57
*/
-class SecretsEventReloadIT {
+class K8sClientSecretsReloadIT {
private static final String PROPERTY_URL = "http://localhost:80/key";
- private static final String IMAGE_NAME = "spring-cloud-kubernetes-client-secrets-event-reload";
+ private static final String IMAGE_NAME = "spring-cloud-kubernetes-client-event-and-polling-reload";
private static final String NAMESPACE = "default";
+ private static final String DEPLOYMENT_NAME = "spring-k8s-client-reload";
+
+ private static final String DOCKER_IMAGE = "docker.io/springcloud/" + IMAGE_NAME + ":" + Commons.pomVersion();
+
private static final K3sContainer K3S = Commons.container();
private static Util util;
@@ -71,30 +70,39 @@ class SecretsEventReloadIT {
util = new Util(K3S);
coreV1Api = new CoreV1Api();
util.setUp(NAMESPACE);
+ configK8sClientIt(Phase.CREATE);
}
@AfterAll
static void afterAll() throws Exception {
+ configK8sClientIt(Phase.DELETE);
Commons.cleanUp(IMAGE_NAME, K3S);
Commons.systemPrune();
}
@Test
void testSecretReload() throws Exception {
- configK8sClientIt(Phase.CREATE, false);
Commons.assertReloadLogStatements("added secret informer for namespace",
- "added configmap informer for namespace", IMAGE_NAME);
+ "added configmap informer for namespace", DEPLOYMENT_NAME);
testSecretEventReload();
- configK8sClientIt(Phase.DELETE, false);
+
+ testAllOther();
+ }
+
+ private void testAllOther() throws Exception {
+ recreateSecret();
+ patchOne(DEPLOYMENT_NAME, NAMESPACE, DOCKER_IMAGE);
+ testSecretReloadConfigDisabled();
+
+ recreateSecret();
+ patchOne(DEPLOYMENT_NAME, NAMESPACE, DOCKER_IMAGE);
+ testDataChangesInSecretsReload(K3S, DEPLOYMENT_NAME);
}
- @Test
void testSecretReloadConfigDisabled() throws Exception {
- configK8sClientIt(Phase.CREATE, true);
Commons.assertReloadLogStatements("added secret informer for namespace",
- "added configmap informer for namespace", IMAGE_NAME);
+ "added configmap informer for namespace", DEPLOYMENT_NAME);
testSecretEventReload();
- configK8sClientIt(Phase.DELETE, true);
}
void testSecretEventReload() throws Exception {
@@ -117,22 +125,18 @@ class SecretsEventReloadIT {
.retryWhen(retrySpec()).block().equals("after-change"));
}
- private void configK8sClientIt(Phase phase, boolean configDisabled) {
- V1Deployment deployment = (V1Deployment) util.yaml("deployment.yaml");
+ private void recreateSecret() {
+ V1Secret secret = (V1Secret) util.yaml("secret.yaml");
+ util.deleteAndWait(NAMESPACE, null, secret);
+ util.createAndWait(NAMESPACE, null, secret);
+ }
+
+ private static void configK8sClientIt(Phase phase) {
+ V1Deployment deployment = (V1Deployment) util.yaml("deployment-with-secret.yaml");
V1Service service = (V1Service) util.yaml("service.yaml");
V1Ingress ingress = (V1Ingress) util.yaml("ingress.yaml");
V1Secret secret = (V1Secret) util.yaml("secret.yaml");
- List envVars = new ArrayList<>(
- Optional.ofNullable(deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv())
- .orElse(List.of()));
-
- if (configDisabled) {
- V1EnvVar disableConfig = new V1EnvVar().name("SPRING_CLOUD_KUBERNETES_CONFIG_ENABLED").value("FALSE");
- envVars.add(disableConfig);
- deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(envVars);
- }
-
if (phase.equals(Phase.CREATE)) {
util.createAndWait(NAMESPACE, null, deployment, service, ingress, true);
util.createAndWait(NAMESPACE, null, secret);
@@ -143,12 +147,4 @@ class SecretsEventReloadIT {
}
}
- private WebClient.Builder builder() {
- return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
- }
-
- private RetryBackoffSpec retrySpec() {
- return Retry.fixedDelay(60, Duration.ofSeconds(2)).filter(Objects::nonNull);
- }
-
}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/reload/K8sClientSecretsReloadITUtil.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/reload/K8sClientSecretsReloadITUtil.java
new file mode 100644
index 00000000..c58051b0
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/reload/K8sClientSecretsReloadITUtil.java
@@ -0,0 +1,102 @@
+/*
+ * 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.secrets.reload;
+
+import java.time.Duration;
+import java.util.Map;
+import java.util.Objects;
+
+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 K8sClientSecretsReloadITUtil {
+
+ private static final Map POD_LABELS = Map.of("app", "spring-k8s-client-reload");
+
+ private static final String BODY_ONE = """
+ {
+ "spec": {
+ "template": {
+ "spec": {
+ "containers": [{
+ "name": "spring-k8s-client-reload",
+ "image": "image_name_here",
+ "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_CLOUD_KUBERNETES_CONFIG_ENABLED",
+ "value": "FALSE"
+ },
+ {
+ "name": "SPRING_PROFILES_ACTIVE",
+ "value": "with-secret"
+ }
+ ]
+ }]
+ }
+ }
+ }
+ }
+ """;
+
+ private K8sClientSecretsReloadITUtil() {
+
+ }
+
+ static WebClient.Builder builder() {
+ return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
+ }
+
+ static RetryBackoffSpec retrySpec() {
+ return Retry.fixedDelay(60, Duration.ofSeconds(2)).filter(Objects::nonNull);
+ }
+
+ static void patchOne(String deploymentName, String namespace, String imageName) {
+ patchWithReplace(imageName, deploymentName, namespace, BODY_ONE, POD_LABELS);
+ }
+
+}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-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-with-secret.yaml
similarity index 71%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-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-with-secret.yaml
index 116475e4..21f9a2e8 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-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-with-secret.yaml
@@ -1,20 +1,20 @@
apiVersion: apps/v1
kind: Deployment
metadata:
- name: spring-cloud-kubernetes-client-secrets-deployment-event-reload
+ name: spring-k8s-client-reload
spec:
selector:
matchLabels:
- app: spring-cloud-kubernetes-client-secrets-event-reload
+ app: spring-k8s-client-reload
template:
metadata:
labels:
- app: spring-cloud-kubernetes-client-secrets-event-reload
+ app: spring-k8s-client-reload
spec:
serviceAccountName: spring-cloud-kubernetes-serviceaccount
containers:
- - name: spring-cloud-kubernetes-client-secrets-event-reload
- image: docker.io/springcloud/spring-cloud-kubernetes-client-secrets-event-reload
+ - name: spring-k8s-client-reload
+ image: docker.io/springcloud/spring-cloud-kubernetes-client-event-and-polling-reload
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
@@ -29,3 +29,5 @@ spec:
env:
- name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD
value: DEBUG
+ - name: SPRING_PROFILES_ACTIVE
+ value: "with-secret"
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/resources/secret.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/secret.yaml
similarity index 100%
rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/resources/secret.yaml
rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-event-and-polling-reload/src/test/resources/secret.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/pom.xml
deleted file mode 100644
index 3057b98f..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/pom.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-
-
-
- org.springframework.cloud
- spring-cloud-kubernetes-integration-tests
- 3.1.0-SNAPSHOT
-
- 4.0.0
-
- spring-cloud-kubernetes-client-secrets-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-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-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/secrets/event/reload/SecretsApp.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/secrets/event/reload/SecretsApp.java
deleted file mode 100644
index 72056a23..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/main/java/org/springframework/cloud/kubernetes/client/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.client.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-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/event/reload/DataChangesInSecretsReloadIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/event/reload/DataChangesInSecretsReloadIT.java
deleted file mode 100644
index bec495be..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/java/org/springframework/cloud/kubernetes/client/secrets/event/reload/DataChangesInSecretsReloadIT.java
+++ /dev/null
@@ -1,213 +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.secrets.event.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 java.util.Set;
-
-import io.kubernetes.client.openapi.ApiException;
-import io.kubernetes.client.openapi.apis.CoreV1Api;
-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.V1ObjectMetaBuilder;
-import io.kubernetes.client.openapi.models.V1Secret;
-import io.kubernetes.client.openapi.models.V1SecretBuilder;
-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;
-
-class DataChangesInSecretsReloadIT {
-
- private static final String IMAGE_NAME = "spring-cloud-kubernetes-client-secrets-event-reload";
-
- private static final String NAMESPACE = "default";
-
- private static final K3sContainer K3S = Commons.container();
-
- private static Util util;
-
- private static CoreV1Api api;
-
- @BeforeAll
- static void beforeAll() throws Exception {
- K3S.start();
- Commons.validateImage(IMAGE_NAME, K3S);
- Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S);
-
- util = new Util(K3S);
- api = new CoreV1Api();
-
- util.setUpClusterWide(NAMESPACE, Set.of(NAMESPACE));
- }
-
- @AfterAll
- static void afterAll() 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();
-
- // we first read the initial value from the secret
- Assertions.assertEquals("initial", result);
-
- // then deploy a new version of left-configmap, but without changing its data,
- // only add a label
- V1Secret secret = new V1SecretBuilder()
- .withMetadata(new V1ObjectMetaBuilder().withLabels(Map.of("new-label", "abc")).withNamespace(NAMESPACE)
- .withName("event-reload").build())
- .withData(Map.of("application.properties", "from.properties.key=initial".getBytes())).build();
-
- replaceSecret(secret, "event-reload");
-
- 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 V1SecretBuilder()
- .withMetadata(new V1ObjectMetaBuilder().withLabels(Map.of("new-label", "abc")).withNamespace(NAMESPACE)
- .withName("event-reload").build())
- .withData(Map.of("application.properties", "from.properties.key=change-initial".getBytes())).build();
-
- replaceSecret(secret, "event-reload");
-
- 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 "change-initial".equals(innerResult);
- });
-
- manifests(Phase.DELETE);
- }
-
- private static void manifests(Phase phase) {
-
- try {
-
- V1Secret secret = (V1Secret) util.yaml("secret.yaml");
- V1Deployment deployment = (V1Deployment) util.yaml("deployment.yaml");
- V1Service service = (V1Service) util.yaml("service.yaml");
- V1Ingress ingress = (V1Ingress) util.yaml("ingress.yaml");
-
- List envVars = new ArrayList<>(
- Optional.ofNullable(deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv())
- .orElse(List.of()));
-
- V1EnvVar configDisabledEnvVar = new V1EnvVar().name("SPRING_CLOUD_KUBERNETES_CONFIG_ENABLED")
- .value("FALSE");
- envVars.add(configDisabledEnvVar);
- 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);
- }
-
- if (phase.equals(Phase.DELETE)) {
- util.deleteAndWait(NAMESPACE, null, secret);
- util.deleteAndWait(NAMESPACE, deployment, service, ingress);
- }
-
- }
- catch (Exception e) {
- throw new RuntimeException(e);
- }
-
- }
-
- 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);
- }
-
- private static void replaceSecret(V1Secret secret, String name) {
- try {
- api.replaceNamespacedSecret(name, NAMESPACE, secret, null, null, null, null);
- }
- catch (ApiException e) {
- throw new RuntimeException(e);
- }
- }
-
-}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/resources/ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/resources/ingress.yaml
deleted file mode 100644
index 7c74d618..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-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-client-secrets-ingress-event-reload
- namespace: default
-spec:
- rules:
- - http:
- paths:
- - path: /
- pathType: Prefix
- backend:
- service:
- name: spring-cloud-kubernetes-client-secrets-event-reload
- port:
- number: 8080
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/resources/logback-test.xml
deleted file mode 100644
index 9e284876..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
- %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
-
-
-
-
-
-
-
-
-
-
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/resources/service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-secrets-event-reload/src/test/resources/service.yaml
deleted file mode 100644
index e1fb85db..00000000
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-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-client-secrets-event-reload
- name: spring-cloud-kubernetes-client-secrets-event-reload
-spec:
- ports:
- - name: http
- port: 8080
- targetPort: 8080
- selector:
- app: spring-cloud-kubernetes-client-secrets-event-reload
- type: ClusterIP