diff --git a/docs/src/main/asciidoc/property-source-config.adoc b/docs/src/main/asciidoc/property-source-config.adoc
index ec0ac32e..d23d14bd 100644
--- a/docs/src/main/asciidoc/property-source-config.adoc
+++ b/docs/src/main/asciidoc/property-source-config.adoc
@@ -14,7 +14,7 @@ The link:./spring-cloud-kubernetes-config[Spring Cloud Kubernetes Config] projec
during application bootstrapping and triggers hot reloading of beans or Spring context when changes are detected on
observed `ConfigMap` instances.
-The default behavior is to create a `ConfigMapPropertySource` based on a Kubernetes `ConfigMap` that has a `metadata.name` value of either the name of
+The default behavior is to create a `Fabric8ConfigMapPropertySource` based on a Kubernetes `ConfigMap` that has a `metadata.name` value of either the name of
your Spring application (as defined by its `spring.application.name` property) or a custom name defined within the
`bootstrap.properties` file under the following key: `spring.cloud.kubernetes.config.name`.
@@ -300,7 +300,7 @@ Kubernetes has the notion of https://kubernetes.io/docs/concepts/configuration/s
sensitive data such as passwords, OAuth tokens, and so on. This project provides integration with `Secrets` to make secrets
accessible by Spring Boot applications. You can explicitly enable or disable This feature by setting the `spring.cloud.kubernetes.secrets.enabled` property.
-When enabled, the `SecretsPropertySource` looks up Kubernetes for `Secrets` from the following sources:
+When enabled, the `Fabric8SecretsPropertySource` looks up Kubernetes for `Secrets` from the following sources:
. Reading recursively from secrets mounts
. Named after the application (as defined by `spring.application.name`)
diff --git a/pom.xml b/pom.xml
index fd26418c..ad2adf27 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,8 +90,9 @@
spring-cloud-kubernetes-commons
spring-cloud-kubernetes-test-support
spring-cloud-kubernetes-client-autoconfig
+ spring-cloud-kubernetes-client-config
spring-cloud-kubernetes-fabric8-autoconfig
- spring-cloud-kubernetes-config
+ spring-cloud-kubernetes-fabric8-config
spring-cloud-kubernetes-discovery
spring-cloud-starter-kubernetes
spring-cloud-starter-kubernetes-config
diff --git a/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java b/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java
index de269f3e..732bf4b6 100644
--- a/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java
+++ b/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java
@@ -20,9 +20,6 @@ import java.io.IOException;
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.apis.CoreV1Api;
-import io.kubernetes.client.util.ClientBuilder;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
import org.springframework.boot.actuate.autoconfigure.info.ConditionalOnEnabledInfoContributor;
@@ -37,6 +34,8 @@ import org.springframework.cloud.kubernetes.commons.PodUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import static org.springframework.cloud.kubernetes.client.KubernetesClientUtils.kubernetesApiClient;
+
/**
* @author Ryan Baxter
*/
@@ -45,36 +44,11 @@ import org.springframework.context.annotation.Configuration;
@AutoConfigureAfter(KubernetesCommonsAutoConfiguration.class)
public class KubernetesClientAutoConfiguration {
- private static final Log LOG = LogFactory.getLog(KubernetesClientAutoConfiguration.class);
-
- private ApiClient kubernetesApiClient() throws IOException {
- try {
- // Assume we are running in a cluster
- ApiClient apiClient = ClientBuilder.cluster().build();
- io.kubernetes.client.openapi.Configuration.setDefaultApiClient(apiClient);
- LOG.info("Created API client in the cluster.");
- return apiClient;
- }
- catch (Exception e) {
- LOG.info(
- "Could not create the Kubernetes ApiClient in a cluster environment, trying to use a \"standard\" configuration instead.",
- e);
- try {
- ApiClient apiClient = ClientBuilder.standard().build();
- io.kubernetes.client.openapi.Configuration.setDefaultApiClient(apiClient);
- return apiClient;
- }
- catch (IOException e1) {
- LOG.warn("Could not create a Kubernetes ApiClient from either a cluster or standard environment", e1);
- throw e1;
- }
- }
- }
-
@Bean
@ConditionalOnMissingBean
public CoreV1Api coreApi() throws IOException {
- kubernetesApiClient();
+ ApiClient apiClient = kubernetesApiClient();
+ io.kubernetes.client.openapi.Configuration.setDefaultApiClient(apiClient);
return new CoreV1Api();
}
diff --git a/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientUtils.java b/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientUtils.java
new file mode 100644
index 00000000..b9c2f232
--- /dev/null
+++ b/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientUtils.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013-2020 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;
+
+import java.io.IOException;
+
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.util.ClientBuilder;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author Ryan Baxter
+ */
+public final class KubernetesClientUtils {
+
+ private static final Log LOG = LogFactory.getLog(KubernetesClientUtils.class);
+
+ private KubernetesClientUtils() {
+ }
+
+ public static ApiClient kubernetesApiClient() throws IOException {
+ try {
+ // Assume we are running in a cluster
+ ApiClient apiClient = ClientBuilder.cluster().build();
+ LOG.info("Created API client in the cluster.");
+ return apiClient;
+ }
+ catch (Exception e) {
+ LOG.info(
+ "Could not create the Kubernetes ApiClient in a cluster environment, trying to use a \"standard\" configuration instead.",
+ e);
+ try {
+ ApiClient apiClient = ClientBuilder.standard().build();
+ return apiClient;
+ }
+ catch (IOException e1) {
+ LOG.warn("Could not create a Kubernetes ApiClient from either a cluster or standard environment", e1);
+ throw e1;
+ }
+ }
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/profile/KubernetesClientProfileEnvironmentPostProcessor.java b/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/profile/KubernetesClientProfileEnvironmentPostProcessor.java
index d419acd3..767d0823 100644
--- a/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/profile/KubernetesClientProfileEnvironmentPostProcessor.java
+++ b/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/profile/KubernetesClientProfileEnvironmentPostProcessor.java
@@ -22,19 +22,19 @@ import org.springframework.cloud.kubernetes.client.KubernetesClientPodUtils;
import org.springframework.cloud.kubernetes.commons.profile.AbstractKubernetesProfileEnvironmentPostProcessor;
import org.springframework.core.env.Environment;
+import static io.kubernetes.client.util.Config.ENV_SERVICE_HOST;
+
/**
* @author Ryan Baxter
* @author Thomas Vitale
*/
public class KubernetesClientProfileEnvironmentPostProcessor extends AbstractKubernetesProfileEnvironmentPostProcessor {
- protected static final String KUBERNETES_SERVICE_ENV_VAR = "KUBERNETES_SERVICE_HOST";
-
@Override
protected boolean isInsideKubernetes(Environment environment) {
CoreV1Api api = new CoreV1Api();
KubernetesClientPodUtils utils = new KubernetesClientPodUtils(api, environment.getProperty(NAMESPACE_PROPERTY));
- return environment.containsProperty(KUBERNETES_SERVICE_ENV_VAR) || utils.isInsideKubernetes();
+ return environment.containsProperty(ENV_SERVICE_HOST) || utils.isInsideKubernetes();
}
}
diff --git a/spring-cloud-kubernetes-client-config/pom.xml b/spring-cloud-kubernetes-client-config/pom.xml
new file mode 100644
index 00000000..09ca59cf
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/pom.xml
@@ -0,0 +1,91 @@
+
+
+
+ spring-cloud-kubernetes
+ org.springframework.cloud
+ 2.0.0-SNAPSHOT
+
+ 4.0.0
+
+ spring-cloud-kubernetes-client-config
+
+
+ 2.26.3
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-kubernetes-client-autoconfig
+
+
+ org.springframework.cloud
+ spring-cloud-kubernetes-commons
+
+
+ io.kubernetes
+ client-java
+
+
+ io.kubernetes
+ client-java-extended
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+ true
+
+
+ org.springframework.boot
+ spring-boot-actuator
+ true
+
+
+ org.springframework.boot
+ spring-boot-actuator-autoconfigure
+ true
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-bootstrap
+
+
+
+ org.springframework.security
+ spring-security-rsa
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-kubernetes-test-support
+
+
+
+ com.github.tomakehurst
+ wiremock-jre8
+ ${wiremock.version}
+ test
+
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientBootstrapConfiguration.java b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientBootstrapConfiguration.java
new file mode 100644
index 00000000..dcffc012
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientBootstrapConfiguration.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013-2020 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.config;
+
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.kubernetes.client.KubernetesClientAutoConfiguration;
+import org.springframework.cloud.kubernetes.commons.ConditionalOnKubernetesEnabled;
+import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
+import org.springframework.cloud.kubernetes.commons.KubernetesCommonsAutoConfiguration;
+import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties;
+import org.springframework.cloud.kubernetes.commons.config.KubernetesBootstrapConfiguration;
+import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * @author Ryan Baxter
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnKubernetesEnabled
+@AutoConfigureAfter(KubernetesBootstrapConfiguration.class)
+public class KubernetesClientBootstrapConfiguration {
+
+ @Configuration(proxyBeanMethods = false)
+ @Import({ KubernetesCommonsAutoConfiguration.class, KubernetesClientAutoConfiguration.class })
+ protected static class KubernetesPropertySourceConfiguration {
+
+ @Bean
+ @ConditionalOnProperty(name = "spring.cloud.kubernetes.config.enabled", matchIfMissing = true)
+ public KubernetesClientConfigMapPropertySourceLocator configMapPropertySourceLocator(
+ ConfigMapConfigProperties properties, CoreV1Api coreV1Api,
+ KubernetesClientProperties kubernetesClientProperties) {
+ return new KubernetesClientConfigMapPropertySourceLocator(coreV1Api, properties,
+ kubernetesClientProperties);
+ }
+
+ @Bean
+ @ConditionalOnProperty(name = "spring.cloud.kubernetes.secrets.enabled", matchIfMissing = true)
+ public KubernetesClientSecretsPropertySourceLocator secretsPropertySourceLocator(
+ SecretsConfigProperties properties, CoreV1Api coreV1Api,
+ KubernetesClientProperties kubernetesClientProperties) {
+ return new KubernetesClientSecretsPropertySourceLocator(coreV1Api, kubernetesClientProperties, properties);
+ }
+
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySource.java b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySource.java
new file mode 100644
index 00000000..8c0901ce
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySource.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2013-2020 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.config;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import io.kubernetes.client.openapi.ApiException;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.cloud.kubernetes.commons.config.ConfigMapPropertySource;
+import org.springframework.core.env.Environment;
+
+/**
+ * @author Ryan Baxter
+ */
+public class KubernetesClientConfigMapPropertySource extends ConfigMapPropertySource {
+
+ private static final Log LOG = LogFactory.getLog(KubernetesClientConfigMapPropertySource.class);
+
+ public KubernetesClientConfigMapPropertySource(CoreV1Api coreV1Api, String name, String namespace,
+ Environment environment) {
+ super(getName(name, namespace), asObjectMap(getData(coreV1Api, name, namespace, environment)));
+ }
+
+ private static Map getData(CoreV1Api coreV1Api, String name, String namespace,
+ Environment environment) {
+
+ try {
+ List names = new ArrayList<>();
+ names.add(name);
+ if (environment != null) {
+ for (String activeProfile : environment.getActiveProfiles()) {
+ names.add(name + "-" + activeProfile);
+ }
+ }
+ Map result = new LinkedHashMap<>();
+ coreV1Api.listNamespacedConfigMap(namespace, null, null, null, null, null, null, null, null, null)
+ .getItems().stream().filter(cm -> names.contains(cm.getMetadata().getName()))
+ .forEach(map -> result.putAll(processAllEntries(map.getData(), environment)));
+
+ return result;
+ }
+ catch (ApiException e) {
+ LOG.warn("Unable to get ConfigMap " + name + " in namespace " + namespace, e);
+ }
+ return new LinkedHashMap<>();
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocator.java b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocator.java
new file mode 100644
index 00000000..21ea5414
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocator.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2013-2020 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.config;
+
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+
+import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
+import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties;
+import org.springframework.cloud.kubernetes.commons.config.ConfigMapPropertySourceLocator;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.MapPropertySource;
+
+import static org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigUtils.getNamespace;
+
+/**
+ * @author Ryan Baxter
+ */
+public class KubernetesClientConfigMapPropertySourceLocator extends ConfigMapPropertySourceLocator {
+
+ private CoreV1Api coreV1Api;
+
+ private KubernetesClientProperties kubernetesClientProperties;
+
+ public KubernetesClientConfigMapPropertySourceLocator(CoreV1Api coreV1Api, ConfigMapConfigProperties properties,
+ KubernetesClientProperties kubernetesClientProperties) {
+ super(properties);
+ this.coreV1Api = coreV1Api;
+ this.kubernetesClientProperties = kubernetesClientProperties;
+ }
+
+ @Override
+ protected MapPropertySource getMapPropertySource(String name,
+ ConfigMapConfigProperties.NormalizedSource normalizedSource, String configurationTarget,
+ ConfigurableEnvironment environment) {
+ return new KubernetesClientConfigMapPropertySource(coreV1Api, name,
+ getNamespace(normalizedSource, kubernetesClientProperties), environment);
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigUtils.java b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigUtils.java
new file mode 100644
index 00000000..fd02e726
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigUtils.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013-2020 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.config;
+
+import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
+import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties;
+import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties;
+import org.springframework.util.StringUtils;
+
+/**
+ * @author Ryan Baxter
+ */
+public final class KubernetesClientConfigUtils {
+
+ private KubernetesClientConfigUtils() {
+ }
+
+ public static String getNamespace(ConfigMapConfigProperties.NormalizedSource normalizedSource,
+ KubernetesClientProperties kubernetesClientProperties) {
+ if (!StringUtils.hasText(normalizedSource.getNamespace())) {
+ return kubernetesClientProperties.getNamespace();
+ }
+ else {
+ return normalizedSource.getNamespace();
+ }
+ }
+
+ public static String getNamespace(SecretsConfigProperties.NormalizedSource normalizedSource,
+ KubernetesClientProperties kubernetesClientProperties) {
+ if (!StringUtils.hasText(normalizedSource.getNamespace())) {
+ return kubernetesClientProperties.getNamespace();
+ }
+ else {
+ return normalizedSource.getNamespace();
+ }
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySource.java b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySource.java
new file mode 100644
index 00000000..64a88c3d
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySource.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2013-2020 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.config;
+
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1Secret;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.cloud.kubernetes.commons.config.SecretsPropertySource;
+import org.springframework.core.env.Environment;
+import org.springframework.util.StringUtils;
+
+/**
+ * @author Ryan Baxter
+ */
+public class KubernetesClientSecretsPropertySource extends SecretsPropertySource {
+
+ private static final Log LOG = LogFactory.getLog(KubernetesClientSecretsPropertySource.class);
+
+ private CoreV1Api coreV1Api;
+
+ public KubernetesClientSecretsPropertySource(CoreV1Api coreV1Api, String name, String namespace,
+ Environment environment, Map labels) {
+ super(getSourceName(name, namespace), getSourceData(coreV1Api, environment, name, namespace, labels));
+
+ }
+
+ private static Map getSourceData(CoreV1Api api, Environment env, String name, String namespace,
+ Map labels) {
+ Map result = new HashMap<>();
+
+ try {
+ // Read for secrets api (named)
+ if (StringUtils.hasText(name)) {
+ Optional secret;
+ if (!StringUtils.hasText(namespace)) {
+
+ // There could technically be more than one, just return the first
+ secret = api.listSecretForAllNamespaces(null, null, null, null, null, null, null, null, null)
+ .getItems().stream().filter(s -> name.equals(s.getMetadata().getName())).findFirst();
+ }
+ else {
+ secret = api.listNamespacedSecret(namespace, null, null, null, null, null, null, null, null, null)
+ .getItems().stream().filter(s -> name.equals(s.getMetadata().getName())).findFirst();
+ }
+
+ secret.ifPresent(s -> putAll(s, result));
+ }
+
+ // Read for secrets api (label)
+ if (labels != null && !labels.isEmpty()) {
+ if (!StringUtils.hasText(namespace)) {
+ api.listSecretForAllNamespaces(null, null, null, createLabelsSelector(labels), null, null, null,
+ null, null).getItems().forEach(s -> putAll(s, result));
+ }
+ else {
+ api.listNamespacedSecret(namespace, null, null, null, null, createLabelsSelector(labels), null,
+ null, null, null).getItems().forEach(s -> putAll(s, result));
+ }
+ }
+ }
+ catch (Exception e) {
+ LOG.warn("Can't read secret with name: [" + name + "] or labels [" + labels + "] in namespace:[" + namespace
+ + "] (cause: " + e.getMessage() + "). Ignoring", e);
+ }
+
+ return result;
+ }
+
+ private static String createLabelsSelector(Map labels) {
+ StringBuilder selectorString = new StringBuilder();
+ for (String key : labels.keySet()) {
+ if (selectorString.length() != 0) {
+ selectorString.append(",");
+ }
+ selectorString.append(key + "=" + labels.get(key));
+ }
+ return selectorString.toString();
+ }
+
+ private static void putAll(V1Secret secret, Map result) {
+ Map secretData = new HashMap<>();
+ secret.getData().forEach((key, value) -> secretData.put(key, Base64.getEncoder().encodeToString(value)));
+ if (secret != null) {
+ putAll(secretData, result);
+ }
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocator.java b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocator.java
new file mode 100644
index 00000000..eb36d31b
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocator.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2013-2020 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.config;
+
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+
+import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
+import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties;
+import org.springframework.cloud.kubernetes.commons.config.SecretsPropertySourceLocator;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.MapPropertySource;
+
+import static org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigUtils.getNamespace;
+import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.getApplicationName;
+
+/**
+ * @author Ryan Baxter
+ */
+public class KubernetesClientSecretsPropertySourceLocator extends SecretsPropertySourceLocator {
+
+ private CoreV1Api coreV1Api;
+
+ private KubernetesClientProperties kubernetesClientProperties;
+
+ public KubernetesClientSecretsPropertySourceLocator(CoreV1Api coreV1Api,
+ KubernetesClientProperties kubernetesClientProperties, SecretsConfigProperties secretsConfigProperties) {
+ super(secretsConfigProperties);
+ this.coreV1Api = coreV1Api;
+ this.kubernetesClientProperties = kubernetesClientProperties;
+ }
+
+ @Override
+ protected MapPropertySource getPropertySource(ConfigurableEnvironment environment,
+ SecretsConfigProperties.NormalizedSource normalizedSource, String configurationTarget) {
+ return new KubernetesClientSecretsPropertySource(coreV1Api,
+ getApplicationName(environment, normalizedSource.getName(), configurationTarget),
+ getNamespace(normalizedSource, kubernetesClientProperties), environment, normalizedSource.getLabels());
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientConfigReloadAutoConfiguration.java b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientConfigReloadAutoConfiguration.java
new file mode 100644
index 00000000..2c0a38be
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientConfigReloadAutoConfiguration.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2013-2020 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.config.reload;
+
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+
+import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
+import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
+import org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration;
+import org.springframework.cloud.context.refresh.ContextRefresher;
+import org.springframework.cloud.context.restart.RestartEndpoint;
+import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySource;
+import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator;
+import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySource;
+import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator;
+import org.springframework.cloud.kubernetes.commons.ConditionalOnKubernetesEnabled;
+import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadAutoConfiguration;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.commons.config.reload.PollingConfigMapChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.PollingSecretsChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.condition.EventReloadDetectionMode;
+import org.springframework.cloud.kubernetes.commons.config.reload.condition.PollingReloadDetectionMode;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.AbstractEnvironment;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * @author Ryan Baxter
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnKubernetesEnabled
+@ConditionalOnClass(EndpointAutoConfiguration.class)
+@AutoConfigureAfter({ InfoEndpointAutoConfiguration.class, RefreshEndpointAutoConfiguration.class,
+ RefreshAutoConfiguration.class, ConfigReloadAutoConfiguration.class })
+@EnableConfigurationProperties(ConfigReloadProperties.class)
+public class KubernetesClientConfigReloadAutoConfiguration {
+
+ /**
+ * Configuration reload must be enabled explicitly.
+ */
+ @ConditionalOnProperty("spring.cloud.kubernetes.reload.enabled")
+ @ConditionalOnClass({ RestartEndpoint.class, ContextRefresher.class })
+ @EnableScheduling
+ @EnableAsync
+ protected static class ConfigReloadAutoConfigurationBeans {
+
+ /**
+ * Polling configMap ConfigurationChangeDetector.
+ * @param properties config reload properties
+ * @param strategy configuration update strategy
+ * @param configMapPropertySourceLocator configMap property source locator
+ * @return a bean that listen to configuration changes and fire a reload.
+ */
+ @Bean
+ @ConditionalOnBean(KubernetesClientConfigMapPropertySourceLocator.class)
+ @Conditional(PollingReloadDetectionMode.class)
+ public ConfigurationChangeDetector configMapPropertyChangePollingWatcher(ConfigReloadProperties properties,
+ ConfigurationUpdateStrategy strategy,
+ KubernetesClientConfigMapPropertySourceLocator configMapPropertySourceLocator,
+ AbstractEnvironment environment) {
+
+ return new PollingConfigMapChangeDetector(environment, properties, strategy,
+ KubernetesClientConfigMapPropertySource.class, configMapPropertySourceLocator);
+ }
+
+ /**
+ * Polling secrets ConfigurationChangeDetector.
+ * @param properties config reload properties
+ * @param strategy configuration update strategy
+ * @param secretsPropertySourceLocator secrets property source locator
+ * @return a bean that listen to configuration changes and fire a reload.
+ */
+ @Bean
+ @ConditionalOnBean(KubernetesClientSecretsPropertySourceLocator.class)
+ @Conditional(PollingReloadDetectionMode.class)
+ public ConfigurationChangeDetector secretsPropertyChangePollingWatcher(ConfigReloadProperties properties,
+ ConfigurationUpdateStrategy strategy,
+ KubernetesClientSecretsPropertySourceLocator secretsPropertySourceLocator,
+ AbstractEnvironment environment) {
+
+ return new PollingSecretsChangeDetector(environment, properties, strategy,
+ KubernetesClientSecretsPropertySource.class, secretsPropertySourceLocator);
+ }
+
+ /**
+ * Event Based configMap ConfigurationChangeDetector.
+ * @param properties config reload properties
+ * @param strategy configuration update strategy
+ * @param configMapPropertySourceLocator configMap property source locator
+ * @return a bean that listen to configMap change events and fire a reload.
+ */
+ @Bean
+ @ConditionalOnBean(KubernetesClientConfigMapPropertySourceLocator.class)
+ @Conditional(EventReloadDetectionMode.class)
+ public ConfigurationChangeDetector configMapPropertyChangeEventWatcher(ConfigReloadProperties properties,
+ ConfigurationUpdateStrategy strategy,
+ KubernetesClientConfigMapPropertySourceLocator configMapPropertySourceLocator,
+ AbstractEnvironment environment, CoreV1Api coreV1Api,
+ KubernetesClientProperties kubernetesClientProperties) {
+
+ return new KubernetesClientEventBasedConfigMapChangeDetector(coreV1Api, environment, properties, strategy,
+ configMapPropertySourceLocator, kubernetesClientProperties);
+ }
+
+ /**
+ * Event Based secrets ConfigurationChangeDetector.
+ * @param properties config reload properties
+ * @param strategy configuration update strategy
+ * @param secretsPropertySourceLocator secrets property source locator
+ * @return a bean that listen to secrets change events and fire a reload.
+ */
+ @Bean
+ @ConditionalOnBean(KubernetesClientSecretsPropertySourceLocator.class)
+ @Conditional(EventReloadDetectionMode.class)
+ public ConfigurationChangeDetector secretsPropertyChangeEventWatcher(ConfigReloadProperties properties,
+ ConfigurationUpdateStrategy strategy,
+ KubernetesClientSecretsPropertySourceLocator secretsPropertySourceLocator,
+ AbstractEnvironment environment, CoreV1Api coreV1Api,
+ KubernetesClientProperties kubernetesClientProperties) {
+
+ return new KubernetesClientEventBasedSecretsChangeDetector(coreV1Api, environment, properties, strategy,
+ secretsPropertySourceLocator, kubernetesClientProperties);
+ }
+
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientEventBasedConfigMapChangeDetector.java b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientEventBasedConfigMapChangeDetector.java
new file mode 100644
index 00000000..5b340484
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientEventBasedConfigMapChangeDetector.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2013-2020 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.config.reload;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import io.kubernetes.client.informer.ResourceEventHandler;
+import io.kubernetes.client.informer.SharedIndexInformer;
+import io.kubernetes.client.informer.SharedInformerFactory;
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1ConfigMap;
+import io.kubernetes.client.openapi.models.V1ConfigMapList;
+import io.kubernetes.client.util.CallGeneratorParams;
+import okhttp3.OkHttpClient;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySource;
+import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator;
+import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.core.env.ConfigurableEnvironment;
+
+import static org.springframework.cloud.kubernetes.client.KubernetesClientUtils.kubernetesApiClient;
+
+/**
+ * @author Ryan Baxter
+ */
+public class KubernetesClientEventBasedConfigMapChangeDetector extends ConfigurationChangeDetector {
+
+ private static final Log LOG = LogFactory.getLog(KubernetesClientEventBasedConfigMapChangeDetector.class);
+
+ private CoreV1Api coreV1Api = null;
+
+ private KubernetesClientConfigMapPropertySourceLocator propertySourceLocator;
+
+ private SharedInformerFactory factory;
+
+ private KubernetesClientProperties kubernetesClientProperties;
+
+ public KubernetesClientEventBasedConfigMapChangeDetector(CoreV1Api coreV1Api, ConfigurableEnvironment environment,
+ ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
+ KubernetesClientConfigMapPropertySourceLocator propertySourceLocator,
+ KubernetesClientProperties kubernetesClientProperties) {
+ super(environment, properties, strategy);
+ this.propertySourceLocator = propertySourceLocator;
+ this.coreV1Api = coreV1Api;
+ this.factory = new SharedInformerFactory();
+ this.kubernetesClientProperties = kubernetesClientProperties;
+ }
+
+ public KubernetesClientEventBasedConfigMapChangeDetector(ConfigurableEnvironment environment,
+ ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
+ KubernetesClientConfigMapPropertySourceLocator propertySourceLocator,
+ KubernetesClientProperties kubernetesClientProperties) {
+ super(environment, properties, strategy);
+ this.propertySourceLocator = propertySourceLocator;
+ this.kubernetesClientProperties = kubernetesClientProperties;
+ try {
+ ApiClient apiClient = kubernetesApiClient();
+ OkHttpClient httpClient = apiClient.getHttpClient().newBuilder().readTimeout(0, TimeUnit.SECONDS).build();
+ apiClient.setHttpClient(httpClient);
+ this.coreV1Api = new CoreV1Api(apiClient);
+ }
+ catch (IOException e) {
+ LOG.error("Failed to create Kubernetes API client. Event based ConfigMap monitoring will not work", e);
+ }
+ this.factory = new SharedInformerFactory();
+ }
+
+ @PostConstruct
+ public void watch() {
+ if (coreV1Api != null && this.properties.isMonitoringConfigMaps()) {
+ SharedIndexInformer configMapInformer = factory.sharedIndexInformerFor(
+ (CallGeneratorParams params) -> coreV1Api.listNamespacedConfigMapCall(
+ kubernetesClientProperties.getNamespace(), null, null, null, null, null, null,
+ params.resourceVersion, params.timeoutSeconds, params.watch, null),
+ V1ConfigMap.class, V1ConfigMapList.class);
+ configMapInformer.addEventHandler(new ResourceEventHandler() {
+ @Override
+ public void onAdd(V1ConfigMap obj) {
+ LOG.info("CongifMap " + obj.getMetadata().getName() + " was added.");
+ onEvent(obj);
+ }
+
+ @Override
+ public void onUpdate(V1ConfigMap oldObj, V1ConfigMap newObj) {
+ LOG.info("ConfigMap " + newObj.getMetadata().getName() + " was added.");
+ onEvent(newObj);
+ }
+
+ @Override
+ public void onDelete(V1ConfigMap obj, boolean deletedFinalStateUnknown) {
+ LOG.info("ConfigMap " + obj.getMetadata() + " was deleted.");
+ onEvent(obj);
+ }
+ });
+ factory.startAllRegisteredInformers();
+ }
+ }
+
+ @PreDestroy
+ public void unwatch() {
+ factory.stopAllRegisteredInformers();
+ }
+
+ private void onEvent(V1ConfigMap configMap) {
+ boolean changed = changed(locateMapPropertySources(this.propertySourceLocator, this.environment),
+ findPropertySources(KubernetesClientConfigMapPropertySource.class));
+ if (changed) {
+ LOG.info("Configuration change detected, reloading properties.");
+ reloadProperties();
+ }
+ else {
+ LOG.warn("Configuration change was not detected.");
+ }
+
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientEventBasedSecretsChangeDetector.java b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientEventBasedSecretsChangeDetector.java
new file mode 100644
index 00000000..be295b94
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientEventBasedSecretsChangeDetector.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2013-2020 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.config.reload;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.PostConstruct;
+
+import io.kubernetes.client.informer.ResourceEventHandler;
+import io.kubernetes.client.informer.SharedIndexInformer;
+import io.kubernetes.client.informer.SharedInformerFactory;
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1Secret;
+import io.kubernetes.client.openapi.models.V1SecretList;
+import io.kubernetes.client.util.CallGeneratorParams;
+import okhttp3.OkHttpClient;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySource;
+import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator;
+import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.core.env.ConfigurableEnvironment;
+
+import static org.springframework.cloud.kubernetes.client.KubernetesClientUtils.kubernetesApiClient;
+
+/**
+ * @author Ryan Baxter
+ */
+public class KubernetesClientEventBasedSecretsChangeDetector extends ConfigurationChangeDetector {
+
+ private static final Log LOG = LogFactory.getLog(KubernetesClientEventBasedSecretsChangeDetector.class);
+
+ private CoreV1Api coreV1Api;
+
+ private KubernetesClientSecretsPropertySourceLocator propertySourceLocator;
+
+ private SharedInformerFactory factory;
+
+ private KubernetesClientProperties kubernetesClientProperties;
+
+ public KubernetesClientEventBasedSecretsChangeDetector(CoreV1Api coreV1Api, ConfigurableEnvironment environment,
+ ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
+ KubernetesClientSecretsPropertySourceLocator propertySourceLocator,
+ KubernetesClientProperties kubernetesClientProperties) {
+ super(environment, properties, strategy);
+ this.propertySourceLocator = propertySourceLocator;
+ this.factory = new SharedInformerFactory();
+ this.coreV1Api = coreV1Api;
+ this.kubernetesClientProperties = kubernetesClientProperties;
+ }
+
+ public KubernetesClientEventBasedSecretsChangeDetector(ConfigurableEnvironment environment,
+ ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
+ KubernetesClientSecretsPropertySourceLocator propertySourceLocator,
+ KubernetesClientProperties kubernetesClientProperties) {
+ super(environment, properties, strategy);
+ this.propertySourceLocator = propertySourceLocator;
+ this.factory = new SharedInformerFactory();
+ this.kubernetesClientProperties = kubernetesClientProperties;
+ try {
+ ApiClient apiClient = kubernetesApiClient();
+ OkHttpClient httpClient = apiClient.getHttpClient().newBuilder().readTimeout(0, TimeUnit.SECONDS).build();
+ apiClient.setHttpClient(httpClient);
+ this.coreV1Api = new CoreV1Api(apiClient);
+ }
+ catch (IOException e) {
+ LOG.error("Failed to create Kubernetes API client. Event based ConfigMap monitoring will not work", e);
+ }
+ }
+
+ @PostConstruct
+ public void watch() {
+ if (coreV1Api != null && this.properties.isMonitoringSecrets()) {
+ SharedIndexInformer configMapInformer = factory.sharedIndexInformerFor(
+ (CallGeneratorParams params) -> coreV1Api.listNamespacedSecretCall(
+ kubernetesClientProperties.getNamespace(), null, null, null, null, null, null,
+ params.resourceVersion, params.timeoutSeconds, params.watch, null),
+ V1Secret.class, V1SecretList.class);
+ configMapInformer.addEventHandler(new ResourceEventHandler() {
+ @Override
+ public void onAdd(V1Secret obj) {
+ LOG.info("Secret " + obj.getMetadata().getName() + " was added.");
+ onEvent(obj);
+ }
+
+ @Override
+ public void onUpdate(V1Secret oldObj, V1Secret newObj) {
+ LOG.info("Secret " + newObj.getMetadata().getName() + " was added.");
+ onEvent(newObj);
+ }
+
+ @Override
+ public void onDelete(V1Secret obj, boolean deletedFinalStateUnknown) {
+ LOG.info("Secret " + obj.getMetadata() + " was deleted.");
+ onEvent(obj);
+ }
+ });
+ factory.startAllRegisteredInformers();
+ }
+ }
+
+ private void onEvent(V1Secret secret) {
+ boolean changed = changed(locateMapPropertySources(this.propertySourceLocator, this.environment),
+ findPropertySources(KubernetesClientSecretsPropertySource.class));
+ if (changed) {
+ this.log.info("Detected change in secrets");
+ reloadProperties();
+ }
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/main/resources/META-INF/spring.factories b/spring-cloud-kubernetes-client-config/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..067e1fb4
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,4 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+org.springframework.cloud.kubernetes.client.config.reload.KubernetesClientConfigReloadAutoConfiguration
+org.springframework.cloud.bootstrap.BootstrapConfiguration=\
+org.springframework.cloud.kubernetes.client.config.KubernetesClientBootstrapConfiguration
diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorTests.java
new file mode 100644
index 00000000..c668480e
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorTests.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2013-2020 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.config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.openapi.Configuration;
+import io.kubernetes.client.openapi.JSON;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1ConfigMapBuilder;
+import io.kubernetes.client.openapi.models.V1ConfigMapList;
+import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder;
+import io.kubernetes.client.util.ClientBuilder;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
+import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties;
+import org.springframework.core.env.PropertySource;
+import org.springframework.mock.env.MockEnvironment;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Ryan Baxter
+ */
+class KubernetesClientConfigMapPropertySourceLocatorTests {
+
+ private static final V1ConfigMapList PROPERTIES_CONFIGMAP_LIST = new V1ConfigMapList()
+ .addItemsItem(
+ new V1ConfigMapBuilder()
+ .withMetadata(new V1ObjectMetaBuilder().withName("bootstrap-640").withNamespace("default")
+ .withResourceVersion("1").build())
+ .addToData("application.properties",
+ "spring.cloud.kubernetes.configuration.watcher.refreshDelay=0\n"
+ + "logging.level.org.springframework.cloud.kubernetes=TRACE")
+ .build());
+
+ private static final String API = "/api/v1/namespaces/default/configmaps";
+
+ private static WireMockServer wireMockServer;
+
+ @BeforeAll
+ public static void setup() {
+ wireMockServer = new WireMockServer(options().dynamicPort());
+
+ wireMockServer.start();
+ WireMock.configureFor("localhost", wireMockServer.port());
+
+ ApiClient client = new ClientBuilder().setBasePath("http://localhost:" + wireMockServer.port()).build();
+ client.setDebugging(true);
+ Configuration.setDefaultApiClient(client);
+ }
+
+ @AfterAll
+ public static void after() {
+ wireMockServer.stop();
+ }
+
+ @AfterEach
+ public void afterEach() {
+ WireMock.reset();
+ }
+
+ @Test
+ void locateWithoutSources() {
+ CoreV1Api api = new CoreV1Api();
+ stubFor(get(API)
+ .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(PROPERTIES_CONFIGMAP_LIST))));
+ ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties();
+ configMapConfigProperties.setName("bootstrap-640");
+ KubernetesClientProperties kubernetesClientProperties = new KubernetesClientProperties();
+ kubernetesClientProperties.setNamespace("default");
+ PropertySource propertySource = new KubernetesClientConfigMapPropertySourceLocator(api,
+ configMapConfigProperties, kubernetesClientProperties).locate(new MockEnvironment());
+ assertThat(propertySource.containsProperty("spring.cloud.kubernetes.configuration.watcher.refreshDelay"))
+ .isTrue();
+ }
+
+ @Test
+ void locateWithSources() {
+ CoreV1Api api = new CoreV1Api();
+ stubFor(get(API)
+ .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(PROPERTIES_CONFIGMAP_LIST))));
+ ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties();
+ configMapConfigProperties.setName("fake-name");
+ ConfigMapConfigProperties.Source source1 = new ConfigMapConfigProperties.Source();
+ source1.setName("bootstrap-640");
+ source1.setNamespace("default");
+ List sources = new ArrayList<>();
+ sources.add(source1);
+ configMapConfigProperties.setSources(sources);
+ KubernetesClientProperties kubernetesClientProperties = new KubernetesClientProperties();
+ kubernetesClientProperties.setNamespace("dev");
+ PropertySource propertySource = new KubernetesClientConfigMapPropertySourceLocator(api,
+ configMapConfigProperties, kubernetesClientProperties).locate(new MockEnvironment());
+ assertThat(propertySource.containsProperty("spring.cloud.kubernetes.configuration.watcher.refreshDelay"))
+ .isTrue();
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceTests.java
new file mode 100644
index 00000000..f4def1fe
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceTests.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2013-2020 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.config;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.openapi.Configuration;
+import io.kubernetes.client.openapi.JSON;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1ConfigMapBuilder;
+import io.kubernetes.client.openapi.models.V1ConfigMapList;
+import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder;
+import io.kubernetes.client.util.ClientBuilder;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.mock.env.MockEnvironment;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.verify;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Ryan Baxter
+ */
+class KubernetesClientConfigMapPropertySourceTests {
+
+ private static final V1ConfigMapList PROPERTIES_CONFIGMAP_LIST = new V1ConfigMapList()
+ .addItemsItem(
+ new V1ConfigMapBuilder()
+ .withMetadata(new V1ObjectMetaBuilder().withName("bootstrap-640").withNamespace("default")
+ .withResourceVersion("1").build())
+ .addToData("application.properties",
+ "spring.cloud.kubernetes.configuration.watcher.refreshDelay=0\n"
+ + "logging.level.org.springframework.cloud.kubernetes=TRACE")
+ .build());
+
+ private static final V1ConfigMapList YAML_CONFIGMAP_LIST = new V1ConfigMapList()
+ .addItemsItem(new V1ConfigMapBuilder()
+ .withMetadata(new V1ObjectMetaBuilder().withName("bootstrap-641").withNamespace("default")
+ .withResourceVersion("1").build())
+ .addToData("application.yaml",
+ "dummy:\n property:\n string2: \"a\"\n int2: 1\n bool2: true\n")
+ .build());
+
+ private static final String API = "/api/v1/namespaces/default/configmaps";
+
+ private static WireMockServer wireMockServer;
+
+ @BeforeAll
+ public static void setup() {
+ wireMockServer = new WireMockServer(options().dynamicPort());
+
+ wireMockServer.start();
+ WireMock.configureFor("localhost", wireMockServer.port());
+
+ ApiClient client = new ClientBuilder().setBasePath("http://localhost:" + wireMockServer.port()).build();
+ client.setDebugging(true);
+ Configuration.setDefaultApiClient(client);
+ }
+
+ @AfterAll
+ public static void after() {
+ wireMockServer.stop();
+ }
+
+ @AfterEach
+ public void afterEach() {
+ WireMock.reset();
+ }
+
+ @Test
+ public void propertiesFile() {
+ CoreV1Api api = new CoreV1Api();
+ stubFor(get(API)
+ .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(PROPERTIES_CONFIGMAP_LIST))));
+ KubernetesClientConfigMapPropertySource propertySource = new KubernetesClientConfigMapPropertySource(api,
+ "bootstrap-640", "default", new MockEnvironment());
+ verify(getRequestedFor(urlEqualTo(API)));
+ assertThat(propertySource.containsProperty("spring.cloud.kubernetes.configuration.watcher.refreshDelay"))
+ .isTrue();
+ assertThat(propertySource.getProperty("spring.cloud.kubernetes.configuration.watcher.refreshDelay"))
+ .isEqualTo("0");
+ assertThat(propertySource.containsProperty("logging.level.org.springframework.cloud.kubernetes")).isTrue();
+ assertThat(propertySource.getProperty("logging.level.org.springframework.cloud.kubernetes")).isEqualTo("TRACE");
+
+ }
+
+ @Test
+ public void yamlFile() {
+ CoreV1Api api = new CoreV1Api();
+ stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(YAML_CONFIGMAP_LIST))));
+ KubernetesClientConfigMapPropertySource propertySource = new KubernetesClientConfigMapPropertySource(api,
+ "bootstrap-641", "default", new MockEnvironment());
+ verify(getRequestedFor(urlEqualTo(API)));
+ assertThat(propertySource.containsProperty("dummy.property.string2")).isTrue();
+ assertThat(propertySource.getProperty("dummy.property.string2")).isEqualTo("a");
+ assertThat(propertySource.containsProperty("dummy.property.int2")).isTrue();
+ assertThat(propertySource.getProperty("dummy.property.int2")).isEqualTo(1);
+ assertThat(propertySource.containsProperty("dummy.property.bool2")).isTrue();
+ assertThat(propertySource.getProperty("dummy.property.bool2")).isEqualTo(true);
+
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocatorTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocatorTests.java
new file mode 100644
index 00000000..4c7eb5b8
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocatorTests.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2013-2020 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.config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.openapi.Configuration;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.util.ClientBuilder;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
+import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties;
+import org.springframework.core.env.PropertySource;
+import org.springframework.mock.env.MockEnvironment;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Ryan Baxter
+ */
+class KubernetesClientSecretsPropertySourceLocatorTests {
+
+ private static final String LIST_API = "/api/v1/secrets";
+
+ private static final String LIST_API_WITH_LABEL = "/api/v1/secrets?labelSelector=spring.cloud.kubernetes.secret%3Dtrue";
+
+ private static final String LIST_BODY = "{\n" + "\t\"kind\": \"SecretList\",\n" + "\t\"apiVersion\": \"v1\",\n"
+ + "\t\"metadata\": {\n" + "\t\t\"selfLink\": \"/api/v1/secrets\",\n"
+ + "\t\t\"resourceVersion\": \"163035\"\n" + "\t},\n" + "\t\"items\": [{\n" + "\t\t\t\"metadata\": {\n"
+ + "\t\t\t\t\"name\": \"db-secret\",\n" + "\t\t\t\t\"namespace\": \"default\",\n"
+ + "\t\t\t\t\"selfLink\": \"/api/v1/namespaces/default/secrets/db-secret\",\n"
+ + "\t\t\t\t\"uid\": \"59ba8e6a-a2d4-416c-b016-22597c193f23\",\n"
+ + "\t\t\t\t\"resourceVersion\": \"1462\",\n" + "\t\t\t\t\"creationTimestamp\": \"2020-10-28T14:45:02Z\",\n"
+ + "\t\t\t\t\"labels\": {\n" + "\t\t\t\t\t\"spring.cloud.kubernetes.secret\": \"true\"\n" + "\t\t\t\t}\n"
+ + "\t\t\t},\n" + "\t\t\t\"data\": {\n" + "\t\t\t\t\"password\": \"cDQ1NXcwcmQ=\",\n"
+ + "\t\t\t\t\"username\": \"dXNlcg==\"\n" + "\t\t\t},\n" + "\t\t\t\"type\": \"Opaque\"\n" + "\t\t},\n"
+ + "\t\t{\n" + "\t\t\t\"metadata\": {\n" + "\t\t\t\t\"name\": \"rabbit-password\",\n"
+ + "\t\t\t\t\"namespace\": \"default\",\n"
+ + "\t\t\t\t\"selfLink\": \"/api/v1/namespaces/default/secrets/rabbit-password\",\n"
+ + "\t\t\t\t\"uid\": \"bc211cb4-e7ff-4556-b26e-c54911301740\",\n"
+ + "\t\t\t\t\"resourceVersion\": \"162708\",\n"
+ + "\t\t\t\t\"creationTimestamp\": \"2020-10-29T19:47:36Z\",\n" + "\t\t\t\t\"labels\": {\n"
+ + "\t\t\t\t\t\"spring.cloud.kubernetes.secret\": \"true\"\n" + "\t\t\t\t},\n"
+ + "\t\t\t\t\"annotations\": {\n"
+ + "\t\t\t\t\t\"kubectl.kubernetes.io/last-applied-configuration\": \"{\\\"apiVersion\\\":\\\"v1\\\",\\\"data\\\":{\\\"spring.rabbitmq.password\\\":\\\"password\\\"},\\\"kind\\\":\\\"Secret\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"labels\\\":{\\\"spring.cloud.kubernetes.secret\\\":\\\"true\\\"},\\\"name\\\":\\\"rabbit-password\\\",\\\"namespace\\\":\\\"default\\\"},\\\"type\\\":\\\"Opaque\\\"}\\n\"\n"
+ + "\t\t\t\t}\n" + "\t\t\t},\n" + "\t\t\t\"data\": {\n"
+ + "\t\t\t\t\"spring.rabbitmq.password\": \"cGFzc3dvcmQ=\"\n" + "\t\t\t},\n" + "\t\t\t\"type\": \"Opaque\"\n"
+ + "\t\t}\n" + "\t]\n" + "}";
+
+ private static WireMockServer wireMockServer;
+
+ @BeforeAll
+ public static void setup() {
+ wireMockServer = new WireMockServer(options().dynamicPort());
+
+ wireMockServer.start();
+ WireMock.configureFor("localhost", wireMockServer.port());
+
+ ApiClient client = new ClientBuilder().setBasePath("http://localhost:" + wireMockServer.port()).build();
+ client.setDebugging(true);
+ Configuration.setDefaultApiClient(client);
+ }
+
+ @AfterAll
+ public static void after() {
+ wireMockServer.stop();
+ }
+
+ @AfterEach
+ public void afterEach() {
+ WireMock.reset();
+ }
+
+ @Test
+ void getLocateWithSources() {
+ CoreV1Api api = new CoreV1Api();
+ stubFor(get(LIST_API).willReturn(aResponse().withStatus(200).withBody(LIST_BODY)));
+ SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties();
+ SecretsConfigProperties.Source source1 = new SecretsConfigProperties.Source();
+ source1.setName("db-secret");
+ source1.setNamespace("");
+ SecretsConfigProperties.Source source2 = new SecretsConfigProperties.Source();
+ source2.setName("rabbit-password");
+ source2.setNamespace("");
+ List sources = new ArrayList<>();
+ sources.add(source1);
+ sources.add(source2);
+ secretsConfigProperties.setName("app");
+ secretsConfigProperties.setNamespace("");
+ secretsConfigProperties.setSources(sources);
+ secretsConfigProperties.setEnableApi(true);
+ PropertySource propertySource = new KubernetesClientSecretsPropertySourceLocator(api,
+ new KubernetesClientProperties(), secretsConfigProperties).locate(new MockEnvironment());
+ assertThat(propertySource.containsProperty("password")).isTrue();
+ assertThat(propertySource.getProperty("password")).isEqualTo("p455w0rd");
+ }
+
+ @Test
+ void getLocateWithOutSources() {
+ CoreV1Api api = new CoreV1Api();
+ stubFor(get(LIST_API).willReturn(aResponse().withStatus(200).withBody(LIST_BODY)));
+ SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties();
+ secretsConfigProperties.setName("db-secret");
+ secretsConfigProperties.setNamespace("");
+ secretsConfigProperties.setEnableApi(true);
+ PropertySource propertySource = new KubernetesClientSecretsPropertySourceLocator(api,
+ new KubernetesClientProperties(), secretsConfigProperties).locate(new MockEnvironment());
+ assertThat(propertySource.containsProperty("password")).isTrue();
+ assertThat(propertySource.getProperty("password")).isEqualTo("p455w0rd");
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceTests.java
new file mode 100644
index 00000000..d94ce47c
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceTests.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2013-2020 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.config;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.openapi.Configuration;
+import io.kubernetes.client.openapi.JSON;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder;
+import io.kubernetes.client.openapi.models.V1SecretBuilder;
+import io.kubernetes.client.openapi.models.V1SecretList;
+import io.kubernetes.client.openapi.models.V1SecretListBuilder;
+import io.kubernetes.client.util.ClientBuilder;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.mock.env.MockEnvironment;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Ryan Baxter
+ */
+class KubernetesClientSecretsPropertySourceTests {
+
+ private static final String API = "/api/v1/namespaces/default/secrets";
+
+ private static final V1SecretList SECRET_LIST = new V1SecretListBuilder().addToItems(new V1SecretBuilder()
+ .withMetadata(new V1ObjectMetaBuilder().withName("db-secret").withResourceVersion("0")
+ .withNamespace("default").build())
+ .addToData("password", "p455w0rd".getBytes()).addToData("username", "user".getBytes()).build()).build();
+
+ private static final String LIST_API = "/api/v1/secrets";
+
+ private static final String LIST_API_WITH_LABEL = "/api/v1/secrets?labelSelector=spring.cloud.kubernetes.secret%3Dtrue";
+
+ private static final String LIST_BODY = "{\n" + "\t\"kind\": \"SecretList\",\n" + "\t\"apiVersion\": \"v1\",\n"
+ + "\t\"metadata\": {\n" + "\t\t\"selfLink\": \"/api/v1/secrets\",\n"
+ + "\t\t\"resourceVersion\": \"163035\"\n" + "\t},\n" + "\t\"items\": [{\n" + "\t\t\t\"metadata\": {\n"
+ + "\t\t\t\t\"name\": \"db-secret\",\n" + "\t\t\t\t\"namespace\": \"default\",\n"
+ + "\t\t\t\t\"selfLink\": \"/api/v1/namespaces/default/secrets/db-secret\",\n"
+ + "\t\t\t\t\"uid\": \"59ba8e6a-a2d4-416c-b016-22597c193f23\",\n"
+ + "\t\t\t\t\"resourceVersion\": \"1462\",\n" + "\t\t\t\t\"creationTimestamp\": \"2020-10-28T14:45:02Z\",\n"
+ + "\t\t\t\t\"labels\": {\n" + "\t\t\t\t\t\"spring.cloud.kubernetes.secret\": \"true\"\n" + "\t\t\t\t}\n"
+ + "\t\t\t},\n" + "\t\t\t\"data\": {\n" + "\t\t\t\t\"password\": \"cDQ1NXcwcmQ=\",\n"
+ + "\t\t\t\t\"username\": \"dXNlcg==\"\n" + "\t\t\t},\n" + "\t\t\t\"type\": \"Opaque\"\n" + "\t\t},\n"
+ + "\t\t{\n" + "\t\t\t\"metadata\": {\n" + "\t\t\t\t\"name\": \"rabbit-password\",\n"
+ + "\t\t\t\t\"namespace\": \"default\",\n"
+ + "\t\t\t\t\"selfLink\": \"/api/v1/namespaces/default/secrets/rabbit-password\",\n"
+ + "\t\t\t\t\"uid\": \"bc211cb4-e7ff-4556-b26e-c54911301740\",\n"
+ + "\t\t\t\t\"resourceVersion\": \"162708\",\n"
+ + "\t\t\t\t\"creationTimestamp\": \"2020-10-29T19:47:36Z\",\n" + "\t\t\t\t\"labels\": {\n"
+ + "\t\t\t\t\t\"spring.cloud.kubernetes.secret\": \"true\"\n" + "\t\t\t\t},\n"
+ + "\t\t\t\t\"annotations\": {\n"
+ + "\t\t\t\t\t\"kubectl.kubernetes.io/last-applied-configuration\": \"{\\\"apiVersion\\\":\\\"v1\\\",\\\"data\\\":{\\\"spring.rabbitmq.password\\\":\\\"password\\\"},\\\"kind\\\":\\\"Secret\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"labels\\\":{\\\"spring.cloud.kubernetes.secret\\\":\\\"true\\\"},\\\"name\\\":\\\"rabbit-password\\\",\\\"namespace\\\":\\\"default\\\"},\\\"type\\\":\\\"Opaque\\\"}\\n\"\n"
+ + "\t\t\t\t}\n" + "\t\t\t},\n" + "\t\t\t\"data\": {\n"
+ + "\t\t\t\t\"spring.rabbitmq.password\": \"cGFzc3dvcmQ=\"\n" + "\t\t\t},\n" + "\t\t\t\"type\": \"Opaque\"\n"
+ + "\t\t}\n" + "\t]\n" + "}";
+
+ private static WireMockServer wireMockServer;
+
+ @BeforeAll
+ public static void setup() {
+ wireMockServer = new WireMockServer(options().dynamicPort());
+
+ wireMockServer.start();
+ WireMock.configureFor("localhost", wireMockServer.port());
+
+ ApiClient client = new ClientBuilder().setBasePath("http://localhost:" + wireMockServer.port()).build();
+ client.setDebugging(true);
+ Configuration.setDefaultApiClient(client);
+ }
+
+ @AfterAll
+ public static void after() {
+ wireMockServer.stop();
+ }
+
+ @AfterEach
+ public void afterEach() {
+ WireMock.reset();
+ }
+
+ @Test
+ public void secretsTest() {
+ CoreV1Api api = new CoreV1Api();
+ stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(SECRET_LIST))));
+ KubernetesClientSecretsPropertySource propertySource = new KubernetesClientSecretsPropertySource(api,
+ "db-secret", "default", new MockEnvironment(), new HashMap<>());
+ assertThat(propertySource.containsProperty("password")).isTrue();
+ assertThat(propertySource.getProperty("password")).isEqualTo("p455w0rd");
+ assertThat(propertySource.containsProperty("username")).isTrue();
+ assertThat(propertySource.getProperty("username")).isEqualTo("user");
+ }
+
+ @Test
+ public void secretsNullNamespaceTest() {
+ CoreV1Api api = new CoreV1Api();
+ stubFor(get(LIST_API).willReturn(aResponse().withStatus(200).withBody(LIST_BODY)));
+ KubernetesClientSecretsPropertySource propertySource = new KubernetesClientSecretsPropertySource(api,
+ "db-secret", null, new MockEnvironment(), new HashMap<>());
+ assertThat(propertySource.containsProperty("password")).isTrue();
+ assertThat(propertySource.getProperty("password")).isEqualTo("p455w0rd");
+ assertThat(propertySource.containsProperty("username")).isTrue();
+ assertThat(propertySource.getProperty("username")).isEqualTo("user");
+ }
+
+ @Test
+ public void secretLabelsTest() {
+ CoreV1Api api = new CoreV1Api();
+ stubFor(get(LIST_API_WITH_LABEL).willReturn(aResponse().withStatus(200).withBody(LIST_BODY)));
+ Map labels = new HashMap<>();
+ labels.put("spring.cloud.kubernetes.secret", "true");
+ KubernetesClientSecretsPropertySource propertySource = new KubernetesClientSecretsPropertySource(api, null,
+ null, new MockEnvironment(), labels);
+ assertThat(propertySource.containsProperty("spring.rabbitmq.password")).isTrue();
+ assertThat(propertySource.getProperty("spring.rabbitmq.password")).isEqualTo("password");
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientEventBasedConfigMapChangeDetectorTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientEventBasedConfigMapChangeDetectorTests.java
new file mode 100644
index 00000000..b6ce3cb5
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientEventBasedConfigMapChangeDetectorTests.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2013-2020 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.config.reload;
+
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.google.gson.Gson;
+import io.kubernetes.client.informer.EventType;
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.openapi.JSON;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1ConfigMap;
+import io.kubernetes.client.openapi.models.V1ConfigMapList;
+import io.kubernetes.client.openapi.models.V1ListMeta;
+import io.kubernetes.client.openapi.models.V1ObjectMeta;
+import io.kubernetes.client.util.ClientBuilder;
+import io.kubernetes.client.util.Watch;
+import okhttp3.OkHttpClient;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySource;
+import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator;
+import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.mock.env.MockPropertySource;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
+import static com.github.tomakehurst.wiremock.stubbing.Scenario.STARTED;
+import static org.awaitility.Awaitility.await;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author Ryan Baxter
+ */
+class KubernetesClientEventBasedConfigMapChangeDetectorTests {
+
+ private static WireMockServer wireMockServer;
+
+ @BeforeAll
+ public static void setup() {
+ wireMockServer = new WireMockServer(options().dynamicPort());
+ wireMockServer.start();
+ WireMock.configureFor("localhost", wireMockServer.port());
+
+ }
+
+ @AfterAll
+ public static void after() {
+ wireMockServer.stop();
+ }
+
+ @AfterEach
+ public void afterEach() {
+ WireMock.reset();
+ }
+
+ @Test
+ void watch() throws Exception {
+ Map data = new HashMap<>();
+ data.put("application.properties", "spring.cloud.kubernetes.configuration.watcher.refreshDelay=0\n"
+ + "logging.level.org.springframework.cloud.kubernetes=TRACE");
+ Map updateData = new HashMap<>();
+ updateData.put("application.properties", "spring.cloud.kubernetes.configuration.watcher.refreshDelay=1\n"
+ + "logging.level.org.springframework.cloud.kubernetes=TRACE");
+ V1ConfigMap applicationConfig = new V1ConfigMap().kind("ConfigMap")
+ .metadata(new V1ObjectMeta().namespace("default").name("bar1")).data(data);
+ V1ConfigMapList configMapList = new V1ConfigMapList().metadata(new V1ListMeta().resourceVersion("0"))
+ .items(Arrays.asList(applicationConfig));
+ stubFor(get(urlMatching("^/api/v1/namespaces/default/configmaps.*")).inScenario("watch")
+ .whenScenarioStateIs(STARTED).withQueryParam("watch", equalTo("false"))
+ .willReturn(aResponse().withStatus(200).withBody(new Gson().toJson(configMapList)))
+ .willSetStateTo("update"));
+
+ Watch.Response watchResponse = new Watch.Response<>(EventType.MODIFIED.name(), new V1ConfigMap()
+ .kind("ConfigMap").metadata(new V1ObjectMeta().namespace("default").name("bar1")).data(updateData));
+ stubFor(get(urlMatching("^/api/v1/namespaces/default/configmaps.*")).inScenario("watch")
+ .whenScenarioStateIs("update").withQueryParam("watch", equalTo("true"))
+ .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(watchResponse)))
+ .willSetStateTo("add"));
+
+ stubFor(get(urlMatching("^/api/v1/namespaces/default/configmaps.*")).inScenario("watch")
+ .whenScenarioStateIs("add").withQueryParam("watch", equalTo("true"))
+ .willReturn(aResponse().withStatus(200)
+ .withBody(new JSON().serialize(new Watch.Response<>(EventType.ADDED.name(),
+ new V1ConfigMap().kind("ConfigMap")
+ .metadata(new V1ObjectMeta().namespace("default").name("bar3"))
+ .putDataItem("application.properties", "debug=true")))))
+ .willSetStateTo("delete"));
+
+ stubFor(get(urlMatching("^/api/v1/namespaces/default/configmaps.*")).inScenario("watch")
+ .whenScenarioStateIs("delete").withQueryParam("watch", equalTo("true"))
+ .willReturn(aResponse().withStatus(200)
+ .withBody(new JSON().serialize(new Watch.Response<>(EventType.DELETED.name(),
+ new V1ConfigMap().kind("ConfigMap")
+ .metadata(new V1ObjectMeta().namespace("default").name("bar1"))
+ .putDataItem("application.properties", "debug=true")))))
+ .willSetStateTo("done"));
+
+ stubFor(get(urlMatching("^/api/v1/namespaces/default/configmaps.*")).inScenario("watch")
+ .whenScenarioStateIs("done").withQueryParam("watch", equalTo("true"))
+ .willReturn(aResponse().withStatus(200)));
+ ApiClient apiClient = new ClientBuilder().setBasePath("http://localhost:" + wireMockServer.port()).build();
+ OkHttpClient httpClient = apiClient.getHttpClient().newBuilder().readTimeout(0, TimeUnit.SECONDS).build();
+ apiClient.setHttpClient(httpClient);
+ CoreV1Api coreV1Api = new CoreV1Api(apiClient);
+ ConfigurationUpdateStrategy strategy = mock(ConfigurationUpdateStrategy.class);
+ when(strategy.getName()).thenReturn("strategy");
+ KubernetesMockEnvironment environment = new KubernetesMockEnvironment(
+ mock(KubernetesClientConfigMapPropertySource.class)).withProperty("debug", "true");
+ KubernetesClientConfigMapPropertySourceLocator locator = mock(
+ KubernetesClientConfigMapPropertySourceLocator.class);
+ when(locator.locate(environment)).thenReturn(new MockPropertySource().withProperty("debug", "false"));
+ KubernetesClientProperties kubernetesClientProperties = new KubernetesClientProperties();
+ kubernetesClientProperties.setNamespace("default");
+ KubernetesClientEventBasedConfigMapChangeDetector changeDetector = new KubernetesClientEventBasedConfigMapChangeDetector(
+ coreV1Api, environment, new ConfigReloadProperties(), strategy, locator, kubernetesClientProperties);
+
+ Thread controllerThread = new Thread(changeDetector::watch);
+ controllerThread.setDaemon(true);
+ controllerThread.start();
+ await().timeout(Duration.ofSeconds(5))
+ .until(() -> Mockito.mockingDetails(strategy).getInvocations().size() > 4);
+ verify(strategy, atLeast(3)).reload();
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientEventBasedSecretsChangeDetectorTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientEventBasedSecretsChangeDetectorTests.java
new file mode 100644
index 00000000..2ccd60c2
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesClientEventBasedSecretsChangeDetectorTests.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2013-2020 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.config.reload;
+
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.concurrent.TimeUnit;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.google.gson.Gson;
+import io.kubernetes.client.informer.EventType;
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.openapi.JSON;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1ListMeta;
+import io.kubernetes.client.openapi.models.V1ObjectMeta;
+import io.kubernetes.client.openapi.models.V1Secret;
+import io.kubernetes.client.openapi.models.V1SecretList;
+import io.kubernetes.client.util.ClientBuilder;
+import io.kubernetes.client.util.Watch;
+import okhttp3.OkHttpClient;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySource;
+import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator;
+import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.mock.env.MockPropertySource;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
+import static com.github.tomakehurst.wiremock.stubbing.Scenario.STARTED;
+import static org.awaitility.Awaitility.await;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author Ryan Baxter
+ */
+class KubernetesClientEventBasedSecretsChangeDetectorTests {
+
+ private static WireMockServer wireMockServer;
+
+ @BeforeAll
+ public static void setup() {
+ wireMockServer = new WireMockServer(options().dynamicPort());
+ wireMockServer.start();
+ WireMock.configureFor("localhost", wireMockServer.port());
+
+ }
+
+ @AfterAll
+ public static void after() {
+ wireMockServer.stop();
+ }
+
+ @AfterEach
+ public void afterEach() {
+ WireMock.reset();
+ }
+
+ @Test
+ void watch() {
+
+ V1Secret dbPassword = new V1Secret().kind("Secret").metadata(new V1ObjectMeta().name("db-password"))
+ .putStringDataItem("password", Base64.getEncoder().encodeToString("p455w0rd".getBytes()))
+ .putStringDataItem("username", Base64.getEncoder().encodeToString("user".getBytes()));
+ V1Secret dbPasswordUpdated = new V1Secret().kind("Secret").metadata(new V1ObjectMeta().name("db-password"))
+ .putStringDataItem("password", Base64.getEncoder().encodeToString("p455w0rd2".getBytes()))
+ .putStringDataItem("username", Base64.getEncoder().encodeToString("user".getBytes()));
+ V1SecretList secretList = new V1SecretList().kind("SecretList").metadata(new V1ListMeta().resourceVersion("0"))
+ .items(Arrays.asList(dbPassword));
+
+ stubFor(get(urlMatching("^/api/v1/namespaces/default/secrets.*")).inScenario("watch")
+ .whenScenarioStateIs(STARTED).withQueryParam("watch", equalTo("false"))
+ .willReturn(aResponse().withStatus(200).withBody(new Gson().toJson(secretList)))
+ .willSetStateTo("update"));
+
+ Watch.Response watchResponse = new Watch.Response<>(EventType.MODIFIED.name(), dbPasswordUpdated);
+ stubFor(get(urlMatching("/api/v1/namespaces/default/secrets.*")).inScenario("watch")
+ .whenScenarioStateIs("update").withQueryParam("watch", equalTo("true"))
+ .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(watchResponse)))
+ .willSetStateTo("add"));
+
+ stubFor(get(urlMatching("/api/v1/namespaces/default/secrets.*")).inScenario("watch").whenScenarioStateIs("add")
+ .withQueryParam("watch", equalTo("true"))
+ .willReturn(aResponse().withStatus(200)
+ .withBody(new JSON().serialize(new Watch.Response<>(EventType.ADDED.name(),
+ new V1Secret().kind("Secret").metadata(new V1ObjectMeta().name("rabbit-password"))
+ .putDataItem("rabbit-pw", Base64.getEncoder().encode("password".getBytes()))))))
+ .willSetStateTo("delete"));
+
+ stubFor(get(urlMatching("/api/v1/namespaces/default/secrets.*")).inScenario("watch")
+ .whenScenarioStateIs("delete").withQueryParam("watch", equalTo("true"))
+ .willReturn(aResponse().withStatus(200)
+ .withBody(new JSON().serialize(new Watch.Response<>(EventType.DELETED.name(),
+ new V1Secret().kind("Secret").metadata(new V1ObjectMeta().name("rabbit-password"))
+ .putDataItem("rabbit-pw", Base64.getEncoder().encode("password".getBytes()))))))
+ .willSetStateTo("done"));
+
+ stubFor(get(urlMatching("/api/v1/namespaces/default/secrets.*")).inScenario("watch").whenScenarioStateIs("done")
+ .withQueryParam("watch", equalTo("true")).willReturn(aResponse().withStatus(200)));
+
+ ApiClient apiClient = new ClientBuilder().setBasePath("http://localhost:" + wireMockServer.port()).build();
+ OkHttpClient httpClient = apiClient.getHttpClient().newBuilder().readTimeout(0, TimeUnit.SECONDS).build();
+ apiClient.setHttpClient(httpClient);
+ CoreV1Api coreV1Api = new CoreV1Api(apiClient);
+ ConfigurationUpdateStrategy strategy = mock(ConfigurationUpdateStrategy.class);
+ when(strategy.getName()).thenReturn("strategy");
+ KubernetesMockEnvironment environment = new KubernetesMockEnvironment(
+ mock(KubernetesClientSecretsPropertySource.class)).withProperty("db-password", "p455w0rd");
+ KubernetesClientSecretsPropertySourceLocator locator = mock(KubernetesClientSecretsPropertySourceLocator.class);
+ when(locator.locate(environment)).thenReturn(new MockPropertySource().withProperty("db-password", "p455w0rd2"));
+ ConfigReloadProperties properties = new ConfigReloadProperties();
+ properties.setMonitoringSecrets(true);
+ KubernetesClientProperties kubernetesClientProperties = new KubernetesClientProperties();
+ kubernetesClientProperties.setNamespace("default");
+ KubernetesClientEventBasedSecretsChangeDetector changeDetector = new KubernetesClientEventBasedSecretsChangeDetector(
+ coreV1Api, environment, properties, strategy, locator, kubernetesClientProperties);
+
+ Thread controllerThread = new Thread(changeDetector::watch);
+ controllerThread.setDaemon(true);
+ controllerThread.start();
+
+ await().timeout(Duration.ofSeconds(300))
+ .until(() -> Mockito.mockingDetails(strategy).getInvocations().size() > 4);
+ verify(strategy, atLeast(3)).reload();
+ }
+
+}
diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesMockEnvironment.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesMockEnvironment.java
new file mode 100644
index 00000000..f951f627
--- /dev/null
+++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/KubernetesMockEnvironment.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2013-2020 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.config.reload;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySource;
+import org.springframework.core.env.AbstractEnvironment;
+import org.springframework.core.env.PropertySource;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author Ryan Baxter
+ */
+public class KubernetesMockEnvironment extends AbstractEnvironment {
+
+ private PropertySource propertySource = mock(KubernetesClientSecretsPropertySource.class);
+
+ private Map map = new HashMap<>();
+
+ public KubernetesMockEnvironment(PropertySource mockPropertySource) {
+ this.propertySource = mockPropertySource;
+ this.getPropertySources().addLast(this.propertySource);
+ when(propertySource.getSource()).thenReturn(map);
+ }
+
+ public void setProperty(String key, String value) {
+ map.put(key, value);
+ when(propertySource.getProperty(eq(key))).thenReturn(value);
+ }
+
+ public KubernetesMockEnvironment withProperty(String key, String value) {
+ this.setProperty(key, value);
+ return this;
+ }
+
+}
diff --git a/spring-cloud-kubernetes-commons/pom.xml b/spring-cloud-kubernetes-commons/pom.xml
index b67c8c5f..6db6bab1 100644
--- a/spring-cloud-kubernetes-commons/pom.xml
+++ b/spring-cloud-kubernetes-commons/pom.xml
@@ -26,6 +26,14 @@
spring-boot-configuration-processor
true
+
+ org.springframework.cloud
+ spring-cloud-context
+
+
+ javax.annotation
+ javax.annotation-api
+
org.springframework.boot
spring-boot-starter-test
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/AbstractConfigProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/AbstractConfigProperties.java
similarity index 95%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/AbstractConfigProperties.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/AbstractConfigProperties.java
index c1c83ead..a3f9cbbe 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/AbstractConfigProperties.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/AbstractConfigProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.commons.config;
/**
* Abstraction over configuration properties.
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapConfigProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigProperties.java
similarity index 97%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapConfigProperties.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigProperties.java
index cb287f40..443a401a 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapConfigProperties.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.commons.config;
import java.util.Collections;
import java.util.List;
@@ -137,7 +137,7 @@ public class ConfigMapConfigProperties extends AbstractConfigProperties {
}
- static class NormalizedSource {
+ public static class NormalizedSource {
private final String name;
diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapPropertySource.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapPropertySource.java
new file mode 100644
index 00000000..591c8b7c
--- /dev/null
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapPropertySource.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2013-2019 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.commons.config;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.core.env.Environment;
+import org.springframework.core.env.MapPropertySource;
+import org.springframework.core.env.StandardEnvironment;
+
+import static org.springframework.cloud.kubernetes.commons.config.PropertySourceUtils.KEY_VALUE_TO_PROPERTIES;
+import static org.springframework.cloud.kubernetes.commons.config.PropertySourceUtils.PROPERTIES_TO_MAP;
+import static org.springframework.cloud.kubernetes.commons.config.PropertySourceUtils.throwingMerger;
+import static org.springframework.cloud.kubernetes.commons.config.PropertySourceUtils.yamlParserGenerator;
+
+/**
+ * A {@link MapPropertySource} that uses Kubernetes config maps.
+ *
+ * @author Ioannis Canellos
+ * @author Ali Shahbour
+ * @author Michael Moudatsos
+ */
+public abstract class ConfigMapPropertySource extends MapPropertySource {
+
+ private static final Log LOG = LogFactory.getLog(ConfigMapPropertySource.class);
+
+ protected static final String APPLICATION_YML = "application.yml";
+
+ protected static final String APPLICATION_YAML = "application.yaml";
+
+ protected static final String APPLICATION_PROPERTIES = "application.properties";
+
+ protected static final String PREFIX = "configmap";
+
+ public ConfigMapPropertySource(String name, Map source) {
+ super(name, source);
+ }
+
+ protected static Environment createEnvironmentWithActiveProfiles(String[] activeProfiles) {
+ StandardEnvironment environment = new StandardEnvironment();
+ environment.setActiveProfiles(activeProfiles);
+ return environment;
+ }
+
+ protected static String getName(String name, String namespace) {
+ return new StringBuilder().append(PREFIX).append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(name)
+ .append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(namespace).toString();
+ }
+
+ protected static Map processAllEntries(Map input, Environment environment) {
+
+ Set> entrySet = input.entrySet();
+ if (entrySet.size() == 1) {
+ // we handle the case where the configmap contains a single "file"
+ // in this case we don't care what the name of t he file is
+ Entry singleEntry = entrySet.iterator().next();
+ String propertyName = singleEntry.getKey();
+ String propertyValue = singleEntry.getValue();
+ if (propertyName.endsWith(".yml") || propertyName.endsWith(".yaml")) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("The single property with name: [" + propertyName + "] will be treated as a yaml file");
+ }
+
+ return yamlParserGenerator(environment).andThen(PROPERTIES_TO_MAP).apply(propertyValue);
+ }
+ else if (propertyName.endsWith(".properties")) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("The single property with name: [" + propertyName
+ + "] will be treated as a properties file");
+ }
+
+ return KEY_VALUE_TO_PROPERTIES.andThen(PROPERTIES_TO_MAP).apply(propertyValue);
+ }
+ else {
+ return defaultProcessAllEntries(input, environment);
+ }
+ }
+
+ return defaultProcessAllEntries(input, environment);
+ }
+
+ protected static Map defaultProcessAllEntries(Map input, Environment environment) {
+
+ return input.entrySet().stream().map(e -> extractProperties(e.getKey(), e.getValue(), environment))
+ .filter(m -> !m.isEmpty()).flatMap(m -> m.entrySet().stream())
+ .collect(Collectors.toMap(Entry::getKey, Entry::getValue, throwingMerger(), LinkedHashMap::new));
+ }
+
+ protected static Map extractProperties(String resourceName, String content,
+ Environment environment) {
+
+ if (resourceName.equals(APPLICATION_YAML) || resourceName.equals(APPLICATION_YML)) {
+ return yamlParserGenerator(environment).andThen(PROPERTIES_TO_MAP).apply(content);
+ }
+ else if (resourceName.equals(APPLICATION_PROPERTIES)) {
+ return KEY_VALUE_TO_PROPERTIES.andThen(PROPERTIES_TO_MAP).apply(content);
+ }
+
+ return new LinkedHashMap() {
+ {
+ put(resourceName, content);
+ }
+ };
+ }
+
+ protected static Map asObjectMap(Map source) {
+ return source.entrySet().stream()
+ .collect(Collectors.toMap(Entry::getKey, Entry::getValue, throwingMerger(), LinkedHashMap::new));
+ }
+
+}
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySourceLocator.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapPropertySourceLocator.java
similarity index 72%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySourceLocator.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapPropertySourceLocator.java
index a1212ad2..a450f63a 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySourceLocator.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapPropertySourceLocator.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.commons.config;
import java.io.IOException;
import java.nio.file.Files;
@@ -22,26 +22,23 @@ import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
-import io.fabric8.kubernetes.api.builder.Function;
-import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.ConfigMapConfigProperties.NormalizedSource;
-import org.springframework.core.annotation.Order;
+import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties.NormalizedSource;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
-import static org.springframework.cloud.kubernetes.config.ConfigUtils.getApplicationName;
-import static org.springframework.cloud.kubernetes.config.ConfigUtils.getApplicationNamespace;
-import static org.springframework.cloud.kubernetes.config.PropertySourceUtils.KEY_VALUE_TO_PROPERTIES;
-import static org.springframework.cloud.kubernetes.config.PropertySourceUtils.PROPERTIES_TO_MAP;
-import static org.springframework.cloud.kubernetes.config.PropertySourceUtils.yamlParserGenerator;
+import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.getApplicationName;
+import static org.springframework.cloud.kubernetes.commons.config.PropertySourceUtils.KEY_VALUE_TO_PROPERTIES;
+import static org.springframework.cloud.kubernetes.commons.config.PropertySourceUtils.PROPERTIES_TO_MAP;
+import static org.springframework.cloud.kubernetes.commons.config.PropertySourceUtils.yamlParserGenerator;
/**
* A {@link PropertySourceLocator} that uses config maps.
@@ -49,17 +46,13 @@ import static org.springframework.cloud.kubernetes.config.PropertySourceUtils.ya
* @author Ioannis Canellos
* @author Michael Moudatsos
*/
-@Order(0)
-public class ConfigMapPropertySourceLocator implements PropertySourceLocator {
+public abstract class ConfigMapPropertySourceLocator implements PropertySourceLocator {
private static final Log LOG = LogFactory.getLog(ConfigMapPropertySourceLocator.class);
- private final KubernetesClient client;
+ protected final ConfigMapConfigProperties properties;
- private final ConfigMapConfigProperties properties;
-
- public ConfigMapPropertySourceLocator(KubernetesClient client, ConfigMapConfigProperties properties) {
- this.client = client;
+ public ConfigMapPropertySourceLocator(ConfigMapConfigProperties properties) {
this.properties = properties;
}
@@ -68,7 +61,7 @@ public class ConfigMapPropertySourceLocator implements PropertySourceLocator {
if (environment instanceof ConfigurableEnvironment) {
ConfigurableEnvironment env = (ConfigurableEnvironment) environment;
- List sources = this.properties.determineSources();
+ List sources = this.properties.determineSources();
CompositePropertySource composite = new CompositePropertySource("composite-configmap");
if (this.properties.isEnableApi()) {
sources.forEach(s -> composite.addFirstPropertySource(getMapPropertySourceForSingleConfigMap(env, s)));
@@ -85,12 +78,13 @@ public class ConfigMapPropertySourceLocator implements PropertySourceLocator {
NormalizedSource normalizedSource) {
String configurationTarget = this.properties.getConfigurationTarget();
- return new ConfigMapPropertySource(this.client,
- getApplicationName(environment, normalizedSource.getName(), configurationTarget),
- getApplicationNamespace(this.client, normalizedSource.getNamespace(), configurationTarget),
- environment);
+ return getMapPropertySource(getApplicationName(environment, normalizedSource.getName(), configurationTarget),
+ normalizedSource, configurationTarget, environment);
}
+ protected abstract MapPropertySource getMapPropertySource(String name, NormalizedSource normalizedSource,
+ String configurationTarget, ConfigurableEnvironment environment);
+
private void addPropertySourcesFromPaths(Environment environment, CompositePropertySource composite) {
this.properties.getPaths().stream().map(Paths::get).peek(p -> {
if (!Files.exists(p)) {
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigUtils.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java
similarity index 66%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigUtils.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java
index d06e33ab..6ebf5c61 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigUtils.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java
@@ -14,17 +14,16 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.commons.config;
-import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
-import static org.springframework.cloud.kubernetes.config.Constants.FALLBACK_APPLICATION_NAME;
-import static org.springframework.cloud.kubernetes.config.Constants.SPRING_APPLICATION_NAME;
+import static org.springframework.cloud.kubernetes.commons.config.Constants.FALLBACK_APPLICATION_NAME;
+import static org.springframework.cloud.kubernetes.commons.config.Constants.SPRING_APPLICATION_NAME;
/**
* Utility class that works with configuration properties.
@@ -36,7 +35,6 @@ public final class ConfigUtils {
private static final Log LOG = LogFactory.getLog(ConfigUtils.class);
private ConfigUtils() {
- throw new IllegalStateException("Can't instantiate a utility class");
}
public static String getApplicationName(Environment env, String configName, String configurationTarget) {
@@ -50,15 +48,4 @@ public final class ConfigUtils {
return configName;
}
- public static String getApplicationNamespace(KubernetesClient client, String configNamespace,
- String configurationTarget) {
- if (StringUtils.isEmpty(configNamespace)) {
- LOG.debug(configurationTarget + " namespace has not been set, taking it from client (ns="
- + client.getNamespace() + ")");
- configNamespace = client.getNamespace();
- }
-
- return configNamespace;
- }
-
}
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/Constants.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/Constants.java
similarity index 60%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/Constants.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/Constants.java
index 8fdd8a3f..bd98ab3e 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/Constants.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/Constants.java
@@ -14,13 +14,24 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.commons.config;
-final class Constants {
+public final class Constants {
- static final String SPRING_APPLICATION_NAME = "spring.application.name";
- static final String FALLBACK_APPLICATION_NAME = "application";
- static final String PROPERTY_SOURCE_NAME_SEPARATOR = ".";
+ /**
+ * Spring application name property.
+ */
+ public static final String SPRING_APPLICATION_NAME = "spring.application.name";
+
+ /**
+ * Default application name.
+ */
+ public static final String FALLBACK_APPLICATION_NAME = "application";
+
+ /**
+ * Property separator.
+ */
+ public static final String PROPERTY_SOURCE_NAME_SEPARATOR = ".";
private Constants() {
}
diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesBootstrapConfiguration.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesBootstrapConfiguration.java
new file mode 100644
index 00000000..71bb65c0
--- /dev/null
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesBootstrapConfiguration.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013-2020 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.commons.config;
+
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.kubernetes.commons.ConditionalOnKubernetesEnabled;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Ryan Baxter
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnKubernetesEnabled
+@EnableConfigurationProperties({ ConfigMapConfigProperties.class, SecretsConfigProperties.class })
+public class KubernetesBootstrapConfiguration {
+
+}
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/PropertySourceUtils.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/PropertySourceUtils.java
similarity index 77%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/PropertySourceUtils.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/PropertySourceUtils.java
index ad9641fd..5c757813 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/PropertySourceUtils.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/PropertySourceUtils.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.commons.config;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -42,7 +42,10 @@ import static org.springframework.beans.factory.config.YamlProcessor.MatchStatus
*/
public final class PropertySourceUtils {
- static final Function KEY_VALUE_TO_PROPERTIES = s -> {
+ /**
+ * Function to convert a String to Properties.
+ */
+ public static final Function KEY_VALUE_TO_PROPERTIES = s -> {
Properties properties = new Properties();
try {
properties.load(new ByteArrayInputStream(s.getBytes()));
@@ -52,7 +55,11 @@ public final class PropertySourceUtils {
throw new IllegalArgumentException();
}
};
- static final Function> PROPERTIES_TO_MAP = p -> p.entrySet().stream()
+
+ /**
+ * Function to convert Properties to a Map.
+ */
+ public static final Function> PROPERTIES_TO_MAP = p -> p.entrySet().stream()
.collect(Collectors.toMap(e -> String.valueOf(e.getKey()), Map.Entry::getValue, throwingMerger(),
java.util.LinkedHashMap::new));
@@ -60,7 +67,12 @@ public final class PropertySourceUtils {
throw new IllegalStateException("Can't instantiate a utility class");
}
- static Function yamlParserGenerator(Environment environment) {
+ /**
+ * Function to convert String into Properties with an environment.
+ * @param environment Environment.
+ * @return properties.
+ */
+ public static Function yamlParserGenerator(Environment environment) {
return s -> {
YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
yamlFactory.setDocumentMatchers(properties -> {
@@ -77,7 +89,12 @@ public final class PropertySourceUtils {
};
}
- static BinaryOperator throwingMerger() {
+ /**
+ * Throws IllegalStateException.
+ * @param Throwable.
+ * @return IllegalStateException.
+ */
+ public static BinaryOperator throwingMerger() {
return (u, v) -> {
throw new IllegalStateException(String.format("Duplicate key %s", u));
};
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsConfigProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigProperties.java
similarity index 97%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsConfigProperties.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigProperties.java
index 2a1c23c3..79cad9dd 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsConfigProperties.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.commons.config;
import java.util.ArrayList;
import java.util.HashMap;
@@ -169,7 +169,7 @@ public class SecretsConfigProperties extends AbstractConfigProperties {
}
- static class NormalizedSource {
+ public static class NormalizedSource {
private final String name;
diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsPropertySource.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsPropertySource.java
new file mode 100644
index 00000000..88cfe3e6
--- /dev/null
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsPropertySource.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2013-2019 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.commons.config;
+
+import java.util.Base64;
+import java.util.Map;
+
+import org.springframework.core.env.MapPropertySource;
+
+/**
+ * Kubernetes property source for secrets.
+ *
+ * @author l burgazzoli
+ * @author Haytham Mohamed
+ */
+public class SecretsPropertySource extends MapPropertySource {
+
+ private static final String PREFIX = "secrets";
+
+ public SecretsPropertySource(String name, Map source) {
+ super(name, source);
+ }
+
+ protected static String getSourceName(String name, String namespace) {
+ return new StringBuilder().append(PREFIX).append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(name)
+ .append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(namespace).toString();
+ }
+
+ protected static void putAll(Map data, Map result) {
+ if (data != null) {
+ data.forEach((k, v) -> result.put(k, new String(Base64.getDecoder().decode(v)).trim()));
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + " {name='" + this.name + "'}";
+ }
+
+}
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsPropertySourceLocator.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsPropertySourceLocator.java
similarity index 73%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsPropertySourceLocator.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsPropertySourceLocator.java
index 862712f4..4b09389e 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsPropertySourceLocator.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsPropertySourceLocator.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.commons.config;
import java.io.IOException;
import java.nio.file.Files;
@@ -24,38 +24,29 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
-import org.springframework.core.annotation.Order;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
-import static org.springframework.cloud.kubernetes.config.ConfigUtils.getApplicationName;
-import static org.springframework.cloud.kubernetes.config.ConfigUtils.getApplicationNamespace;
-
/**
* Kubernetes {@link PropertySourceLocator} for secrets.
*
* @author l burgazzoli
* @author Haytham Mohamed
*/
-@Order(1)
-public class SecretsPropertySourceLocator implements PropertySourceLocator {
+public abstract class SecretsPropertySourceLocator implements PropertySourceLocator {
private static final Log LOG = LogFactory.getLog(SecretsPropertySourceLocator.class);
- private final KubernetesClient client;
+ protected final SecretsConfigProperties properties;
- private final SecretsConfigProperties properties;
-
- public SecretsPropertySourceLocator(KubernetesClient client, SecretsConfigProperties properties) {
- this.client = client;
+ public SecretsPropertySourceLocator(SecretsConfigProperties properties) {
this.properties = properties;
}
@@ -83,17 +74,17 @@ public class SecretsPropertySourceLocator implements PropertySourceLocator {
SecretsConfigProperties.NormalizedSource normalizedSource) {
String configurationTarget = this.properties.getConfigurationTarget();
- return new SecretsPropertySource(this.client, environment,
- getApplicationName(environment, normalizedSource.getName(), configurationTarget),
- getApplicationNamespace(this.client, normalizedSource.getNamespace(), configurationTarget),
- normalizedSource.getLabels());
+ return getPropertySource(environment, normalizedSource, configurationTarget);
}
- private void putPathConfig(CompositePropertySource composite) {
+ protected abstract MapPropertySource getPropertySource(ConfigurableEnvironment environment,
+ SecretsConfigProperties.NormalizedSource normalizedSource, String configurationTarget);
+
+ protected void putPathConfig(CompositePropertySource composite) {
this.properties.getPaths().stream().map(Paths::get).filter(Files::exists).forEach(p -> putAll(p, composite));
}
- private void putAll(Path path, CompositePropertySource composite) {
+ protected void putAll(Path path, CompositePropertySource composite) {
try {
Files.walk(path).filter(Files::isRegularFile).forEach(p -> readFile(p, composite));
@@ -103,7 +94,7 @@ public class SecretsPropertySourceLocator implements PropertySourceLocator {
}
}
- private void readFile(Path path, CompositePropertySource composite) {
+ protected void readFile(Path path, CompositePropertySource composite) {
try {
Map result = new HashMap<>();
result.put(path.getFileName().toString(), new String(Files.readAllBytes(path)).trim());
diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadAutoConfiguration.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadAutoConfiguration.java
new file mode 100644
index 00000000..b508bde7
--- /dev/null
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadAutoConfiguration.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2013-2019 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.commons.config.reload;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
+import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
+import org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration;
+import org.springframework.cloud.context.refresh.ContextRefresher;
+import org.springframework.cloud.context.restart.RestartEndpoint;
+import org.springframework.cloud.kubernetes.commons.ConditionalOnKubernetesEnabled;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.Assert;
+
+/**
+ * @author Ryan Baxter
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnKubernetesEnabled
+@ConditionalOnClass(EndpointAutoConfiguration.class)
+@AutoConfigureAfter({ InfoEndpointAutoConfiguration.class, RefreshEndpointAutoConfiguration.class,
+ RefreshAutoConfiguration.class })
+public class ConfigReloadAutoConfiguration {
+
+ /**
+ * Configuration reload must be enabled explicitly.
+ */
+ @ConditionalOnProperty("spring.cloud.kubernetes.reload.enabled")
+ @ConditionalOnClass({ RestartEndpoint.class, ContextRefresher.class })
+ protected static class ConfigReloadAutoConfigurationBeans {
+
+ /**
+ * @param properties config reload properties
+ * @param ctx application context
+ * @param restarter restart endpoint
+ * @param refresher context refresher
+ * @return provides the action to execute when the configuration changes.
+ */
+ @Bean
+ @ConditionalOnMissingBean
+ public ConfigurationUpdateStrategy configurationUpdateStrategy(ConfigReloadProperties properties,
+ ConfigurableApplicationContext ctx, @Autowired(required = false) RestartEndpoint restarter,
+ ContextRefresher refresher) {
+ switch (properties.getStrategy()) {
+ case RESTART_CONTEXT:
+ Assert.notNull(restarter, "Restart endpoint is not enabled");
+ return new ConfigurationUpdateStrategy(properties.getStrategy().name(), () -> {
+ wait(properties);
+ restarter.restart();
+ });
+ case REFRESH:
+ return new ConfigurationUpdateStrategy(properties.getStrategy().name(), refresher::refresh);
+ case SHUTDOWN:
+ return new ConfigurationUpdateStrategy(properties.getStrategy().name(), () -> {
+ wait(properties);
+ ctx.close();
+ });
+ }
+ throw new IllegalStateException("Unsupported configuration update strategy: " + properties.getStrategy());
+ }
+
+ private static void wait(ConfigReloadProperties properties) {
+ final long waitMillis = ThreadLocalRandom.current().nextLong(properties.getMaxWaitForRestart().toMillis());
+ try {
+ Thread.sleep(waitMillis);
+ }
+ catch (InterruptedException ignored) {
+ }
+ }
+
+ }
+
+}
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java
similarity index 98%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadProperties.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java
index b89c4ad5..1d5c8076 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadProperties.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.reload;
+package org.springframework.cloud.kubernetes.commons.config.reload;
import java.time.Duration;
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationChangeDetector.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigurationChangeDetector.java
similarity index 88%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationChangeDetector.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigurationChangeDetector.java
index 4df0a4ea..182e86d1 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationChangeDetector.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigurationChangeDetector.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.reload;
+package org.springframework.cloud.kubernetes.commons.config.reload;
import java.util.ArrayList;
import java.util.LinkedList;
@@ -23,9 +23,6 @@ import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
-import javax.annotation.PreDestroy;
-
-import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -51,25 +48,15 @@ public abstract class ConfigurationChangeDetector {
protected ConfigReloadProperties properties;
- protected KubernetesClient kubernetesClient;
-
protected ConfigurationUpdateStrategy strategy;
public ConfigurationChangeDetector(ConfigurableEnvironment environment, ConfigReloadProperties properties,
- KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy) {
+ ConfigurationUpdateStrategy strategy) {
this.environment = environment;
this.properties = properties;
- this.kubernetesClient = kubernetesClient;
this.strategy = strategy;
}
- @PreDestroy
- public void shutdown() {
- // Ensure the kubernetes client is cleaned up from spare threads when shutting
- // down
- this.kubernetesClient.close();
- }
-
public void reloadProperties() {
this.log.info("Reloading using strategy: " + this.strategy.getName());
this.strategy.reload();
@@ -81,7 +68,7 @@ public abstract class ConfigurationChangeDetector {
* @param right right map property sources
* @return {@code true} if source has changed
*/
- protected boolean changed(MapPropertySource left, MapPropertySource right) {
+ public boolean changed(MapPropertySource left, MapPropertySource right) {
if (left == right) {
return false;
}
@@ -93,7 +80,7 @@ public abstract class ConfigurationChangeDetector {
return !Objects.equals(leftMap, rightMap);
}
- protected boolean changed(List extends MapPropertySource> left, List extends MapPropertySource> right) {
+ public boolean changed(List extends MapPropertySource> left, List extends MapPropertySource> right) {
if (left.size() != right.size()) {
this.log.warn("The current number of ConfigMap PropertySources does not match "
@@ -132,7 +119,7 @@ public abstract class ConfigurationChangeDetector {
* @param sourceClass class for which property sources will be found
* @return finds all registered property sources of the given type
*/
- protected > List findPropertySources(Class sourceClass) {
+ public > List findPropertySources(Class sourceClass) {
List managedSources = new LinkedList<>();
LinkedList> sources = toLinkedList(this.environment.getPropertySources());
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationUpdateStrategy.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigurationUpdateStrategy.java
similarity index 95%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationUpdateStrategy.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigurationUpdateStrategy.java
index 1b6b7506..3a5df326 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationUpdateStrategy.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigurationUpdateStrategy.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.reload;
+package org.springframework.cloud.kubernetes.commons.config.reload;
import java.util.Objects;
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/PollingConfigMapChangeDetector.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/PollingConfigMapChangeDetector.java
similarity index 72%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/PollingConfigMapChangeDetector.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/PollingConfigMapChangeDetector.java
index 28b859aa..e8b9701d 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/PollingConfigMapChangeDetector.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/PollingConfigMapChangeDetector.java
@@ -14,18 +14,16 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.reload;
+package org.springframework.cloud.kubernetes.commons.config.reload;
import java.util.List;
import javax.annotation.PostConstruct;
-import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.springframework.cloud.kubernetes.config.ConfigMapPropertySource;
-import org.springframework.cloud.kubernetes.config.ConfigMapPropertySourceLocator;
+import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.scheduling.annotation.Scheduled;
@@ -42,14 +40,16 @@ public class PollingConfigMapChangeDetector extends ConfigurationChangeDetector
protected Log log = LogFactory.getLog(getClass());
- private ConfigMapPropertySourceLocator configMapPropertySourceLocator;
+ private PropertySourceLocator propertySourceLocator;
+
+ private Class propertySourceClass;
public PollingConfigMapChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
- KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
- ConfigMapPropertySourceLocator configMapPropertySourceLocator) {
- super(environment, properties, kubernetesClient, strategy);
-
- this.configMapPropertySourceLocator = configMapPropertySourceLocator;
+ ConfigurationUpdateStrategy strategy, Class propertySourceClass,
+ PropertySourceLocator propertySourceLocator) {
+ super(environment, properties, strategy);
+ this.propertySourceLocator = propertySourceLocator;
+ this.propertySourceClass = propertySourceClass;
}
@PostConstruct
@@ -66,12 +66,10 @@ public class PollingConfigMapChangeDetector extends ConfigurationChangeDetector
if (log.isDebugEnabled()) {
log.debug("Polling for changes in config maps");
}
- List extends MapPropertySource> currentConfigMapSources = findPropertySources(
- ConfigMapPropertySource.class);
+ List extends MapPropertySource> currentConfigMapSources = findPropertySources(propertySourceClass);
if (!currentConfigMapSources.isEmpty()) {
- changedConfigMap = changed(
- locateMapPropertySources(this.configMapPropertySourceLocator, this.environment),
+ changedConfigMap = changed(locateMapPropertySources(this.propertySourceLocator, this.environment),
currentConfigMapSources);
}
}
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/PollingSecretsChangeDetector.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/PollingSecretsChangeDetector.java
similarity index 74%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/PollingSecretsChangeDetector.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/PollingSecretsChangeDetector.java
index d1e1ee97..4d99c082 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/PollingSecretsChangeDetector.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/PollingSecretsChangeDetector.java
@@ -14,18 +14,16 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.reload;
+package org.springframework.cloud.kubernetes.commons.config.reload;
import java.util.List;
import javax.annotation.PostConstruct;
-import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.springframework.cloud.kubernetes.config.SecretsPropertySource;
-import org.springframework.cloud.kubernetes.config.SecretsPropertySourceLocator;
+import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.scheduling.annotation.Scheduled;
@@ -42,14 +40,16 @@ public class PollingSecretsChangeDetector extends ConfigurationChangeDetector {
protected Log log = LogFactory.getLog(getClass());
- private final SecretsPropertySourceLocator secretsPropertySourceLocator;
+ private final PropertySourceLocator propertySourceLocator;
+
+ private Class propertySourceClass;
public PollingSecretsChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
- KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
- SecretsPropertySourceLocator secretsPropertySourceLocator) {
- super(environment, properties, kubernetesClient, strategy);
-
- this.secretsPropertySourceLocator = secretsPropertySourceLocator;
+ ConfigurationUpdateStrategy strategy, Class propertySourceClass,
+ PropertySourceLocator propertySourceLocator) {
+ super(environment, properties, strategy);
+ this.propertySourceClass = propertySourceClass;
+ this.propertySourceLocator = propertySourceLocator;
}
@PostConstruct
@@ -66,10 +66,10 @@ public class PollingSecretsChangeDetector extends ConfigurationChangeDetector {
if (log.isDebugEnabled()) {
log.debug("Polling for changes in secrets");
}
- List currentSecretSources = locateMapPropertySources(this.secretsPropertySourceLocator,
+ List currentSecretSources = locateMapPropertySources(this.propertySourceLocator,
this.environment);
if (currentSecretSources != null && !currentSecretSources.isEmpty()) {
- List propertySources = findPropertySources(SecretsPropertySource.class);
+ List propertySources = findPropertySources(this.propertySourceClass);
changedSecrets = changed(currentSecretSources, propertySources);
}
}
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/condition/EventReloadDetectionMode.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/condition/EventReloadDetectionMode.java
similarity index 84%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/condition/EventReloadDetectionMode.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/condition/EventReloadDetectionMode.java
index 04702a87..972c4e9e 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/condition/EventReloadDetectionMode.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/condition/EventReloadDetectionMode.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.reload.condition;
+package org.springframework.cloud.kubernetes.commons.config.reload.condition;
-import org.springframework.cloud.kubernetes.config.reload.ConfigReloadProperties.ReloadDetectionMode;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
@@ -38,7 +38,7 @@ public class EventReloadDetectionMode implements Condition {
}
else {
if (environment.getProperty("spring.cloud.kubernetes.reload.mode")
- .equalsIgnoreCase(ReloadDetectionMode.EVENT.name())) {
+ .equalsIgnoreCase(ConfigReloadProperties.ReloadDetectionMode.EVENT.name())) {
return true;
}
}
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/condition/PollingReloadDetectionMode.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/condition/PollingReloadDetectionMode.java
similarity index 84%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/condition/PollingReloadDetectionMode.java
rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/condition/PollingReloadDetectionMode.java
index 39e20910..f7696d2f 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/condition/PollingReloadDetectionMode.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/condition/PollingReloadDetectionMode.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.reload.condition;
+package org.springframework.cloud.kubernetes.commons.config.reload.condition;
-import org.springframework.cloud.kubernetes.config.reload.ConfigReloadProperties.ReloadDetectionMode;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
@@ -38,7 +38,7 @@ public class PollingReloadDetectionMode implements Condition {
}
else {
if (environment.getProperty("spring.cloud.kubernetes.reload.mode")
- .equalsIgnoreCase(ReloadDetectionMode.POLLING.name())) {
+ .equalsIgnoreCase(ConfigReloadProperties.ReloadDetectionMode.POLLING.name())) {
return true;
}
}
diff --git a/spring-cloud-kubernetes-commons/src/main/resources/META-INF/spring.factories b/spring-cloud-kubernetes-commons/src/main/resources/META-INF/spring.factories
index 85a298fb..ddd9639e 100644
--- a/spring-cloud-kubernetes-commons/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-kubernetes-commons/src/main/resources/META-INF/spring.factories
@@ -1,2 +1,5 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-org.springframework.cloud.kubernetes.commons.KubernetesCommonsAutoConfiguration
+org.springframework.cloud.kubernetes.commons.KubernetesCommonsAutoConfiguration,\
+org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadAutoConfiguration
+org.springframework.cloud.bootstrap.BootstrapConfiguration=\
+org.springframework.cloud.kubernetes.commons.config.KubernetesBootstrapConfiguration
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySource.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySource.java
deleted file mode 100644
index 41cac15f..00000000
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySource.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright 2013-2019 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.config;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import io.fabric8.kubernetes.api.model.ConfigMap;
-import io.fabric8.kubernetes.client.KubernetesClient;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.springframework.core.env.Environment;
-import org.springframework.core.env.MapPropertySource;
-import org.springframework.core.env.StandardEnvironment;
-import org.springframework.util.StringUtils;
-
-import static org.springframework.cloud.kubernetes.config.PropertySourceUtils.KEY_VALUE_TO_PROPERTIES;
-import static org.springframework.cloud.kubernetes.config.PropertySourceUtils.PROPERTIES_TO_MAP;
-import static org.springframework.cloud.kubernetes.config.PropertySourceUtils.throwingMerger;
-import static org.springframework.cloud.kubernetes.config.PropertySourceUtils.yamlParserGenerator;
-
-/**
- * A {@link MapPropertySource} that uses Kubernetes config maps.
- *
- * @author Ioannis Canellos
- * @author Ali Shahbour
- * @author Michael Moudatsos
- */
-public class ConfigMapPropertySource extends MapPropertySource {
-
- private static final Log LOG = LogFactory.getLog(ConfigMapPropertySource.class);
-
- private static final String APPLICATION_YML = "application.yml";
-
- private static final String APPLICATION_YAML = "application.yaml";
-
- private static final String APPLICATION_PROPERTIES = "application.properties";
-
- private static final String PREFIX = "configmap";
-
- public ConfigMapPropertySource(KubernetesClient client, String name) {
- this(client, name, null, (Environment) null);
- }
-
- public ConfigMapPropertySource(KubernetesClient client, String name, String namespace, String[] profiles) {
- this(client, name, namespace, createEnvironmentWithActiveProfiles(profiles));
- }
-
- private static Environment createEnvironmentWithActiveProfiles(String[] activeProfiles) {
- StandardEnvironment environment = new StandardEnvironment();
- environment.setActiveProfiles(activeProfiles);
- return environment;
- }
-
- public ConfigMapPropertySource(KubernetesClient client, String name, String namespace, Environment environment) {
- super(getName(client, name, namespace), asObjectMap(getData(client, name, namespace, environment)));
- }
-
- private static String getName(KubernetesClient client, String name, String namespace) {
- return new StringBuilder().append(PREFIX).append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(name)
- .append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR)
- .append(namespace == null || namespace.isEmpty() ? client.getNamespace() : namespace).toString();
- }
-
- private static Map getData(KubernetesClient client, String name, String namespace,
- Environment environment) {
- try {
- Map result = new LinkedHashMap<>();
- ConfigMap map = StringUtils.isEmpty(namespace) ? client.configMaps().withName(name).get()
- : client.configMaps().inNamespace(namespace).withName(name).get();
-
- if (map != null) {
- result.putAll(processAllEntries(map.getData(), environment));
- }
-
- if (environment != null) {
- for (String activeProfile : environment.getActiveProfiles()) {
-
- String mapNameWithProfile = name + "-" + activeProfile;
-
- ConfigMap mapWithProfile = StringUtils.isEmpty(namespace)
- ? client.configMaps().withName(mapNameWithProfile).get()
- : client.configMaps().inNamespace(namespace).withName(mapNameWithProfile).get();
-
- if (mapWithProfile != null) {
- result.putAll(processAllEntries(mapWithProfile.getData(), environment));
- }
-
- }
- }
-
- return result;
-
- }
- catch (Exception e) {
- LOG.warn("Can't read configMap with name: [" + name + "] in namespace:[" + namespace + "]. Ignoring.", e);
- }
-
- return new LinkedHashMap<>();
- }
-
- private static Map processAllEntries(Map input, Environment environment) {
-
- Set> entrySet = input.entrySet();
- if (entrySet.size() == 1) {
- // we handle the case where the configmap contains a single "file"
- // in this case we don't care what the name of t he file is
- Entry singleEntry = entrySet.iterator().next();
- String propertyName = singleEntry.getKey();
- String propertyValue = singleEntry.getValue();
- if (propertyName.endsWith(".yml") || propertyName.endsWith(".yaml")) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("The single property with name: [" + propertyName + "] will be treated as a yaml file");
- }
-
- return yamlParserGenerator(environment).andThen(PROPERTIES_TO_MAP).apply(propertyValue);
- }
- else if (propertyName.endsWith(".properties")) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("The single property with name: [" + propertyName
- + "] will be treated as a properties file");
- }
-
- return KEY_VALUE_TO_PROPERTIES.andThen(PROPERTIES_TO_MAP).apply(propertyValue);
- }
- else {
- return defaultProcessAllEntries(input, environment);
- }
- }
-
- return defaultProcessAllEntries(input, environment);
- }
-
- private static Map defaultProcessAllEntries(Map input, Environment environment) {
-
- return input.entrySet().stream().map(e -> extractProperties(e.getKey(), e.getValue(), environment))
- .filter(m -> !m.isEmpty()).flatMap(m -> m.entrySet().stream())
- .collect(Collectors.toMap(Entry::getKey, Entry::getValue, throwingMerger(), LinkedHashMap::new));
- }
-
- private static Map extractProperties(String resourceName, String content, Environment environment) {
-
- if (resourceName.equals(APPLICATION_YAML) || resourceName.equals(APPLICATION_YML)) {
- return yamlParserGenerator(environment).andThen(PROPERTIES_TO_MAP).apply(content);
- }
- else if (resourceName.equals(APPLICATION_PROPERTIES)) {
- return KEY_VALUE_TO_PROPERTIES.andThen(PROPERTIES_TO_MAP).apply(content);
- }
-
- return new LinkedHashMap() {
- {
- put(resourceName, content);
- }
- };
- }
-
- private static Map asObjectMap(Map source) {
- return source.entrySet().stream().collect(
- Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, throwingMerger(), LinkedHashMap::new));
- }
-
-}
diff --git a/spring-cloud-kubernetes-config/src/main/resources/META-INF/spring.factories b/spring-cloud-kubernetes-config/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index 90e6af77..00000000
--- a/spring-cloud-kubernetes-config/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,4 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-org.springframework.cloud.kubernetes.config.reload.ConfigReloadAutoConfiguration
-org.springframework.cloud.bootstrap.BootstrapConfiguration=\
-org.springframework.cloud.kubernetes.config.BootstrapConfiguration
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigMapWatcherChangeDetector.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigMapWatcherChangeDetector.java
index 956a7d9a..4bc967ef 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigMapWatcherChangeDetector.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigMapWatcherChangeDetector.java
@@ -22,9 +22,9 @@ import reactor.core.publisher.Mono;
import org.springframework.cloud.bus.BusProperties;
import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
-import org.springframework.cloud.kubernetes.config.ConfigMapPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.reload.ConfigReloadProperties;
-import org.springframework.cloud.kubernetes.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.core.env.AbstractEnvironment;
@@ -43,10 +43,10 @@ public class BusEventBasedConfigMapWatcherChangeDetector extends ConfigMapWatche
public BusEventBasedConfigMapWatcherChangeDetector(AbstractEnvironment environment,
ConfigReloadProperties properties, KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
- ConfigMapPropertySourceLocator configMapPropertySourceLocator, BusProperties busProperties,
+ Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator, BusProperties busProperties,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadPoolTaskExecutor) {
- super(environment, properties, kubernetesClient, strategy, configMapPropertySourceLocator,
+ super(environment, properties, kubernetesClient, strategy, fabric8ConfigMapPropertySourceLocator,
k8SConfigurationProperties, threadPoolTaskExecutor);
this.busProperties = busProperties;
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedSecretsWatcherChangeDetector.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedSecretsWatcherChangeDetector.java
index 74bce19d..44677032 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedSecretsWatcherChangeDetector.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedSecretsWatcherChangeDetector.java
@@ -22,9 +22,9 @@ import reactor.core.publisher.Mono;
import org.springframework.cloud.bus.BusProperties;
import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
-import org.springframework.cloud.kubernetes.config.SecretsPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.reload.ConfigReloadProperties;
-import org.springframework.cloud.kubernetes.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.core.env.AbstractEnvironment;
@@ -43,10 +43,10 @@ public class BusEventBasedSecretsWatcherChangeDetector extends SecretsWatcherCha
public BusEventBasedSecretsWatcherChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
- SecretsPropertySourceLocator secretsPropertySourceLocator, BusProperties busProperties,
+ Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator, BusProperties busProperties,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadPoolTaskExecutor) {
- super(environment, properties, kubernetesClient, strategy, secretsPropertySourceLocator,
+ super(environment, properties, kubernetesClient, strategy, fabric8SecretsPropertySourceLocator,
k8SConfigurationProperties, threadPoolTaskExecutor);
this.busProperties = busProperties;
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigMapWatcherChangeDetector.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigMapWatcherChangeDetector.java
index 8266b603..02d6ffb0 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigMapWatcherChangeDetector.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigMapWatcherChangeDetector.java
@@ -26,10 +26,10 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Mono;
-import org.springframework.cloud.kubernetes.config.ConfigMapPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.reload.ConfigReloadProperties;
-import org.springframework.cloud.kubernetes.config.reload.ConfigurationUpdateStrategy;
-import org.springframework.cloud.kubernetes.config.reload.EventBasedConfigMapChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
+import org.springframework.cloud.kubernetes.fabric8.config.reload.EventBasedConfigMapChangeDetector;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@@ -47,10 +47,10 @@ public abstract class ConfigMapWatcherChangeDetector extends EventBasedConfigMap
public ConfigMapWatcherChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
- ConfigMapPropertySourceLocator configMapPropertySourceLocator,
+ Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadPoolTaskExecutor) {
- super(environment, properties, kubernetesClient, strategy, configMapPropertySourceLocator);
+ super(environment, properties, kubernetesClient, strategy, fabric8ConfigMapPropertySourceLocator);
this.executorService = Executors.newScheduledThreadPool(k8SConfigurationProperties.getThreadPoolSize(),
threadPoolTaskExecutor);
this.k8SConfigurationProperties = k8SConfigurationProperties;
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherAutoConfiguration.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherAutoConfiguration.java
index 058c52d8..8678023b 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherAutoConfiguration.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherAutoConfiguration.java
@@ -23,11 +23,11 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.bus.BusProperties;
import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration;
-import org.springframework.cloud.kubernetes.config.ConfigMapPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.SecretsPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.reload.ConfigReloadProperties;
-import org.springframework.cloud.kubernetes.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.discovery.reactive.KubernetesReactiveDiscoveryClient;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -53,27 +53,28 @@ public class ConfigurationWatcherAutoConfiguration {
@Bean
@ConditionalOnMissingBean(ConfigMapWatcherChangeDetector.class)
public ConfigMapWatcherChangeDetector httpBasedConfigMapWatchChangeDetector(AbstractEnvironment environment,
- KubernetesClient kubernetesClient, ConfigMapPropertySourceLocator configMapPropertySourceLocator,
- SecretsPropertySourceLocator secretsPropertySourceLocator, ConfigReloadProperties properties,
+ KubernetesClient kubernetesClient,
+ Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator,
+ Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator, ConfigReloadProperties properties,
ConfigurationUpdateStrategy strategy,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadFactory, WebClient webClient,
KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient) {
return new HttpBasedConfigMapWatchChangeDetector(environment, properties, kubernetesClient, strategy,
- configMapPropertySourceLocator, k8SConfigurationProperties, threadFactory, webClient,
+ fabric8ConfigMapPropertySourceLocator, k8SConfigurationProperties, threadFactory, webClient,
kubernetesReactiveDiscoveryClient);
}
@Bean
@ConditionalOnMissingBean(SecretsWatcherChangeDetector.class)
public SecretsWatcherChangeDetector httpBasedSecretsWatchChangeDetector(AbstractEnvironment environment,
- KubernetesClient kubernetesClient, SecretsPropertySourceLocator secretsPropertySourceLocator,
+ KubernetesClient kubernetesClient, Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator,
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadFactory, WebClient webClient,
KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient) {
return new HttpBasedSecretsWatchChangeDetector(environment, properties, kubernetesClient, strategy,
- secretsPropertySourceLocator, k8SConfigurationProperties, threadFactory, webClient,
+ fabric8SecretsPropertySourceLocator, k8SConfigurationProperties, threadFactory, webClient,
kubernetesReactiveDiscoveryClient);
}
@@ -86,24 +87,24 @@ public class ConfigurationWatcherAutoConfiguration {
@ConditionalOnMissingBean(ConfigMapWatcherChangeDetector.class)
public ConfigMapWatcherChangeDetector busConfigMapChangeWatcher(BusProperties busProperties,
AbstractEnvironment environment, KubernetesClient kubernetesClient,
- ConfigMapPropertySourceLocator configMapPropertySourceLocator, ConfigReloadProperties properties,
- ConfigurationUpdateStrategy strategy,
+ Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator,
+ ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadFactory) {
return new BusEventBasedConfigMapWatcherChangeDetector(environment, properties, kubernetesClient, strategy,
- configMapPropertySourceLocator, busProperties, k8SConfigurationProperties, threadFactory);
+ fabric8ConfigMapPropertySourceLocator, busProperties, k8SConfigurationProperties, threadFactory);
}
@Bean
@ConditionalOnMissingBean(SecretsWatcherChangeDetector.class)
public SecretsWatcherChangeDetector busSecretsChangeWatcher(BusProperties busProperties,
AbstractEnvironment environment, KubernetesClient kubernetesClient,
- SecretsPropertySourceLocator secretsPropertySourceLocator, ConfigReloadProperties properties,
- ConfigurationUpdateStrategy strategy,
+ Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator,
+ ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadFactory) {
return new BusEventBasedSecretsWatcherChangeDetector(environment, properties, kubernetesClient, strategy,
- secretsPropertySourceLocator, busProperties, k8SConfigurationProperties, threadFactory);
+ fabric8SecretsPropertySourceLocator, busProperties, k8SConfigurationProperties, threadFactory);
}
}
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigMapWatchChangeDetector.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigMapWatchChangeDetector.java
index 7d910db7..ea6c8eea 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigMapWatchChangeDetector.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigMapWatchChangeDetector.java
@@ -27,10 +27,10 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.cloud.client.ServiceInstance;
-import org.springframework.cloud.kubernetes.config.ConfigMapPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.reload.ConfigReloadProperties;
-import org.springframework.cloud.kubernetes.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.discovery.reactive.KubernetesReactiveDiscoveryClient;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@@ -57,11 +57,11 @@ public class HttpBasedConfigMapWatchChangeDetector extends ConfigMapWatcherChang
public HttpBasedConfigMapWatchChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
- ConfigMapPropertySourceLocator configMapPropertySourceLocator,
+ Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadPoolTaskExecutor, WebClient webClient,
KubernetesReactiveDiscoveryClient k8sReactiveDiscoveryClient) {
- super(environment, properties, kubernetesClient, strategy, configMapPropertySourceLocator,
+ super(environment, properties, kubernetesClient, strategy, fabric8ConfigMapPropertySourceLocator,
k8SConfigurationProperties, threadPoolTaskExecutor);
this.webClient = webClient;
this.kubernetesReactiveDiscoveryClient = k8sReactiveDiscoveryClient;
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedSecretsWatchChangeDetector.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedSecretsWatchChangeDetector.java
index c9192508..29b13dcd 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedSecretsWatchChangeDetector.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedSecretsWatchChangeDetector.java
@@ -25,10 +25,10 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.cloud.client.ServiceInstance;
-import org.springframework.cloud.kubernetes.config.SecretsPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.reload.ConfigReloadProperties;
-import org.springframework.cloud.kubernetes.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.discovery.reactive.KubernetesReactiveDiscoveryClient;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@@ -53,11 +53,11 @@ public class HttpBasedSecretsWatchChangeDetector extends SecretsWatcherChangeDet
public HttpBasedSecretsWatchChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
- SecretsPropertySourceLocator secretsPropertySourceLocator,
+ Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadPoolTaskExecutor, WebClient webClient,
KubernetesReactiveDiscoveryClient k8sReactiveDiscoveryClient) {
- super(environment, properties, kubernetesClient, strategy, secretsPropertySourceLocator,
+ super(environment, properties, kubernetesClient, strategy, fabric8SecretsPropertySourceLocator,
k8SConfigurationProperties, threadPoolTaskExecutor);
this.webClient = webClient;
this.kubernetesReactiveDiscoveryClient = k8sReactiveDiscoveryClient;
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/SecretsWatcherChangeDetector.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/SecretsWatcherChangeDetector.java
index 01b714d0..e81adba5 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/SecretsWatcherChangeDetector.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/SecretsWatcherChangeDetector.java
@@ -26,10 +26,10 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Mono;
-import org.springframework.cloud.kubernetes.config.SecretsPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.reload.ConfigReloadProperties;
-import org.springframework.cloud.kubernetes.config.reload.ConfigurationUpdateStrategy;
-import org.springframework.cloud.kubernetes.config.reload.EventBasedSecretsChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
+import org.springframework.cloud.kubernetes.fabric8.config.reload.EventBasedSecretsChangeDetector;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@@ -47,10 +47,10 @@ public abstract class SecretsWatcherChangeDetector extends EventBasedSecretsChan
public SecretsWatcherChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
- SecretsPropertySourceLocator secretsPropertySourceLocator,
+ Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator,
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
ThreadPoolTaskExecutor threadPoolTaskExecutor) {
- super(environment, properties, kubernetesClient, strategy, secretsPropertySourceLocator);
+ super(environment, properties, kubernetesClient, strategy, fabric8SecretsPropertySourceLocator);
this.executorService = Executors.newScheduledThreadPool(k8SConfigurationProperties.getThreadPoolSize(),
threadPoolTaskExecutor);
this.k8SConfigurationProperties = k8SConfigurationProperties;
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigMapWatcherChangeDetectorTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigMapWatcherChangeDetectorTests.java
index 6c8f62d2..ea7effb1 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigMapWatcherChangeDetectorTests.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigMapWatcherChangeDetectorTests.java
@@ -28,9 +28,9 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.cloud.bus.BusProperties;
import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
-import org.springframework.cloud.kubernetes.config.ConfigMapPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.reload.ConfigReloadProperties;
-import org.springframework.cloud.kubernetes.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@@ -52,7 +52,7 @@ public class BusEventBasedConfigMapWatcherChangeDetectorTests {
private ConfigurationUpdateStrategy updateStrategy;
@Mock
- private ConfigMapPropertySourceLocator configMapPropertySourceLocator;
+ private Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator;
@Mock
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@@ -73,7 +73,7 @@ public class BusEventBasedConfigMapWatcherChangeDetectorTests {
configurationWatcherConfigurationProperties = new ConfigurationWatcherConfigurationProperties();
busProperties = new BusProperties();
changeDetector = new BusEventBasedConfigMapWatcherChangeDetector(mockEnvironment, configReloadProperties,
- client, updateStrategy, configMapPropertySourceLocator, busProperties,
+ client, updateStrategy, fabric8ConfigMapPropertySourceLocator, busProperties,
configurationWatcherConfigurationProperties, threadPoolTaskExecutor);
changeDetector.setApplicationEventPublisher(applicationEventPublisher);
}
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedSecretsWatcherChangeDetectorTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedSecretsWatcherChangeDetectorTests.java
index 0266f069..109ecb30 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedSecretsWatcherChangeDetectorTests.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedSecretsWatcherChangeDetectorTests.java
@@ -28,9 +28,9 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.cloud.bus.BusProperties;
import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
-import org.springframework.cloud.kubernetes.config.SecretsPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.reload.ConfigReloadProperties;
-import org.springframework.cloud.kubernetes.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@@ -52,7 +52,7 @@ public class BusEventBasedSecretsWatcherChangeDetectorTests {
private ConfigurationUpdateStrategy updateStrategy;
@Mock
- private SecretsPropertySourceLocator secretsPropertySourceLocator;
+ private Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator;
@Mock
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@@ -73,7 +73,7 @@ public class BusEventBasedSecretsWatcherChangeDetectorTests {
configurationWatcherConfigurationProperties = new ConfigurationWatcherConfigurationProperties();
busProperties = new BusProperties();
changeDetector = new BusEventBasedSecretsWatcherChangeDetector(mockEnvironment, configReloadProperties, client,
- updateStrategy, secretsPropertySourceLocator, busProperties,
+ updateStrategy, fabric8SecretsPropertySourceLocator, busProperties,
configurationWatcherConfigurationProperties, threadPoolTaskExecutor);
changeDetector.setApplicationEventPublisher(applicationEventPublisher);
}
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigMapWatchChangeDetectorTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigMapWatchChangeDetectorTests.java
index e77fc279..ad37e3bf 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigMapWatchChangeDetectorTests.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigMapWatchChangeDetectorTests.java
@@ -38,11 +38,11 @@ import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
import org.springframework.cloud.client.ServiceInstance;
-import org.springframework.cloud.kubernetes.config.ConfigMapPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.reload.ConfigReloadProperties;
-import org.springframework.cloud.kubernetes.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.discovery.KubernetesServiceInstance;
import org.springframework.cloud.kubernetes.discovery.reactive.KubernetesReactiveDiscoveryClient;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.reactive.function.client.WebClient;
@@ -74,7 +74,7 @@ public class HttpBasedConfigMapWatchChangeDetectorTests {
private ConfigurationUpdateStrategy updateStrategy;
@Mock
- private ConfigMapPropertySourceLocator configMapPropertySourceLocator;
+ private Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator;
@Mock
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@@ -103,7 +103,7 @@ public class HttpBasedConfigMapWatchChangeDetectorTests {
configurationWatcherConfigurationProperties = new ConfigurationWatcherConfigurationProperties();
WebClient webClient = WebClient.builder().build();
changeDetector = new HttpBasedConfigMapWatchChangeDetector(mockEnvironment, configReloadProperties, client,
- updateStrategy, configMapPropertySourceLocator, configurationWatcherConfigurationProperties,
+ updateStrategy, fabric8ConfigMapPropertySourceLocator, configurationWatcherConfigurationProperties,
threadPoolTaskExecutor, webClient, reactiveDiscoveryClient);
}
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedSecretsWatchChangeDetectorTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedSecretsWatchChangeDetectorTests.java
index e9ff1588..3b177bae 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedSecretsWatchChangeDetectorTests.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedSecretsWatchChangeDetectorTests.java
@@ -38,11 +38,11 @@ import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
import org.springframework.cloud.client.ServiceInstance;
-import org.springframework.cloud.kubernetes.config.SecretsPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.reload.ConfigReloadProperties;
-import org.springframework.cloud.kubernetes.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.cloud.kubernetes.discovery.KubernetesServiceInstance;
import org.springframework.cloud.kubernetes.discovery.reactive.KubernetesReactiveDiscoveryClient;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.reactive.function.client.WebClient;
@@ -74,7 +74,7 @@ public class HttpBasedSecretsWatchChangeDetectorTests {
private ConfigurationUpdateStrategy updateStrategy;
@Mock
- private SecretsPropertySourceLocator secretsPropertySourceLocator;
+ private Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator;
@Mock
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@@ -103,7 +103,7 @@ public class HttpBasedSecretsWatchChangeDetectorTests {
configurationWatcherConfigurationProperties = new ConfigurationWatcherConfigurationProperties();
WebClient webClient = WebClient.builder().build();
changeDetector = new HttpBasedSecretsWatchChangeDetector(mockEnvironment, configReloadProperties, client,
- updateStrategy, secretsPropertySourceLocator, configurationWatcherConfigurationProperties,
+ updateStrategy, fabric8SecretsPropertySourceLocator, configurationWatcherConfigurationProperties,
threadPoolTaskExecutor, webClient, reactiveDiscoveryClient);
}
diff --git a/spring-cloud-kubernetes-dependencies/pom.xml b/spring-cloud-kubernetes-dependencies/pom.xml
index cfca9df6..3277b9c7 100644
--- a/spring-cloud-kubernetes-dependencies/pom.xml
+++ b/spring-cloud-kubernetes-dependencies/pom.xml
@@ -77,7 +77,13 @@
org.springframework.cloud
- spring-cloud-kubernetes-config
+ spring-cloud-kubernetes-fabric8-config
+ ${project.version}
+
+
+
+ org.springframework.cloud
+ spring-cloud-kubernetes-client-config
${project.version}
diff --git a/spring-cloud-kubernetes-config/.jdk8 b/spring-cloud-kubernetes-fabric8-config/.jdk8
similarity index 100%
rename from spring-cloud-kubernetes-config/.jdk8
rename to spring-cloud-kubernetes-fabric8-config/.jdk8
diff --git a/spring-cloud-kubernetes-config/pom.xml b/spring-cloud-kubernetes-fabric8-config/pom.xml
similarity index 97%
rename from spring-cloud-kubernetes-config/pom.xml
rename to spring-cloud-kubernetes-fabric8-config/pom.xml
index 4a537063..f243e21a 100644
--- a/spring-cloud-kubernetes-config/pom.xml
+++ b/spring-cloud-kubernetes-fabric8-config/pom.xml
@@ -10,8 +10,8 @@
4.0.0
org.springframework.cloud
- spring-cloud-kubernetes-config
- Spring Cloud Kubernetes :: Config
+ spring-cloud-kubernetes-fabric8-config
+ Spring Cloud Kubernetes :: Fabric8 Config
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/BootstrapConfiguration.java b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8BootstrapConfiguration.java
similarity index 70%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/BootstrapConfiguration.java
rename to spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8BootstrapConfiguration.java
index 3a88b26b..6848089d 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/BootstrapConfiguration.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8BootstrapConfiguration.java
@@ -14,17 +14,20 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.kubernetes.commons.KubernetesCommonsAutoConfiguration;
+import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties;
+import org.springframework.cloud.kubernetes.commons.config.KubernetesBootstrapConfiguration;
+import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties;
import org.springframework.cloud.kubernetes.fabric8.Fabric8AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -38,11 +41,11 @@ import org.springframework.context.annotation.Import;
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "spring.cloud.kubernetes.enabled", matchIfMissing = true)
@ConditionalOnClass({ ConfigMap.class, Secret.class })
-public class BootstrapConfiguration {
+@AutoConfigureAfter(KubernetesBootstrapConfiguration.class)
+public class Fabric8BootstrapConfiguration {
@Configuration(proxyBeanMethods = false)
@Import({ KubernetesCommonsAutoConfiguration.class, Fabric8AutoConfiguration.class })
- @EnableConfigurationProperties({ ConfigMapConfigProperties.class, SecretsConfigProperties.class })
protected static class KubernetesPropertySourceConfiguration {
@Autowired
@@ -50,14 +53,15 @@ public class BootstrapConfiguration {
@Bean
@ConditionalOnProperty(name = "spring.cloud.kubernetes.config.enabled", matchIfMissing = true)
- public ConfigMapPropertySourceLocator configMapPropertySourceLocator(ConfigMapConfigProperties properties) {
- return new ConfigMapPropertySourceLocator(this.client, properties);
+ public Fabric8ConfigMapPropertySourceLocator configMapPropertySourceLocator(
+ ConfigMapConfigProperties properties) {
+ return new Fabric8ConfigMapPropertySourceLocator(this.client, properties);
}
@Bean
@ConditionalOnProperty(name = "spring.cloud.kubernetes.secrets.enabled", matchIfMissing = true)
- public SecretsPropertySourceLocator secretsPropertySourceLocator(SecretsConfigProperties properties) {
- return new SecretsPropertySourceLocator(this.client, properties);
+ public Fabric8SecretsPropertySourceLocator secretsPropertySourceLocator(SecretsConfigProperties properties) {
+ return new Fabric8SecretsPropertySourceLocator(this.client, properties);
}
}
diff --git a/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapPropertySource.java b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapPropertySource.java
new file mode 100644
index 00000000..61a8f6cf
--- /dev/null
+++ b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapPropertySource.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2013-2019 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.config;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import io.fabric8.kubernetes.api.model.ConfigMap;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.cloud.kubernetes.commons.config.ConfigMapPropertySource;
+import org.springframework.core.env.Environment;
+import org.springframework.core.env.MapPropertySource;
+import org.springframework.util.StringUtils;
+
+/**
+ * A {@link MapPropertySource} that uses Kubernetes config maps.
+ *
+ * @author Ioannis Canellos
+ * @author Ali Shahbour
+ * @author Michael Moudatsos
+ */
+public class Fabric8ConfigMapPropertySource extends ConfigMapPropertySource {
+
+ private static final Log LOG = LogFactory.getLog(Fabric8ConfigMapPropertySource.class);
+
+ public Fabric8ConfigMapPropertySource(KubernetesClient client, String name) {
+ this(client, name, null, (Environment) null);
+ }
+
+ public Fabric8ConfigMapPropertySource(KubernetesClient client, String name, String namespace,
+ Environment environment) {
+ super(getName(name, getNamespace(client, namespace)),
+ asObjectMap(getData(client, name, getNamespace(client, namespace), environment)));
+ }
+
+ private static String getNamespace(KubernetesClient client, String namespace) {
+ return StringUtils.isEmpty(namespace) ? client.getNamespace() : namespace;
+ }
+
+ private static Map getData(KubernetesClient client, String name, String namespace,
+ Environment environment) {
+ try {
+ Map result = new LinkedHashMap<>();
+ ConfigMap map = StringUtils.isEmpty(namespace) ? client.configMaps().withName(name).get()
+ : client.configMaps().inNamespace(namespace).withName(name).get();
+
+ if (map != null) {
+ result.putAll(processAllEntries(map.getData(), environment));
+ }
+
+ if (environment != null) {
+ for (String activeProfile : environment.getActiveProfiles()) {
+
+ String mapNameWithProfile = name + "-" + activeProfile;
+
+ ConfigMap mapWithProfile = StringUtils.isEmpty(namespace)
+ ? client.configMaps().withName(mapNameWithProfile).get()
+ : client.configMaps().inNamespace(namespace).withName(mapNameWithProfile).get();
+
+ if (mapWithProfile != null) {
+ result.putAll(processAllEntries(mapWithProfile.getData(), environment));
+ }
+
+ }
+ }
+
+ return result;
+
+ }
+ catch (Exception e) {
+ LOG.warn("Can't read configMap with name: [" + name + "] in namespace:[" + namespace + "]. Ignoring.", e);
+ }
+
+ return new LinkedHashMap<>();
+ }
+
+}
diff --git a/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapPropertySourceLocator.java b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapPropertySourceLocator.java
new file mode 100644
index 00000000..a6c6947b
--- /dev/null
+++ b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapPropertySourceLocator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2013-2019 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.config;
+
+import io.fabric8.kubernetes.client.KubernetesClient;
+
+import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
+import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties;
+import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties.NormalizedSource;
+import org.springframework.cloud.kubernetes.commons.config.ConfigMapPropertySourceLocator;
+import org.springframework.core.annotation.Order;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.MapPropertySource;
+
+import static org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigUtils.getApplicationNamespace;
+
+/**
+ * A {@link PropertySourceLocator} that uses config maps.
+ *
+ * @author Ioannis Canellos
+ * @author Michael Moudatsos
+ */
+@Order(0)
+public class Fabric8ConfigMapPropertySourceLocator extends ConfigMapPropertySourceLocator {
+
+ private final KubernetesClient client;
+
+ public Fabric8ConfigMapPropertySourceLocator(KubernetesClient client, ConfigMapConfigProperties properties) {
+ super(properties);
+ this.client = client;
+ }
+
+ @Override
+ protected MapPropertySource getMapPropertySource(String name, NormalizedSource normalizedSource,
+ String configurationTarget, ConfigurableEnvironment environment) {
+ return new Fabric8ConfigMapPropertySource(this.client, name,
+ getApplicationNamespace(this.client, normalizedSource.getNamespace(), configurationTarget),
+ environment);
+ }
+
+}
diff --git a/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigUtils.java b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigUtils.java
new file mode 100644
index 00000000..8e8091f7
--- /dev/null
+++ b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigUtils.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2013-2019 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.config;
+
+import io.fabric8.kubernetes.client.KubernetesClient;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.util.StringUtils;
+
+/**
+ * Utility class that works with configuration properties.
+ *
+ * @author Ioannis Canellos
+ */
+public final class Fabric8ConfigUtils {
+
+ private static final Log LOG = LogFactory.getLog(Fabric8ConfigUtils.class);
+
+ private Fabric8ConfigUtils() {
+ }
+
+ public static String getApplicationNamespace(KubernetesClient client, String configNamespace,
+ String configurationTarget) {
+ if (StringUtils.isEmpty(configNamespace)) {
+ LOG.debug(configurationTarget + " namespace has not been set, taking it from client (ns="
+ + client.getNamespace() + ")");
+ configNamespace = client.getNamespace();
+ }
+
+ return configNamespace;
+ }
+
+}
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsPropertySource.java b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySource.java
similarity index 66%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsPropertySource.java
rename to spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySource.java
index 7c96c1db..ba697a1c 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsPropertySource.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySource.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
-import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
@@ -25,8 +24,8 @@ import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.cloud.kubernetes.commons.config.SecretsPropertySource;
import org.springframework.core.env.Environment;
-import org.springframework.core.env.MapPropertySource;
import org.springframework.util.StringUtils;
/**
@@ -35,20 +34,15 @@ import org.springframework.util.StringUtils;
* @author l burgazzoli
* @author Haytham Mohamed
*/
-public class SecretsPropertySource extends MapPropertySource {
+public class Fabric8SecretsPropertySource extends SecretsPropertySource {
- private static final Log LOG = LogFactory.getLog(SecretsPropertySource.class);
+ private static final Log LOG = LogFactory.getLog(Fabric8SecretsPropertySource.class);
private static final String PREFIX = "secrets";
- public SecretsPropertySource(KubernetesClient client, Environment env, String name, String namespace,
+ public Fabric8SecretsPropertySource(KubernetesClient client, Environment env, String name, String namespace,
Map labels) {
- super(getSourceName(client, env, name, namespace), getSourceData(client, env, name, namespace, labels));
- }
-
- private static String getSourceName(KubernetesClient client, Environment env, String name, String namespace) {
- return new StringBuilder().append(PREFIX).append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(name)
- .append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(namespace).toString();
+ super(getSourceName(name, namespace), getSourceData(client, env, name, namespace, labels));
}
private static Map getSourceData(KubernetesClient client, Environment env, String name,
@@ -85,18 +79,10 @@ public class SecretsPropertySource extends MapPropertySource {
return result;
}
- // *****************************
- // Helpers
- // *****************************
private static void putAll(Secret secret, Map result) {
- if (secret != null && secret.getData() != null) {
- secret.getData().forEach((k, v) -> result.put(k, new String(Base64.getDecoder().decode(v)).trim()));
+ if (secret != null) {
+ putAll(secret.getData(), result);
}
}
- @Override
- public String toString() {
- return getClass().getSimpleName() + " {name='" + this.name + "'}";
- }
-
}
diff --git a/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySourceLocator.java b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySourceLocator.java
new file mode 100644
index 00000000..df725867
--- /dev/null
+++ b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySourceLocator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2013-2019 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.config;
+
+import io.fabric8.kubernetes.client.KubernetesClient;
+
+import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
+import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties;
+import org.springframework.cloud.kubernetes.commons.config.SecretsPropertySourceLocator;
+import org.springframework.core.annotation.Order;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.MapPropertySource;
+
+import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.getApplicationName;
+
+/**
+ * Kubernetes {@link PropertySourceLocator} for secrets.
+ *
+ * @author l burgazzoli
+ * @author Haytham Mohamed
+ */
+@Order(1)
+public class Fabric8SecretsPropertySourceLocator extends SecretsPropertySourceLocator {
+
+ private final KubernetesClient client;
+
+ public Fabric8SecretsPropertySourceLocator(KubernetesClient client, SecretsConfigProperties properties) {
+ super(properties);
+ this.client = client;
+ }
+
+ @Override
+ protected MapPropertySource getPropertySource(ConfigurableEnvironment environment,
+ SecretsConfigProperties.NormalizedSource normalizedSource, String configurationTarget) {
+ return new Fabric8SecretsPropertySource(this.client, environment,
+ getApplicationName(environment, normalizedSource.getName(), configurationTarget), Fabric8ConfigUtils
+ .getApplicationNamespace(this.client, normalizedSource.getNamespace(), configurationTarget),
+ normalizedSource.getLabels());
+ }
+
+}
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/ConfigReloadAutoConfiguration.java
similarity index 72%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadAutoConfiguration.java
rename to spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/ConfigReloadAutoConfiguration.java
index 509609d1..f8381e9c 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadAutoConfiguration.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/ConfigReloadAutoConfiguration.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.reload;
+package org.springframework.cloud.kubernetes.fabric8.config.reload;
import java.util.concurrent.ThreadLocalRandom;
@@ -33,10 +33,17 @@ import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.cloud.context.restart.RestartEndpoint;
-import org.springframework.cloud.kubernetes.config.ConfigMapPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.SecretsPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.reload.condition.EventReloadDetectionMode;
-import org.springframework.cloud.kubernetes.config.reload.condition.PollingReloadDetectionMode;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.commons.config.reload.PollingConfigMapChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.PollingSecretsChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.condition.EventReloadDetectionMode;
+import org.springframework.cloud.kubernetes.commons.config.reload.condition.PollingReloadDetectionMode;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySource;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySource;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
@@ -79,68 +86,72 @@ public class ConfigReloadAutoConfiguration {
* Polling configMap ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
- * @param configMapPropertySourceLocator configMap property source locator
+ * @param fabric8ConfigMapPropertySourceLocator configMap property source locator
* @return a bean that listen to configuration changes and fire a reload.
*/
@Bean
- @ConditionalOnBean(ConfigMapPropertySourceLocator.class)
+ @ConditionalOnBean(Fabric8ConfigMapPropertySourceLocator.class)
@Conditional(PollingReloadDetectionMode.class)
public ConfigurationChangeDetector configMapPropertyChangePollingWatcher(ConfigReloadProperties properties,
- ConfigurationUpdateStrategy strategy, ConfigMapPropertySourceLocator configMapPropertySourceLocator) {
+ ConfigurationUpdateStrategy strategy,
+ Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator) {
- return new PollingConfigMapChangeDetector(this.environment, properties, this.kubernetesClient, strategy,
- configMapPropertySourceLocator);
+ return new PollingConfigMapChangeDetector(this.environment, properties, strategy,
+ Fabric8ConfigMapPropertySource.class, fabric8ConfigMapPropertySourceLocator);
}
/**
* Polling secrets ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
- * @param secretsPropertySourceLocator secrets property source locator
+ * @param fabric8SecretsPropertySourceLocator secrets property source locator
* @return a bean that listen to configuration changes and fire a reload.
*/
@Bean
- @ConditionalOnBean(SecretsPropertySourceLocator.class)
+ @ConditionalOnBean(Fabric8SecretsPropertySourceLocator.class)
@Conditional(PollingReloadDetectionMode.class)
public ConfigurationChangeDetector secretsPropertyChangePollingWatcher(ConfigReloadProperties properties,
- ConfigurationUpdateStrategy strategy, SecretsPropertySourceLocator secretsPropertySourceLocator) {
+ ConfigurationUpdateStrategy strategy,
+ Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator) {
- return new PollingSecretsChangeDetector(this.environment, properties, this.kubernetesClient, strategy,
- secretsPropertySourceLocator);
+ return new PollingSecretsChangeDetector(this.environment, properties, strategy,
+ Fabric8SecretsPropertySource.class, fabric8SecretsPropertySourceLocator);
}
/**
* Event Based configMap ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
- * @param configMapPropertySourceLocator configMap property source locator
+ * @param fabric8ConfigMapPropertySourceLocator configMap property source locator
* @return a bean that listen to configMap change events and fire a reload.
*/
@Bean
- @ConditionalOnBean(ConfigMapPropertySourceLocator.class)
+ @ConditionalOnBean(Fabric8ConfigMapPropertySourceLocator.class)
@Conditional(EventReloadDetectionMode.class)
public ConfigurationChangeDetector configMapPropertyChangeEventWatcher(ConfigReloadProperties properties,
- ConfigurationUpdateStrategy strategy, ConfigMapPropertySourceLocator configMapPropertySourceLocator) {
+ ConfigurationUpdateStrategy strategy,
+ Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator) {
return new EventBasedConfigMapChangeDetector(this.environment, properties, this.kubernetesClient, strategy,
- configMapPropertySourceLocator);
+ fabric8ConfigMapPropertySourceLocator);
}
/**
* Event Based secrets ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
- * @param secretsPropertySourceLocator secrets property source locator
+ * @param fabric8SecretsPropertySourceLocator secrets property source locator
* @return a bean that listen to secrets change events and fire a reload.
*/
@Bean
- @ConditionalOnBean(SecretsPropertySourceLocator.class)
+ @ConditionalOnBean(Fabric8SecretsPropertySourceLocator.class)
@Conditional(EventReloadDetectionMode.class)
public ConfigurationChangeDetector secretsPropertyChangeEventWatcher(ConfigReloadProperties properties,
- ConfigurationUpdateStrategy strategy, SecretsPropertySourceLocator secretsPropertySourceLocator) {
+ ConfigurationUpdateStrategy strategy,
+ Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator) {
return new EventBasedSecretsChangeDetector(this.environment, properties, this.kubernetesClient, strategy,
- secretsPropertySourceLocator);
+ fabric8SecretsPropertySourceLocator);
}
/**
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadDefaultAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/ConfigReloadDefaultAutoConfiguration.java
similarity index 66%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadDefaultAutoConfiguration.java
rename to spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/ConfigReloadDefaultAutoConfiguration.java
index 621bf03d..b6e381e5 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadDefaultAutoConfiguration.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/ConfigReloadDefaultAutoConfiguration.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.reload;
+package org.springframework.cloud.kubernetes.fabric8.config.reload;
import java.util.concurrent.ThreadLocalRandom;
@@ -25,10 +25,17 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.cloud.kubernetes.config.ConfigMapPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.SecretsPropertySourceLocator;
-import org.springframework.cloud.kubernetes.config.reload.condition.EventReloadDetectionMode;
-import org.springframework.cloud.kubernetes.config.reload.condition.PollingReloadDetectionMode;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.commons.config.reload.PollingConfigMapChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.PollingSecretsChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.condition.EventReloadDetectionMode;
+import org.springframework.cloud.kubernetes.commons.config.reload.condition.PollingReloadDetectionMode;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySource;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySource;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
@@ -62,77 +69,90 @@ public class ConfigReloadDefaultAutoConfiguration {
private KubernetesClient kubernetesClient;
@Autowired
- private ConfigMapPropertySourceLocator configMapPropertySourceLocator;
+ private Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator;
@Autowired
- private SecretsPropertySourceLocator secretsPropertySourceLocator;
+ private Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator;
+
+ private static void wait(ConfigReloadProperties properties) {
+ final long waitMillis = ThreadLocalRandom.current().nextLong(properties.getMaxWaitForRestart().toMillis());
+ try {
+ Thread.sleep(waitMillis);
+ }
+ catch (InterruptedException ignored) {
+ }
+ }
/**
* Polling configMap ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
- * @param configMapPropertySourceLocator configMap property source locator
+ * @param fabric8ConfigMapPropertySourceLocator configMap property source locator
* @return a bean that listen to configuration changes and fire a reload.
*/
@Bean
- @ConditionalOnBean(ConfigMapPropertySourceLocator.class)
+ @ConditionalOnBean(Fabric8ConfigMapPropertySourceLocator.class)
@Conditional(PollingReloadDetectionMode.class)
public ConfigurationChangeDetector configMapPropertyChangePollingWatcher(ConfigReloadProperties properties,
- ConfigurationUpdateStrategy strategy, ConfigMapPropertySourceLocator configMapPropertySourceLocator) {
+ ConfigurationUpdateStrategy strategy,
+ Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator) {
- return new PollingConfigMapChangeDetector(this.environment, properties, this.kubernetesClient, strategy,
- configMapPropertySourceLocator);
+ return new PollingConfigMapChangeDetector(this.environment, properties, strategy,
+ Fabric8ConfigMapPropertySource.class, fabric8ConfigMapPropertySourceLocator);
}
/**
* Polling secrets ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
- * @param secretsPropertySourceLocator secrets property source locator
+ * @param fabric8SecretsPropertySourceLocator secrets property source locator
* @return a bean that listen to configuration changes and fire a reload.
*/
@Bean
- @ConditionalOnBean(SecretsPropertySourceLocator.class)
+ @ConditionalOnBean(Fabric8SecretsPropertySourceLocator.class)
@Conditional(PollingReloadDetectionMode.class)
public ConfigurationChangeDetector secretsPropertyChangePollingWatcher(ConfigReloadProperties properties,
- ConfigurationUpdateStrategy strategy, SecretsPropertySourceLocator secretsPropertySourceLocator) {
+ ConfigurationUpdateStrategy strategy,
+ Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator) {
- return new PollingSecretsChangeDetector(this.environment, properties, this.kubernetesClient, strategy,
- secretsPropertySourceLocator);
+ return new PollingSecretsChangeDetector(this.environment, properties, strategy,
+ Fabric8SecretsPropertySource.class, fabric8SecretsPropertySourceLocator);
}
/**
* Event Based configMap ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
- * @param configMapPropertySourceLocator configMap property source locator
+ * @param fabric8ConfigMapPropertySourceLocator configMap property source locator
* @return a bean that listen to configMap change events and fire a reload.
*/
@Bean
- @ConditionalOnBean(ConfigMapPropertySourceLocator.class)
+ @ConditionalOnBean(Fabric8ConfigMapPropertySourceLocator.class)
@Conditional(EventReloadDetectionMode.class)
public ConfigurationChangeDetector configMapPropertyChangeEventWatcher(ConfigReloadProperties properties,
- ConfigurationUpdateStrategy strategy, ConfigMapPropertySourceLocator configMapPropertySourceLocator) {
+ ConfigurationUpdateStrategy strategy,
+ Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator) {
return new EventBasedConfigMapChangeDetector(this.environment, properties, this.kubernetesClient, strategy,
- configMapPropertySourceLocator);
+ fabric8ConfigMapPropertySourceLocator);
}
/**
* Event Based secrets ConfigurationChangeDetector.
* @param properties config reload properties
* @param strategy configuration update strategy
- * @param secretsPropertySourceLocator secrets property source locator
+ * @param fabric8SecretsPropertySourceLocator secrets property source locator
* @return a bean that listen to secrets change events and fire a reload.
*/
@Bean
- @ConditionalOnBean(SecretsPropertySourceLocator.class)
+ @ConditionalOnBean(Fabric8SecretsPropertySourceLocator.class)
@Conditional(EventReloadDetectionMode.class)
public ConfigurationChangeDetector secretsPropertyChangeEventWatcher(ConfigReloadProperties properties,
- ConfigurationUpdateStrategy strategy, SecretsPropertySourceLocator secretsPropertySourceLocator) {
+ ConfigurationUpdateStrategy strategy,
+ Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator) {
return new EventBasedSecretsChangeDetector(this.environment, properties, this.kubernetesClient, strategy,
- secretsPropertySourceLocator);
+ fabric8SecretsPropertySourceLocator);
}
/**
@@ -154,15 +174,6 @@ public class ConfigReloadDefaultAutoConfiguration {
throw new IllegalStateException("Unsupported configuration update strategy: " + properties.getStrategy());
}
- private static void wait(ConfigReloadProperties properties) {
- final long waitMillis = ThreadLocalRandom.current().nextLong(properties.getMaxWaitForRestart().toMillis());
- try {
- Thread.sleep(waitMillis);
- }
- catch (InterruptedException ignored) {
- }
- }
-
}
}
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigMapChangeDetector.java b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/EventBasedConfigMapChangeDetector.java
similarity index 70%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigMapChangeDetector.java
rename to spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/EventBasedConfigMapChangeDetector.java
index c7567d80..e19d5c13 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigMapChangeDetector.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/EventBasedConfigMapChangeDetector.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.reload;
+package org.springframework.cloud.kubernetes.fabric8.config.reload;
import java.util.HashMap;
import java.util.Map;
@@ -28,8 +28,11 @@ import io.fabric8.kubernetes.client.KubernetesClientException;
import io.fabric8.kubernetes.client.Watch;
import io.fabric8.kubernetes.client.Watcher;
-import org.springframework.cloud.kubernetes.config.ConfigMapPropertySource;
-import org.springframework.cloud.kubernetes.config.ConfigMapPropertySourceLocator;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySource;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
import org.springframework.core.env.AbstractEnvironment;
/**
@@ -42,19 +45,28 @@ import org.springframework.core.env.AbstractEnvironment;
*/
public class EventBasedConfigMapChangeDetector extends ConfigurationChangeDetector {
- private final ConfigMapPropertySourceLocator configMapPropertySourceLocator;
+ private final Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator;
private final Map watches;
+ private KubernetesClient kubernetesClient;
+
public EventBasedConfigMapChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
- ConfigMapPropertySourceLocator configMapPropertySourceLocator) {
- super(environment, properties, kubernetesClient, strategy);
-
- this.configMapPropertySourceLocator = configMapPropertySourceLocator;
+ Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator) {
+ super(environment, properties, strategy);
+ this.kubernetesClient = kubernetesClient;
+ this.fabric8ConfigMapPropertySourceLocator = fabric8ConfigMapPropertySourceLocator;
this.watches = new HashMap<>();
}
+ @PreDestroy
+ public void shutdown() {
+ // Ensure the kubernetes client is cleaned up from spare threads when shutting
+ // down
+ this.kubernetesClient.close();
+ }
+
@PostConstruct
public void watch() {
boolean activated = false;
@@ -107,8 +119,9 @@ public class EventBasedConfigMapChangeDetector extends ConfigurationChangeDetect
}
protected void onEvent(ConfigMap configMap) {
- boolean changed = changed(locateMapPropertySources(this.configMapPropertySourceLocator, this.environment),
- findPropertySources(ConfigMapPropertySource.class));
+ boolean changed = changed(
+ locateMapPropertySources(this.fabric8ConfigMapPropertySourceLocator, this.environment),
+ findPropertySources(Fabric8ConfigMapPropertySource.class));
if (changed) {
this.log.info("Detected change in config maps");
reloadProperties();
diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/EventBasedSecretsChangeDetector.java b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/EventBasedSecretsChangeDetector.java
similarity index 70%
rename from spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/EventBasedSecretsChangeDetector.java
rename to spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/EventBasedSecretsChangeDetector.java
index f3f24cb1..4e626668 100644
--- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/EventBasedSecretsChangeDetector.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/EventBasedSecretsChangeDetector.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.reload;
+package org.springframework.cloud.kubernetes.fabric8.config.reload;
import java.util.HashMap;
import java.util.Map;
@@ -28,8 +28,11 @@ import io.fabric8.kubernetes.client.KubernetesClientException;
import io.fabric8.kubernetes.client.Watch;
import io.fabric8.kubernetes.client.Watcher;
-import org.springframework.cloud.kubernetes.config.SecretsPropertySource;
-import org.springframework.cloud.kubernetes.config.SecretsPropertySourceLocator;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySource;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator;
import org.springframework.core.env.AbstractEnvironment;
/**
@@ -42,19 +45,28 @@ import org.springframework.core.env.AbstractEnvironment;
*/
public class EventBasedSecretsChangeDetector extends ConfigurationChangeDetector {
- private SecretsPropertySourceLocator secretsPropertySourceLocator;
+ private Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator;
private Map watches;
+ private KubernetesClient kubernetesClient;
+
public EventBasedSecretsChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
- SecretsPropertySourceLocator secretsPropertySourceLocator) {
- super(environment, properties, kubernetesClient, strategy);
-
- this.secretsPropertySourceLocator = secretsPropertySourceLocator;
+ Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator) {
+ super(environment, properties, strategy);
+ this.kubernetesClient = kubernetesClient;
+ this.fabric8SecretsPropertySourceLocator = fabric8SecretsPropertySourceLocator;
this.watches = new HashMap<>();
}
+ @PreDestroy
+ public void shutdown() {
+ // Ensure the kubernetes client is cleaned up from spare threads when shutting
+ // down
+ this.kubernetesClient.close();
+ }
+
@PostConstruct
public void watch() {
boolean activated = false;
@@ -107,8 +119,8 @@ public class EventBasedSecretsChangeDetector extends ConfigurationChangeDetector
}
protected void onEvent(Secret secret) {
- boolean changed = changed(locateMapPropertySources(this.secretsPropertySourceLocator, this.environment),
- findPropertySources(SecretsPropertySource.class));
+ boolean changed = changed(locateMapPropertySources(this.fabric8SecretsPropertySourceLocator, this.environment),
+ findPropertySources(Fabric8SecretsPropertySource.class));
if (changed) {
this.log.info("Detected change in secrets");
reloadProperties();
diff --git a/spring-cloud-kubernetes-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-kubernetes-fabric8-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json
similarity index 100%
rename from spring-cloud-kubernetes-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json
rename to spring-cloud-kubernetes-fabric8-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json
diff --git a/spring-cloud-kubernetes-fabric8-config/src/main/resources/META-INF/spring.factories b/spring-cloud-kubernetes-fabric8-config/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..79ca4b9f
--- /dev/null
+++ b/spring-cloud-kubernetes-fabric8-config/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,4 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+org.springframework.cloud.kubernetes.fabric8.config.reload.ConfigReloadAutoConfiguration
+org.springframework.cloud.bootstrap.BootstrapConfiguration=\
+org.springframework.cloud.kubernetes.fabric8.config.Fabric8BootstrapConfiguration
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapTestUtil.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapTestUtil.java
similarity index 95%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapTestUtil.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapTestUtil.java
index 5cb55d99..1955050d 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapTestUtil.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapTestUtil.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import java.io.IOException;
import java.nio.file.Files;
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsFromFilePathsTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsFromFilePathsTests.java
similarity index 89%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsFromFilePathsTests.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsFromFilePathsTests.java
index 99928dc6..a0ec697e 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsFromFilePathsTests.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsFromFilePathsTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import java.io.IOException;
import java.nio.file.Files;
@@ -31,12 +31,11 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.kubernetes.config.example.App;
+import org.springframework.cloud.kubernetes.fabric8.config.example.App;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.assertj.core.util.Lists.newArrayList;
-import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.createFileWithContent;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class,
@@ -86,10 +85,11 @@ public class ConfigMapsFromFilePathsTests {
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
Files.createDirectories(Paths.get(FILES_ROOT_PATH + "/" + FILES_SUB_PATH));
- createFileWithContent(FIRST_FILE_NAME_FULL_PATH, "bean.greeting=Hello from path!");
- createFileWithContent(SECOND_FILE_NAME_FULL_PATH, "bean.farewell=Bye from path!");
- createFileWithContent(UNUSED_FILE_NAME_FULL_PATH, "bean.morning=Morning from path!");
- createFileWithContent(FIRST_FILE_NAME_DUPLICATED_FULL_PATH, "bean.bonjour=Bonjour from path!");
+ ConfigMapTestUtil.createFileWithContent(FIRST_FILE_NAME_FULL_PATH, "bean.greeting=Hello from path!");
+ ConfigMapTestUtil.createFileWithContent(SECOND_FILE_NAME_FULL_PATH, "bean.farewell=Bye from path!");
+ ConfigMapTestUtil.createFileWithContent(UNUSED_FILE_NAME_FULL_PATH, "bean.morning=Morning from path!");
+ ConfigMapTestUtil.createFileWithContent(FIRST_FILE_NAME_DUPLICATED_FULL_PATH,
+ "bean.bonjour=Bonjour from path!");
}
@AfterClass
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsMixedTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsMixedTests.java
similarity index 93%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsMixedTests.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsMixedTests.java
index 08b42808..f5a24336 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsMixedTests.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsMixedTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import java.io.IOException;
import java.nio.file.Files;
@@ -33,12 +33,11 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.kubernetes.config.example.App;
+import org.springframework.cloud.kubernetes.fabric8.config.example.App;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.assertj.core.util.Lists.newArrayList;
-import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.readResourceFile;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class,
@@ -76,7 +75,8 @@ public class ConfigMapsMixedTests {
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
Files.createDirectories(Paths.get(FILES_ROOT_PATH));
- ConfigMapTestUtil.createFileWithContent(FILE_NAME_FULL_PATH, readResourceFile("application-path.yaml"));
+ ConfigMapTestUtil.createFileWithContent(FILE_NAME_FULL_PATH,
+ ConfigMapTestUtil.readResourceFile("application-path.yaml"));
HashMap data = new HashMap<>();
data.put("bean.morning", "Buenos Dias ConfigMap, %s");
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsTest.java
similarity index 87%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsTest.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsTest.java
index 0997152e..dcf20fbd 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsTest.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import java.util.Map;
@@ -27,7 +27,7 @@ import org.junit.Rule;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.readResourceFile;
+import static org.springframework.cloud.kubernetes.fabric8.config.ConfigMapTestUtil.readResourceFile;
/**
* @author Charles Moulliard
@@ -74,8 +74,8 @@ public class ConfigMapsTest {
.addToData("application.properties", readResourceFile("application.properties")).build())
.once();
- ConfigMapPropertySource cmps = new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace),
- configMapName);
+ Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(
+ this.server.getClient().inNamespace(namespace), configMapName);
assertThat(cmps.getProperty("dummy.property.string1")).isEqualTo("a");
assertThat(cmps.getProperty("dummy.property.int1")).isEqualTo("1");
@@ -91,8 +91,8 @@ public class ConfigMapsTest {
.addToData("application.yaml", readResourceFile("application.yaml")).build())
.once();
- ConfigMapPropertySource cmps = new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace),
- configMapName);
+ Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(
+ this.server.getClient().inNamespace(namespace), configMapName);
assertThat(cmps.getProperty("dummy.property.string2")).isEqualTo("a");
assertThat(cmps.getProperty("dummy.property.int2")).isEqualTo(1);
@@ -108,8 +108,8 @@ public class ConfigMapsTest {
.addToData("adhoc.yml", readResourceFile("adhoc.yml")).build())
.once();
- ConfigMapPropertySource cmps = new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace),
- configMapName);
+ Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(
+ this.server.getClient().inNamespace(namespace), configMapName);
assertThat(cmps.getProperty("dummy.property.string3")).isEqualTo("a");
assertThat(cmps.getProperty("dummy.property.int3")).isEqualTo(1);
@@ -125,7 +125,7 @@ public class ConfigMapsTest {
.addToData("application.properties", "somevalue").build())
.once();
- new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace), configMapName);
+ new Fabric8ConfigMapPropertySource(this.server.getClient().inNamespace(namespace), configMapName);
// no exception is thrown for unparseable content
}
@@ -139,7 +139,7 @@ public class ConfigMapsTest {
.addToData("application.yaml", "somevalue").build())
.once();
- new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace), configMapName);
+ new Fabric8ConfigMapPropertySource(this.server.getClient().inNamespace(namespace), configMapName);
// no exception is thrown for unparseable content
}
@@ -155,8 +155,8 @@ public class ConfigMapsTest {
.addToData("adhoc.properties", readResourceFile("adhoc.properties")).build())
.once();
- ConfigMapPropertySource cmps = new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace),
- configMapName);
+ Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(
+ this.server.getClient().inNamespace(namespace), configMapName);
// application.properties should be read correctly
assertThat(cmps.getProperty("dummy.property.string1")).isEqualTo("a");
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsTests.java
similarity index 96%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsTests.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsTests.java
index dbdbb2eb..5e07dfa8 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsTests.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import java.util.HashMap;
@@ -31,7 +31,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.kubernetes.config.example.App;
+import org.springframework.cloud.kubernetes.fabric8.config.example.App;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithActiveProfilesNameTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithActiveProfilesNameTests.java
similarity index 94%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithActiveProfilesNameTests.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithActiveProfilesNameTests.java
index 6d57e29a..aa9771b3 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithActiveProfilesNameTests.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithActiveProfilesNameTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import java.util.HashMap;
@@ -30,13 +30,13 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.kubernetes.config.example.App;
+import org.springframework.cloud.kubernetes.fabric8.config.example.App;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
-import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.readResourceFile;
+import static org.springframework.cloud.kubernetes.fabric8.config.ConfigMapTestUtil.readResourceFile;
/**
* @author Ali Shahbour
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfileExpressionTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithProfileExpressionTests.java
similarity index 91%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfileExpressionTests.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithProfileExpressionTests.java
index ebe1be2e..a2fefb6c 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfileExpressionTests.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithProfileExpressionTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import java.util.HashMap;
@@ -30,13 +30,11 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.kubernetes.config.example.App;
+import org.springframework.cloud.kubernetes.fabric8.config.example.App;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
-import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.readResourceFile;
-
/**
* Tests reading property from YAML document specified by profile expression.
*/
@@ -68,7 +66,7 @@ public class ConfigMapsWithProfileExpressionTests {
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
HashMap data = new HashMap<>();
- data.put("application.yml", readResourceFile("application-with-profiles.yaml"));
+ data.put("application.yml", ConfigMapTestUtil.readResourceFile("application-with-profiles.yaml"));
server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME)
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata()
.addToData(data).build())
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfilesNoActiveProfileTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithProfilesNoActiveProfileTests.java
similarity index 93%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfilesNoActiveProfileTests.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithProfilesNoActiveProfileTests.java
index a0082bc2..ee46439a 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfilesNoActiveProfileTests.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithProfilesNoActiveProfileTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import java.util.HashMap;
@@ -30,11 +30,11 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.kubernetes.config.example.App;
+import org.springframework.cloud.kubernetes.fabric8.config.example.App;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
-import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.readResourceFile;
+import static org.springframework.cloud.kubernetes.fabric8.config.ConfigMapTestUtil.readResourceFile;
/**
* @author Charles Moulliard
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfilesTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithProfilesTests.java
similarity index 92%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfilesTests.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithProfilesTests.java
index fe26523f..8be8d701 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfilesTests.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithProfilesTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import java.util.HashMap;
@@ -30,13 +30,11 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.kubernetes.config.example.App;
+import org.springframework.cloud.kubernetes.fabric8.config.example.App;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
-import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.readResourceFile;
-
/**
* @author Charles Moulliard
*/
@@ -73,7 +71,7 @@ public class ConfigMapsWithProfilesTests {
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
HashMap data = new HashMap<>();
- data.put("application.yml", readResourceFile("application-with-profiles.yaml"));
+ data.put("application.yml", ConfigMapTestUtil.readResourceFile("application-with-profiles.yaml"));
server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME)
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata()
.addToData(data).build())
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithoutProfilesTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithoutProfilesTests.java
similarity index 91%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithoutProfilesTests.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithoutProfilesTests.java
index 2f0bc98c..fe384179 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithoutProfilesTests.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapsWithoutProfilesTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import java.util.HashMap;
@@ -30,13 +30,11 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.kubernetes.config.example.App;
+import org.springframework.cloud.kubernetes.fabric8.config.example.App;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
-import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.readResourceFile;
-
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = {
"spring.application.name=configmap-without-profile-example", "spring.cloud.kubernetes.reload.enabled=false" })
@@ -67,7 +65,7 @@ public class ConfigMapsWithoutProfilesTests {
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
HashMap data = new HashMap<>();
- data.put("application.yml", readResourceFile("application-without-profiles.yaml"));
+ data.put("application.yml", ConfigMapTestUtil.readResourceFile("application-without-profiles.yaml"));
server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME)
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata()
.addToData(data).build())
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/CoreTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/CoreTest.java
similarity index 98%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/CoreTest.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/CoreTest.java
index e94d87ed..b0aae403 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/CoreTest.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/CoreTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import java.util.HashMap;
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/SecretsPropertySourceTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySourceTest.java
similarity index 92%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/SecretsPropertySourceTest.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySourceTest.java
index 9e00777b..da7bf7ba 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/SecretsPropertySourceTest.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySourceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import java.util.Base64;
@@ -30,7 +30,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.kubernetes.config.example.App;
+import org.springframework.cloud.kubernetes.fabric8.config.example.App;
import org.springframework.core.env.Environment;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
@@ -41,7 +41,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class)
@TestPropertySource("classpath:/application-secrets.properties")
-public class SecretsPropertySourceTest {
+public class Fabric8SecretsPropertySourceTest {
private static final String NAMESPACE = "test";
@@ -51,7 +51,7 @@ public class SecretsPropertySourceTest {
public static KubernetesServer server = new KubernetesServer(false, true);
@Autowired
- private SecretsPropertySourceLocator propertySourceLocator;
+ private Fabric8SecretsPropertySourceLocator propertySourceLocator;
@Autowired
private Environment environment;
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/HealthIndicatorTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/HealthIndicatorTest.java
similarity index 95%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/HealthIndicatorTest.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/HealthIndicatorTest.java
index 6384df25..25e70e87 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/HealthIndicatorTest.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/HealthIndicatorTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.KubernetesClient;
@@ -27,7 +27,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.kubernetes.config.example.App;
+import org.springframework.cloud.kubernetes.fabric8.config.example.App;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/KubernetesConfigConfigurationTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/KubernetesConfigConfigurationTest.java
similarity index 96%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/KubernetesConfigConfigurationTest.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/KubernetesConfigConfigurationTest.java
index a58f6851..b3013afb 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/KubernetesConfigConfigurationTest.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/KubernetesConfigConfigurationTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.junit.After;
@@ -23,7 +23,7 @@ import org.junit.Test;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
-import org.springframework.cloud.kubernetes.config.reload.ConfigReloadAutoConfiguration;
+import org.springframework.cloud.kubernetes.fabric8.config.reload.ConfigReloadAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -124,7 +124,7 @@ public class KubernetesConfigConfigurationTest {
private void setup(String... env) {
this.context = new SpringApplicationBuilder(PropertyPlaceholderAutoConfiguration.class,
- KubernetesClientTestConfiguration.class, BootstrapConfiguration.class,
+ KubernetesClientTestConfiguration.class, Fabric8BootstrapConfiguration.class,
ConfigReloadAutoConfiguration.class, RefreshAutoConfiguration.class)
.web(org.springframework.boot.WebApplicationType.NONE).properties(env).run();
}
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MissingActuatorTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/MissingActuatorTest.java
similarity index 97%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MissingActuatorTest.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/MissingActuatorTest.java
index e0c6c606..48cbbbdf 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MissingActuatorTest.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/MissingActuatorTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import org.junit.Rule;
import org.junit.Test;
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MultipleConfigMapsTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/MultipleConfigMapsTests.java
similarity index 96%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MultipleConfigMapsTests.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/MultipleConfigMapsTests.java
index 9e452242..a5afa5e0 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MultipleConfigMapsTests.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/MultipleConfigMapsTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import java.util.HashMap;
import java.util.Map;
@@ -31,7 +31,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.kubernetes.config.example2.ExampleApp;
+import org.springframework.cloud.kubernetes.fabric8.config.example2.ExampleApp;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MultipleSecretsTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/MultipleSecretsTests.java
similarity index 96%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MultipleSecretsTests.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/MultipleSecretsTests.java
index 676129cc..0ac5fcc0 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MultipleSecretsTests.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/MultipleSecretsTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import java.util.Base64;
import java.util.HashMap;
@@ -33,7 +33,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.kubernetes.config.example3.MultiSecretsApp;
+import org.springframework.cloud.kubernetes.fabric8.config.example3.MultiSecretsApp;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/TestApplication.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/TestApplication.java
similarity index 93%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/TestApplication.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/TestApplication.java
index 4b1a7675..1ad91638 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/TestApplication.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/TestApplication.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config;
+package org.springframework.cloud.kubernetes.fabric8.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/App.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example/App.java
similarity index 93%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/App.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example/App.java
index abf9e3b8..f617945b 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/App.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example/App.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.example;
+package org.springframework.cloud.kubernetes.fabric8.config.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/GreetingController.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example/GreetingController.java
similarity index 96%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/GreetingController.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example/GreetingController.java
index ca71d3a2..9aab422d 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/GreetingController.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example/GreetingController.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.example;
+package org.springframework.cloud.kubernetes.fabric8.config.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/GreetingProperties.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example/GreetingProperties.java
similarity index 95%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/GreetingProperties.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example/GreetingProperties.java
index 0c47e8dc..cb5dbe94 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/GreetingProperties.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example/GreetingProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.example;
+package org.springframework.cloud.kubernetes.fabric8.config.example;
import org.springframework.boot.context.properties.ConfigurationProperties;
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/ResponseMessage.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example/ResponseMessage.java
similarity index 92%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/ResponseMessage.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example/ResponseMessage.java
index 60b8b196..6f3e210c 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/ResponseMessage.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example/ResponseMessage.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.example;
+package org.springframework.cloud.kubernetes.fabric8.config.example;
/**
* @author Charles Moulliard
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example2/ExampleApp.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example2/ExampleApp.java
similarity index 91%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example2/ExampleApp.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example2/ExampleApp.java
index b8932fba..8ebc7338 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example2/ExampleApp.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example2/ExampleApp.java
@@ -14,11 +14,12 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.example2;
+package org.springframework.cloud.kubernetes.fabric8.config.example2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.kubernetes.fabric8.config.example.App;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -27,7 +28,7 @@ import org.springframework.web.bind.annotation.RestController;
public class ExampleApp {
public static void main(String[] args) {
- SpringApplication.run(org.springframework.cloud.kubernetes.config.example.App.class, args);
+ SpringApplication.run(App.class, args);
}
@RestController
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example2/ExampleAppProps.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example2/ExampleAppProps.java
similarity index 95%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example2/ExampleAppProps.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example2/ExampleAppProps.java
index ed949277..b5179c88 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example2/ExampleAppProps.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example2/ExampleAppProps.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.example2;
+package org.springframework.cloud.kubernetes.fabric8.config.example2;
import org.springframework.boot.context.properties.ConfigurationProperties;
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example3/MultiSecretsApp.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example3/MultiSecretsApp.java
similarity index 96%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example3/MultiSecretsApp.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example3/MultiSecretsApp.java
index 52b88473..015e762e 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example3/MultiSecretsApp.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example3/MultiSecretsApp.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.example3;
+package org.springframework.cloud.kubernetes.fabric8.config.example3;
/**
* @author Haytham Mohamed
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example3/MultiSecretsProperties.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example3/MultiSecretsProperties.java
similarity index 94%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example3/MultiSecretsProperties.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example3/MultiSecretsProperties.java
index 72ee8750..dccf36b2 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example3/MultiSecretsProperties.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/example3/MultiSecretsProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.example3;
+package org.springframework.cloud.kubernetes.fabric8.config.example3;
import org.springframework.boot.context.properties.ConfigurationProperties;
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationChangeDetectorTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload/ConfigurationChangeDetectorTest.java
similarity index 89%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationChangeDetectorTest.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload/ConfigurationChangeDetectorTest.java
index a68d2f4e..5f59b07b 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationChangeDetectorTest.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload/ConfigurationChangeDetectorTest.java
@@ -14,17 +14,19 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.reload;
+package org.springframework.cloud.kubernetes.fabric8.config.reload;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import io.fabric8.kubernetes.client.KubernetesClient;
import org.junit.Assert;
import org.junit.Test;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationChangeDetector;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
@@ -33,7 +35,7 @@ import org.springframework.core.env.MapPropertySource;
*/
public class ConfigurationChangeDetectorTest {
- private final ConfigurationChangeDetectorStub stub = new ConfigurationChangeDetectorStub(null, null, null, null);
+ private final ConfigurationChangeDetectorStub stub = new ConfigurationChangeDetectorStub(null, null, null);
@Test
public void testChangedTwoNulls() {
@@ -122,8 +124,8 @@ public class ConfigurationChangeDetectorTest {
private static final class ConfigurationChangeDetectorStub extends ConfigurationChangeDetector {
private ConfigurationChangeDetectorStub(ConfigurableEnvironment environment, ConfigReloadProperties properties,
- KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy) {
- super(environment, properties, kubernetesClient, strategy);
+ ConfigurationUpdateStrategy strategy) {
+ super(environment, properties, strategy);
}
}
diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetectorTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload/EventBasedConfigurationChangeDetectorTests.java
similarity index 76%
rename from spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetectorTests.java
rename to spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload/EventBasedConfigurationChangeDetectorTests.java
index 2e96c23a..a8a3deac 100644
--- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetectorTests.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload/EventBasedConfigurationChangeDetectorTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.kubernetes.config.reload;
+package org.springframework.cloud.kubernetes.fabric8.config.reload;
import java.util.HashMap;
import java.util.List;
@@ -29,8 +29,10 @@ import io.fabric8.kubernetes.client.dsl.Resource;
import org.junit.Test;
import org.springframework.cloud.bootstrap.config.BootstrapPropertySource;
-import org.springframework.cloud.kubernetes.config.ConfigMapPropertySource;
-import org.springframework.cloud.kubernetes.config.ConfigMapPropertySourceLocator;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties;
+import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySource;
+import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator;
import org.springframework.mock.env.MockEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
@@ -59,14 +61,16 @@ public class EventBasedConfigurationChangeDetectorTests {
when(mixedOperation.withName(eq("myconfigmap"))).thenReturn(resource);
when(k8sClient.configMaps()).thenReturn(mixedOperation);
- ConfigMapPropertySource configMapPropertySource = new ConfigMapPropertySource(k8sClient, "myconfigmap");
- env.getPropertySources().addFirst(new BootstrapPropertySource(configMapPropertySource));
+ Fabric8ConfigMapPropertySource fabric8ConfigMapPropertySource = new Fabric8ConfigMapPropertySource(k8sClient,
+ "myconfigmap");
+ env.getPropertySources().addFirst(new BootstrapPropertySource(fabric8ConfigMapPropertySource));
ConfigurationUpdateStrategy configurationUpdateStrategy = mock(ConfigurationUpdateStrategy.class);
- ConfigMapPropertySourceLocator configMapLocator = mock(ConfigMapPropertySourceLocator.class);
+ Fabric8ConfigMapPropertySourceLocator configMapLocator = mock(Fabric8ConfigMapPropertySourceLocator.class);
EventBasedConfigMapChangeDetector detector = new EventBasedConfigMapChangeDetector(env, configReloadProperties,
k8sClient, configurationUpdateStrategy, configMapLocator);
- List sources = detector.findPropertySources(ConfigMapPropertySource.class);
+ List sources = detector
+ .findPropertySources(Fabric8ConfigMapPropertySource.class);
assertThat(sources.size()).isEqualTo(1);
assertThat(sources.get(0).getProperty("foo")).isEqualTo("bar");
}
diff --git a/spring-cloud-kubernetes-config/src/test/resources/adhoc.properties b/spring-cloud-kubernetes-fabric8-config/src/test/resources/adhoc.properties
similarity index 100%
rename from spring-cloud-kubernetes-config/src/test/resources/adhoc.properties
rename to spring-cloud-kubernetes-fabric8-config/src/test/resources/adhoc.properties
diff --git a/spring-cloud-kubernetes-config/src/test/resources/adhoc.yml b/spring-cloud-kubernetes-fabric8-config/src/test/resources/adhoc.yml
similarity index 100%
rename from spring-cloud-kubernetes-config/src/test/resources/adhoc.yml
rename to spring-cloud-kubernetes-fabric8-config/src/test/resources/adhoc.yml
diff --git a/spring-cloud-kubernetes-config/src/test/resources/application-path.yaml b/spring-cloud-kubernetes-fabric8-config/src/test/resources/application-path.yaml
similarity index 100%
rename from spring-cloud-kubernetes-config/src/test/resources/application-path.yaml
rename to spring-cloud-kubernetes-fabric8-config/src/test/resources/application-path.yaml
diff --git a/spring-cloud-kubernetes-config/src/test/resources/application-secrets.properties b/spring-cloud-kubernetes-fabric8-config/src/test/resources/application-secrets.properties
similarity index 64%
rename from spring-cloud-kubernetes-config/src/test/resources/application-secrets.properties
rename to spring-cloud-kubernetes-fabric8-config/src/test/resources/application-secrets.properties
index 93827ece..62735073 100644
--- a/spring-cloud-kubernetes-config/src/test/resources/application-secrets.properties
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/resources/application-secrets.properties
@@ -1,5 +1,5 @@
spring.application.name=configmap-example
spring.cloud.kubernetes.reload.enabled=false
-logging.level.org.springframework.cloud.kubernetes.config.SecretsPropertySource=DEBUG
+logging.level.org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySource=DEBUG
spring.cloud.kubernetes.secrets.labels.foo=bar
spring.cloud.kubernetes.secrets.enableApi=true
diff --git a/spring-cloud-kubernetes-config/src/test/resources/application-with-active-profiles-name.yaml b/spring-cloud-kubernetes-fabric8-config/src/test/resources/application-with-active-profiles-name.yaml
similarity index 100%
rename from spring-cloud-kubernetes-config/src/test/resources/application-with-active-profiles-name.yaml
rename to spring-cloud-kubernetes-fabric8-config/src/test/resources/application-with-active-profiles-name.yaml
diff --git a/spring-cloud-kubernetes-config/src/test/resources/application-with-profiles.yaml b/spring-cloud-kubernetes-fabric8-config/src/test/resources/application-with-profiles.yaml
similarity index 100%
rename from spring-cloud-kubernetes-config/src/test/resources/application-with-profiles.yaml
rename to spring-cloud-kubernetes-fabric8-config/src/test/resources/application-with-profiles.yaml
diff --git a/spring-cloud-kubernetes-config/src/test/resources/application-without-profiles.yaml b/spring-cloud-kubernetes-fabric8-config/src/test/resources/application-without-profiles.yaml
similarity index 100%
rename from spring-cloud-kubernetes-config/src/test/resources/application-without-profiles.yaml
rename to spring-cloud-kubernetes-fabric8-config/src/test/resources/application-without-profiles.yaml
diff --git a/spring-cloud-kubernetes-config/src/test/resources/application.properties b/spring-cloud-kubernetes-fabric8-config/src/test/resources/application.properties
similarity index 100%
rename from spring-cloud-kubernetes-config/src/test/resources/application.properties
rename to spring-cloud-kubernetes-fabric8-config/src/test/resources/application.properties
diff --git a/spring-cloud-kubernetes-config/src/test/resources/application.yaml b/spring-cloud-kubernetes-fabric8-config/src/test/resources/application.yaml
similarity index 100%
rename from spring-cloud-kubernetes-config/src/test/resources/application.yaml
rename to spring-cloud-kubernetes-fabric8-config/src/test/resources/application.yaml
diff --git a/spring-cloud-kubernetes-config/src/test/resources/logback-test.xml b/spring-cloud-kubernetes-fabric8-config/src/test/resources/logback-test.xml
similarity index 100%
rename from spring-cloud-kubernetes-config/src/test/resources/logback-test.xml
rename to spring-cloud-kubernetes-fabric8-config/src/test/resources/logback-test.xml
diff --git a/spring-cloud-kubernetes-config/src/test/resources/multiple-secrets.yml b/spring-cloud-kubernetes-fabric8-config/src/test/resources/multiple-secrets.yml
similarity index 100%
rename from spring-cloud-kubernetes-config/src/test/resources/multiple-secrets.yml
rename to spring-cloud-kubernetes-fabric8-config/src/test/resources/multiple-secrets.yml
diff --git a/spring-cloud-kubernetes-config/src/test/resources/multiplecms.yml b/spring-cloud-kubernetes-fabric8-config/src/test/resources/multiplecms.yml
similarity index 100%
rename from spring-cloud-kubernetes-config/src/test/resources/multiplecms.yml
rename to spring-cloud-kubernetes-fabric8-config/src/test/resources/multiplecms.yml
diff --git a/spring-cloud-kubernetes-integration-tests/run.sh b/spring-cloud-kubernetes-integration-tests/run.sh
index b4061eb1..e2ca839b 100755
--- a/spring-cloud-kubernetes-integration-tests/run.sh
+++ b/spring-cloud-kubernetes-integration-tests/run.sh
@@ -145,6 +145,9 @@ main() {
# TODO: invoke your tests here
cd spring-cloud-kubernetes-core-k8s-client-it
../../mvnw clean install -P it
+ cd ../
+ cd spring-cloud-kubernetes-client-config-it
+ ../../mvnw clean install -P it
cd ../
cd spring-cloud-kubernetes-configuration-watcher-it
../../mvnw clean install -P it
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/configmap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/configmap.yaml
new file mode 100644
index 00000000..6a4e128c
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/configmap.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+data:
+ application.yaml: |-
+ my:
+ config:
+ myProperty: from-config-map
+kind: ConfigMap
+metadata:
+ name: spring-cloud-kubernetes-client-config-it
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/deployment-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/deployment-it.yaml
new file mode 100644
index 00000000..21f1aa11
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/deployment-it.yaml
@@ -0,0 +1,29 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ creationTimestamp: null
+ labels:
+ app: spring-cloud-kubernetes-client-config-it
+ name: spring-cloud-kubernetes-client-config-it-deployment
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: spring-cloud-kubernetes-client-config-it
+ strategy: {}
+ template:
+ metadata:
+ creationTimestamp: null
+ labels:
+ app: spring-cloud-kubernetes-client-config-it
+ spec:
+ serviceAccountName: spring-cloud-kubernetes-serviceaccount
+ containers:
+ - image: springcloud/spring-cloud-kubernetes-client-config-it:2.0.0-SNAPSHOT
+ imagePullPolicy: IfNotPresent
+ name: spring-cloud-kubernetes-client-config-it
+ resources: {}
+ env:
+ - name: SPRING_PROFILES_ACTIVE
+ value: kubernetes
+status: {}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/deployment-polling-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/deployment-polling-it.yaml
new file mode 100644
index 00000000..6cefe2ab
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/deployment-polling-it.yaml
@@ -0,0 +1,31 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ creationTimestamp: null
+ labels:
+ app: spring-cloud-kubernetes-client-config-it
+ name: spring-cloud-kubernetes-client-config-it-deployment
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: spring-cloud-kubernetes-client-config-it
+ strategy: {}
+ template:
+ metadata:
+ creationTimestamp: null
+ labels:
+ app: spring-cloud-kubernetes-client-config-it
+ spec:
+ serviceAccountName: spring-cloud-kubernetes-serviceaccount
+ containers:
+ - image: springcloud/spring-cloud-kubernetes-client-config-it:2.0.0-SNAPSHOT
+ imagePullPolicy: IfNotPresent
+ name: spring-cloud-kubernetes-client-config-it
+ resources: {}
+ env:
+ - name: SPRING_PROFILES_ACTIVE
+ value: kubernetes
+ - name: SPRING_CLOUD_KUBERNETES_RELOAD_MODE
+ value: polling
+status: {}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/secret.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/secret.yaml
new file mode 100644
index 00000000..9b68d973
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/secret.yaml
@@ -0,0 +1,7 @@
+apiVersion: v1
+data:
+ my.config.mySecret: cDQ1NXcwcmQ=
+kind: Secret
+metadata:
+ name: spring-cloud-kubernetes-client-config-it
+type: Opaque
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/service-it.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/service-it.yaml
new file mode 100644
index 00000000..06324a87
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/k8s/service-it.yaml
@@ -0,0 +1,18 @@
+apiVersion: v1
+kind: Service
+metadata:
+ creationTimestamp: null
+ labels:
+ app: spring-cloud-kubernetes-client-config-it
+ name: spring-cloud-kubernetes-client-config-it
+spec:
+ ports:
+ - name: 80-8080
+ port: 80
+ protocol: TCP
+ targetPort: 8080
+ selector:
+ app: spring-cloud-kubernetes-client-config-it
+ type: ClusterIP
+status:
+ loadBalancer: {}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/pom.xml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/pom.xml
new file mode 100644
index 00000000..3d6db651
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/pom.xml
@@ -0,0 +1,90 @@
+
+
+
+ org.springframework.cloud
+ spring-cloud-kubernetes-integration-tests
+ 2.0.0-SNAPSHOT
+
+ 4.0.0
+
+ spring-cloud-kubernetes-client-config-it
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-kubernetes-client-all
+
+
+ org.springframework.cloud
+ spring-cloud-kubernetes-test-support
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ io.kubernetes
+ client-java
+
+
+ io.kubernetes
+ client-java-extended
+
+
+ com.github.docker-java
+ docker-java-core
+ test
+
+
+ com.github.docker-java
+ docker-java-transport-httpclient5
+ test
+
+
+
+
+
+
+ imagename
+
+
+ !env.IMAGE
+
+
+
+ springcloud/${project.artifactId}:${project.version}
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ ${env.IMAGE}
+
+ build-image
+
+
+
+ package
+
+ build-image
+
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/skaffold.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/skaffold.yaml
new file mode 100644
index 00000000..27f72f02
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/skaffold.yaml
@@ -0,0 +1,33 @@
+apiVersion: skaffold/v2alpha3
+kind: Config
+metadata:
+ name: spring-cloud-kubernetes-client-config-it
+build:
+ artifacts:
+ - image: springcloud/spring-cloud-kubernetes-client-config-it
+ custom:
+ buildCommand: "../../mvnw clean install"
+ dependencies:
+ paths:
+ - src
+ - pom.xml
+
+profiles:
+ - name: polling
+ deploy:
+ kubectl:
+ manifests:
+ - k8s/deployment-polling-it.yaml
+ - k8s/service-it.yaml
+ - k8s/configmap.yaml
+ - k8s/secret.yaml
+ - ../permissions.yaml
+
+deploy:
+ kubectl:
+ manifests:
+ - k8s/deployment-it.yaml
+ - k8s/service-it.yaml
+ - k8s/configmap.yaml
+ - k8s/secret.yaml
+ - ../permissions.yaml
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/java/org/springframework/cloud/kubernetes/client/config/it/KubernetesConfigClientApplicationIt.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/java/org/springframework/cloud/kubernetes/client/config/it/KubernetesConfigClientApplicationIt.java
new file mode 100644
index 00000000..792a3c3a
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/java/org/springframework/cloud/kubernetes/client/config/it/KubernetesConfigClientApplicationIt.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2013-2020 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.config.it;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Ryan Baxter
+ */
+@SpringBootApplication
+@RestController
+public class KubernetesConfigClientApplicationIt {
+
+ @Autowired
+ private MyConfigurationProperties configurationProperties;
+
+ @GetMapping("/myProperty")
+ public String myProperty() {
+ return configurationProperties.getMyProperty();
+ }
+
+ @GetMapping("/mySecret")
+ public String mySecret() {
+ return configurationProperties.getMySecret();
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(KubernetesConfigClientApplicationIt.class, args);
+ }
+
+ @Configuration
+ @EnableConfigurationProperties(MyConfigurationProperties.class)
+ class MyConfig {
+
+ }
+
+}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/java/org/springframework/cloud/kubernetes/client/config/it/MyConfigurationProperties.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/java/org/springframework/cloud/kubernetes/client/config/it/MyConfigurationProperties.java
new file mode 100644
index 00000000..ac43f4a2
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/java/org/springframework/cloud/kubernetes/client/config/it/MyConfigurationProperties.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013-2020 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.config.it;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * @author Ryan Baxter
+ */
+@ConfigurationProperties("my.config")
+public class MyConfigurationProperties {
+
+ private String myProperty = "default-value";
+
+ private String mySecret = "default-secret-value";
+
+ public MyConfigurationProperties() {
+ }
+
+ public String getMyProperty() {
+ return myProperty;
+ }
+
+ public void setMyProperty(String myProperty) {
+ this.myProperty = myProperty;
+ }
+
+ public String getMySecret() {
+ return mySecret;
+ }
+
+ public void setMySecret(String mySecret) {
+ this.mySecret = mySecret;
+ }
+
+}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/application.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/application.yaml
new file mode 100644
index 00000000..e81b66d5
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/application.yaml
@@ -0,0 +1,11 @@
+management:
+ endpoints:
+ web:
+ exposure:
+ include: "*"
+#logging:
+# level:
+# org:
+# springframework:
+# cloud:
+# kubernetes: DEBUG
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/bootstrap-kubernetes.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/bootstrap-kubernetes.yaml
new file mode 100644
index 00000000..723f28c9
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/bootstrap-kubernetes.yaml
@@ -0,0 +1,15 @@
+spring:
+ cloud:
+ kubernetes:
+ enabled: true
+ secrets:
+ enable-api: true
+ reload:
+ enabled: true
+ monitoring-secrets: true
+logging:
+ level:
+ org:
+ springframework:
+ cloud:
+ kubernetes: DEBUG
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/bootstrap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/bootstrap.yaml
new file mode 100644
index 00000000..d4075ec0
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/main/resources/bootstrap.yaml
@@ -0,0 +1,7 @@
+spring:
+ application:
+ name: spring-cloud-kubernetes-client-config-it
+ cloud:
+ kubernetes:
+ enabled: false
+
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/java/org/springframework/cloud/kubernetes/client/config/it/ConfigMapAndSecretIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/java/org/springframework/cloud/kubernetes/client/config/it/ConfigMapAndSecretIT.java
new file mode 100644
index 00000000..6f73abff
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/java/org/springframework/cloud/kubernetes/client/config/it/ConfigMapAndSecretIT.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2013-2020 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.config.it;
+
+import java.io.IOException;
+import java.time.Duration;
+import java.util.Map;
+
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.core.DefaultDockerClientConfig;
+import com.github.dockerjava.core.DockerClientConfig;
+import com.github.dockerjava.core.DockerClientImpl;
+import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
+import com.github.dockerjava.transport.DockerHttpClient;
+import io.kubernetes.client.openapi.ApiClient;
+import io.kubernetes.client.openapi.Configuration;
+import io.kubernetes.client.openapi.apis.AppsV1Api;
+import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.apis.NetworkingV1beta1Api;
+import io.kubernetes.client.openapi.models.NetworkingV1beta1Ingress;
+import io.kubernetes.client.openapi.models.V1ConfigMap;
+import io.kubernetes.client.openapi.models.V1Deployment;
+import io.kubernetes.client.openapi.models.V1Secret;
+import io.kubernetes.client.openapi.models.V1Service;
+import io.kubernetes.client.util.Config;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.After;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.web.client.ResponseErrorHandler;
+import org.springframework.web.client.RestTemplate;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Awaitility.await;
+
+/**
+ * @author Ryan Baxter
+ */
+public class ConfigMapAndSecretIT {
+
+ private static final Log LOG = LogFactory.getLog(ConfigMapAndSecretIT.class);
+
+ private static final String KIND_REPO_HOST_PORT = "localhost:5000";
+
+ private static final String KIND_REPO_URL = "http://" + KIND_REPO_HOST_PORT;
+
+ private static final String IMAGE = "spring-cloud-kubernetes-client-config-it";
+
+ private static final String IMAGE_TAG = "2.0.0-SNAPSHOT";
+
+ private static final String LOCAL_REPO = "docker.io/springcloud";
+
+ private static final String LOCAL_IMAGE = LOCAL_REPO + "/" + IMAGE + ":" + IMAGE_TAG;
+
+ private static final String KIND_IMAGE = KIND_REPO_HOST_PORT + "/" + IMAGE;
+
+ private static final String KIND_IMAGE_WITH_TAG = KIND_IMAGE + ":" + IMAGE_TAG;
+
+ private static final String SPRING_CLOUD_CLIENT_CONFIG_IT_DEPLOYMENT_NAME = "spring-cloud-kubernetes-client-config-it-deployment";
+
+ private static final String K8S_CONFIG_CLIENT_IT_NAME = "spring-cloud-kubernetes-client-config-it-deployment";
+
+ private static final String K8S_CONFIG_CLIENT_IT_SERVICE_NAME = "spring-cloud-kubernetes-client-config-it";
+
+ private static final String NAMESPACE = "default";
+
+ private static final String MYPROPERTY_URL = "http://localhost:80/client-config-it/myProperty";
+
+ private static final String MYSECRET_URL = "http://localhost:80/client-config-it/mySecret";
+
+ private static final String APP_NAME = "spring-cloud-kubernetes-client-config-it";
+
+ private static ApiClient client;
+
+ private static CoreV1Api api;
+
+ private static AppsV1Api appsApi;
+
+ private static NetworkingV1beta1Api networkingApi;
+
+ private static K8SUtils k8SUtils;
+
+ @BeforeClass
+ public static void setup() throws Exception {
+ client = Config.defaultClient();
+ // client.setDebugging(true);
+ Configuration.setDefaultApiClient(client);
+ api = new CoreV1Api();
+ appsApi = new AppsV1Api();
+ networkingApi = new NetworkingV1beta1Api();
+ k8SUtils = new K8SUtils(api, appsApi);
+
+ DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
+ .withRegistryUrl(KIND_REPO_URL).build();
+ DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder().dockerHost(config.getDockerHost())
+ .sslConfig(config.getSSLConfig()).build();
+
+ DockerClient dockerClient = DockerClientImpl.getInstance(config, httpClient);
+ dockerClient.tagImageCmd(LOCAL_IMAGE, KIND_IMAGE, IMAGE_TAG).exec();
+ dockerClient.pushImageCmd(KIND_IMAGE_WITH_TAG).start();
+ }
+
+ @After
+ public void after() throws Exception {
+ appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
+ "metadata.name=" + K8S_CONFIG_CLIENT_IT_NAME, null, null, null, null, null, null, null, null);
+ api.deleteNamespacedService(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, NAMESPACE, null, null, null, null, null, null);
+ networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null);
+ api.deleteNamespacedConfigMap(APP_NAME, NAMESPACE, null, null, null, null, null, null);
+ api.deleteNamespacedSecret(APP_NAME, NAMESPACE, null, null, null, null, null, null);
+ }
+
+ public void testConfigMapAndSecretRefresh() throws Exception {
+
+ RestTemplate rest = new RestTemplateBuilder().build();
+ rest.setErrorHandler(new ResponseErrorHandler() {
+ @Override
+ public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
+ LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
+ if (clientHttpResponse.getRawStatusCode() == 503) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
+
+ }
+ });
+
+ // Sometimes the NGINX ingress takes a bit to catch up and realize the service is
+ // available and we get a 503, we just need to wait a bit
+ await().timeout(Duration.ofSeconds(60))
+ .until(() -> rest.getForEntity(MYPROPERTY_URL, String.class).getStatusCode().is2xxSuccessful());
+
+ String myProperty = rest.getForObject(MYPROPERTY_URL, String.class);
+ assertThat(myProperty).isEqualTo("from-config-map");
+ String mySecret = rest.getForObject(MYSECRET_URL, String.class);
+ assertThat(mySecret).isEqualTo("p455w0rd");
+
+ V1ConfigMap configMap = getConfigK8sClientItConfigMap();
+ Map data = configMap.getData();
+ data.replace("application.yaml", data.get("application.yaml").replace("from-config-map", "from-unit-test"));
+ configMap.data(data);
+ api.replaceNamespacedConfigMap(APP_NAME, NAMESPACE, configMap, null, null, null);
+ await().timeout(Duration.ofSeconds(15))
+ .until(() -> rest.getForObject(MYPROPERTY_URL, String.class).equals("from-unit-test"));
+ myProperty = rest.getForObject(MYPROPERTY_URL, String.class);
+ assertThat(myProperty).isEqualTo("from-unit-test");
+
+ V1Secret secret = getConfigK8sClientItCSecret();
+ Map secretData = secret.getData();
+ secretData.replace("my.config.mySecret", "p455w1rd".getBytes());
+ secret.setData(secretData);
+ api.replaceNamespacedSecret(APP_NAME, NAMESPACE, secret, null, null, null);
+ await().timeout(Duration.ofSeconds(15))
+ .until(() -> rest.getForObject(MYSECRET_URL, String.class).equals("p455w1rd"));
+ mySecret = rest.getForObject(MYSECRET_URL, String.class);
+ assertThat(mySecret).isEqualTo("p455w1rd");
+
+ }
+
+ @Test
+ public void testConfigMapAndSecretWatchRefresh() throws Exception {
+ deployConfigK8sClientIt();
+
+ // Check to make sure the controller deployment is ready
+ k8SUtils.waitForDeployment(SPRING_CLOUD_CLIENT_CONFIG_IT_DEPLOYMENT_NAME, NAMESPACE);
+ testConfigMapAndSecretRefresh();
+ }
+
+ @Test
+ public void testConfigMapAndSecretPollingRefresh() throws Exception {
+ deployConfigK8sClientPollingIt();
+
+ // Check to make sure the controller deployment is ready
+ k8SUtils.waitForDeployment(SPRING_CLOUD_CLIENT_CONFIG_IT_DEPLOYMENT_NAME, NAMESPACE);
+ testConfigMapAndSecretRefresh();
+ }
+
+ private static void deployConfigK8sClientIt() throws Exception {
+ k8SUtils.waitForDeploymentToBeDeleted(K8S_CONFIG_CLIENT_IT_NAME, NAMESPACE);
+ api.createNamespacedSecret(NAMESPACE, getConfigK8sClientItCSecret(), null, null, null);
+ api.createNamespacedConfigMap(NAMESPACE, getConfigK8sClientItConfigMap(), null, null, null);
+ appsApi.createNamespacedDeployment(NAMESPACE, getConfigK8sClientItDeployment(), null, null, null);
+ api.createNamespacedService(NAMESPACE, getConfigK8sClientItService(), null, null, null);
+ networkingApi.createNamespacedIngress(NAMESPACE, getConfigK8sClientItIngress(), null, null, null);
+ }
+
+ private static void deployConfigK8sClientPollingIt() throws Exception {
+ k8SUtils.waitForDeploymentToBeDeleted(K8S_CONFIG_CLIENT_IT_NAME, NAMESPACE);
+ api.createNamespacedSecret(NAMESPACE, getConfigK8sClientItCSecret(), null, null, null);
+ api.createNamespacedConfigMap(NAMESPACE, getConfigK8sClientItConfigMap(), null, null, null);
+ appsApi.createNamespacedDeployment(NAMESPACE, getConfigK8sClientItPollingDeployment(), null, null, null);
+ api.createNamespacedService(NAMESPACE, getConfigK8sClientItService(), null, null, null);
+ networkingApi.createNamespacedIngress(NAMESPACE, getConfigK8sClientItIngress(), null, null, null);
+ }
+
+ private static V1Deployment getConfigK8sClientItDeployment() throws Exception {
+ V1Deployment deployment = (V1Deployment) k8SUtils
+ .readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-deployment.yaml");
+ return deployment;
+ }
+
+ private static V1Deployment getConfigK8sClientItPollingDeployment() throws Exception {
+ V1Deployment deployment = (V1Deployment) k8SUtils
+ .readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-polling-deployment.yaml");
+ return deployment;
+ }
+
+ private static V1Service getConfigK8sClientItService() throws Exception {
+ V1Service service = (V1Service) k8SUtils
+ .readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-service.yaml");
+ return service;
+ }
+
+ private static NetworkingV1beta1Ingress getConfigK8sClientItIngress() throws Exception {
+ NetworkingV1beta1Ingress ingress = (NetworkingV1beta1Ingress) k8SUtils
+ .readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-ingress.yaml");
+ return ingress;
+ }
+
+ private static V1ConfigMap getConfigK8sClientItConfigMap() throws Exception {
+ V1ConfigMap configmap = (V1ConfigMap) k8SUtils
+ .readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-configmap.yaml");
+ return configmap;
+ }
+
+ private static V1Secret getConfigK8sClientItCSecret() throws Exception {
+ V1Secret secret = (V1Secret) k8SUtils
+ .readYamlFromClasspath("spring-cloud-kubernetes-client-config-it-secret.yaml");
+ return secret;
+ }
+
+}
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-configmap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-configmap.yaml
new file mode 100644
index 00000000..6a4e128c
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-configmap.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+data:
+ application.yaml: |-
+ my:
+ config:
+ myProperty: from-config-map
+kind: ConfigMap
+metadata:
+ name: spring-cloud-kubernetes-client-config-it
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-deployment.yaml
new file mode 100644
index 00000000..7ad29f53
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-deployment.yaml
@@ -0,0 +1,31 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: spring-cloud-kubernetes-client-config-it-deployment
+spec:
+ selector:
+ matchLabels:
+ app: spring-cloud-kubernetes-client-config-it
+ template:
+ metadata:
+ labels:
+ app: spring-cloud-kubernetes-client-config-it
+ spec:
+ serviceAccountName: spring-cloud-kubernetes-serviceaccount
+ containers:
+ - name: spring-cloud-kubernetes-client-config-it
+ image: localhost:5000/spring-cloud-kubernetes-client-config-it:2.0.0-SNAPSHOT
+ imagePullPolicy: IfNotPresent
+ readinessProbe:
+ httpGet:
+ port: 8080
+ path: /actuator/health/readiness
+ livenessProbe:
+ httpGet:
+ port: 8080
+ path: /actuator/health/liveness
+ env:
+ - name: SPRING_PROFILES_ACTIVE
+ value: kubernetes
+ ports:
+ - containerPort: 8080
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-ingress.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-ingress.yaml
new file mode 100644
index 00000000..1cac3593
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-ingress.yaml
@@ -0,0 +1,14 @@
+apiVersion: networking.k8s.io/v1beta1
+kind: Ingress
+metadata:
+ name: it-ingress
+ annotations:
+ nginx.ingress.kubernetes.io/rewrite-target: /$2
+spec:
+ rules:
+ - http:
+ paths:
+ - path: /client-config-it(/|$)(.*)
+ backend:
+ serviceName: spring-cloud-kubernetes-client-config-it
+ servicePort: 8080
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-polling-deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-polling-deployment.yaml
new file mode 100644
index 00000000..f769348e
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-polling-deployment.yaml
@@ -0,0 +1,33 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: spring-cloud-kubernetes-client-config-it-deployment
+spec:
+ selector:
+ matchLabels:
+ app: spring-cloud-kubernetes-client-config-it
+ template:
+ metadata:
+ labels:
+ app: spring-cloud-kubernetes-client-config-it
+ spec:
+ serviceAccountName: spring-cloud-kubernetes-serviceaccount
+ containers:
+ - name: spring-cloud-kubernetes-client-config-it
+ image: localhost:5000/spring-cloud-kubernetes-client-config-it:2.0.0-SNAPSHOT
+ imagePullPolicy: IfNotPresent
+ readinessProbe:
+ httpGet:
+ port: 8080
+ path: /actuator/health/readiness
+ livenessProbe:
+ httpGet:
+ port: 8080
+ path: /actuator/health/liveness
+ env:
+ - name: SPRING_PROFILES_ACTIVE
+ value: kubernetes
+ - name: SPRING_CLOUD_KUBERNETES_RELOAD_MODE
+ value: polling
+ ports:
+ - containerPort: 8080
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-secret.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-secret.yaml
new file mode 100644
index 00000000..9b68d973
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-secret.yaml
@@ -0,0 +1,7 @@
+apiVersion: v1
+data:
+ my.config.mySecret: cDQ1NXcwcmQ=
+kind: Secret
+metadata:
+ name: spring-cloud-kubernetes-client-config-it
+type: Opaque
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-service.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-service.yaml
new file mode 100644
index 00000000..10aaed50
--- /dev/null
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-client-config-it/src/test/resources/spring-cloud-kubernetes-client-config-it-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ app: spring-cloud-kubernetes-client-config-it
+ name: spring-cloud-kubernetes-client-config-it
+spec:
+ ports:
+ - name: http
+ port: 8080
+ targetPort: 8080
+ selector:
+ app: spring-cloud-kubernetes-client-config-it
+ type: ClusterIP
diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/java/org/springframework/cloud/kubernetes/core/k8s/it/ActuatorEndpointIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/java/org/springframework/cloud/kubernetes/core/k8s/it/ActuatorEndpointIT.java
index 213ddb02..fabd3577 100644
--- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/java/org/springframework/cloud/kubernetes/core/k8s/it/ActuatorEndpointIT.java
+++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-core-k8s-client-it/src/test/java/org/springframework/cloud/kubernetes/core/k8s/it/ActuatorEndpointIT.java
@@ -16,6 +16,8 @@
package org.springframework.cloud.kubernetes.core.k8s.it;
+import java.io.IOException;
+import java.time.Duration;
import java.util.Map;
import com.github.dockerjava.api.DockerClient;
@@ -33,6 +35,8 @@ import io.kubernetes.client.openapi.models.NetworkingV1beta1Ingress;
import io.kubernetes.client.openapi.models.V1Deployment;
import io.kubernetes.client.openapi.models.V1Service;
import io.kubernetes.client.util.Config;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -41,9 +45,12 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
+import static org.awaitility.Awaitility.await;
/**
* @author Ryan Baxter
@@ -51,6 +58,8 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
@RunWith(MockitoJUnitRunner.class)
public class ActuatorEndpointIT {
+ private static final Log LOG = LogFactory.getLog(ActuatorEndpointIT.class);
+
private static final String KIND_REPO_HOST_PORT = "localhost:5000";
private static final String KIND_REPO_URL = "http://" + KIND_REPO_HOST_PORT;
@@ -96,9 +105,9 @@ public class ActuatorEndpointIT {
k8SUtils = new K8SUtils(api, appsApi);
DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
- .withRegistryUrl(KIND_REPO_URL).build();
+ .withRegistryUrl(KIND_REPO_URL).build();
DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder().dockerHost(config.getDockerHost())
- .sslConfig(config.getSSLConfig()).build();
+ .sslConfig(config.getSSLConfig()).build();
DockerClient dockerClient = DockerClientImpl.getInstance(config, httpClient);
dockerClient.tagImageCmd(LOCAL_IMAGE, KIND_IMAGE, IMAGE_TAG).exec();
@@ -118,19 +127,19 @@ public class ActuatorEndpointIT {
private static V1Deployment getCoreK8sClientItDeployment() throws Exception {
V1Deployment deployment = (V1Deployment) k8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-it-deployment.yaml");
+ .readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-it-deployment.yaml");
return deployment;
}
private static V1Service getCoreK8sClientItService() throws Exception {
V1Service service = (V1Service) k8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-it-service.yaml");
+ .readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-it-service.yaml");
return service;
}
private static NetworkingV1beta1Ingress getCoreK8sClientItIngress() throws Exception {
NetworkingV1beta1Ingress ingress = (NetworkingV1beta1Ingress) k8SUtils
- .readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-it-ingress.yaml");
+ .readYamlFromClasspath("spring-cloud-kubernetes-core-k8s-client-it-ingress.yaml");
return ingress;
}
@@ -138,8 +147,29 @@ public class ActuatorEndpointIT {
public void testHealth() {
RestTemplate rest = new RestTemplateBuilder().build();
+ rest.setErrorHandler(new ResponseErrorHandler() {
+ @Override
+ public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
+ LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
+ if (clientHttpResponse.getRawStatusCode() == 503) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
+
+ }
+ });
+
+ //Sometimes the NGINX ingress takes a bit to catch up and realize the service is available and we get a 503, we just need to wait a bit
+ await().timeout(Duration.ofSeconds(60))
+ .until(() -> rest.getForEntity("http://localhost:80/core-k8s-client-it/actuator/health", String.class)
+ .getStatusCode().is2xxSuccessful());
+
Map health = rest.getForObject("http://localhost:80/core-k8s-client-it/actuator/health",
- Map.class);
+ Map.class);
Map components = (Map) health.get("components");
assertThat(components.containsKey("kubernetes")).isTrue();
Map kubernetes = (Map) components.get("kubernetes");
@@ -159,6 +189,28 @@ public class ActuatorEndpointIT {
public void testInfo() {
RestTemplate rest = new RestTemplateBuilder().build();
+
+ rest.setErrorHandler(new ResponseErrorHandler() {
+ @Override
+ public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
+ LOG.warn("Received response status code: " + clientHttpResponse.getRawStatusCode());
+ if (clientHttpResponse.getRawStatusCode() == 503) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
+
+ }
+ });
+
+ //Sometimes the NGINX ingress takes a bit to catch up and realize the service is available and we get a 503, we just need to wait a bit
+ await().timeout(Duration.ofSeconds(60))
+ .until(() -> rest.getForEntity("http://localhost:80/core-k8s-client-it/actuator/info", String.class)
+ .getStatusCode().is2xxSuccessful());
+
Map info = rest.getForObject("http://localhost:80/core-k8s-client-it/actuator/info", Map.class);
Map kubernetes = (Map) info.get("kubernetes");
assertThat(kubernetes.containsKey("hostIp")).isTrue();
@@ -173,7 +225,7 @@ public class ActuatorEndpointIT {
@AfterClass
public static void after() throws Exception {
appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
- "metadata.name=" + K8S_CONFIG_CLIENT_IT_NAME, null, null, null, null, null, null, null, null);
+ "metadata.name=" + K8S_CONFIG_CLIENT_IT_NAME, null, null, null, null, null, null, null, null);
api.deleteNamespacedService(K8S_CONFIG_CLIENT_IT_SERVICE_NAME, NAMESPACE, null, null, null, null, null, null);
networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null);
}
diff --git a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/K8SUtils.java b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/K8SUtils.java
index 5dbc521f..191b0c96 100644
--- a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/K8SUtils.java
+++ b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/K8SUtils.java
@@ -154,6 +154,15 @@ public class K8SUtils {
.until(() -> isDeployentReady(deploymentName, namespace));
}
+ public void waitForDeploymentToBeDeleted(String deploymentName, String namespace) {
+ await().timeout(
+ Duration.ofSeconds(90)).until(
+ () -> appsApi
+ .listNamespacedDeployment(namespace, null, null, null,
+ "metadata.name=" + deploymentName, null, null, null, null, null)
+ .getItems().isEmpty());
+ }
+
public boolean isDeployentReady(String deploymentName, String namespace) throws ApiException {
V1DeploymentList deployments = appsApi.listNamespacedDeployment(namespace, null, null, null,
"metadata.name=" + deploymentName, null, null, null, null, null);
diff --git a/spring-cloud-starter-kubernetes-all/pom.xml b/spring-cloud-starter-kubernetes-all/pom.xml
index ed34d2c6..8e3a9909 100644
--- a/spring-cloud-starter-kubernetes-all/pom.xml
+++ b/spring-cloud-starter-kubernetes-all/pom.xml
@@ -38,7 +38,7 @@
org.springframework.cloud
- spring-cloud-kubernetes-config
+ spring-cloud-kubernetes-fabric8-config
diff --git a/spring-cloud-starter-kubernetes-client-all/pom.xml b/spring-cloud-starter-kubernetes-client-all/pom.xml
index 1e356384..608c03cf 100644
--- a/spring-cloud-starter-kubernetes-client-all/pom.xml
+++ b/spring-cloud-starter-kubernetes-client-all/pom.xml
@@ -16,6 +16,10 @@
org.springframework.cloud
spring-cloud-kubernetes-client-autoconfig
+
+ org.springframework.cloud
+ spring-cloud-kubernetes-client-config
+
diff --git a/spring-cloud-starter-kubernetes-config/pom.xml b/spring-cloud-starter-kubernetes-config/pom.xml
index 54c5365c..d4332ece 100644
--- a/spring-cloud-starter-kubernetes-config/pom.xml
+++ b/spring-cloud-starter-kubernetes-config/pom.xml
@@ -42,7 +42,7 @@
org.springframework.cloud
- spring-cloud-kubernetes-config
+ spring-cloud-kubernetes-fabric8-config