diff --git a/spring-cloud-kubernetes-integration-tests/pom.xml b/spring-cloud-kubernetes-integration-tests/pom.xml
index f762345d..6bd5668e 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/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 88b2ca6d..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;
@@ -138,6 +139,7 @@ class Fabric8EventReloadIT {
testConfigMapPollingReload();
testConfigMapMountPollingReload();
testPollingReloadConfigMapWithBootstrap();
+ testSecretReload();
}
/**
@@ -151,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",
@@ -193,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",
@@ -264,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",
@@ -296,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);
}
@@ -307,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");
@@ -328,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);
@@ -337,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 3fad77ce..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.1.0-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 d7c80dfd..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,183 +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