From 82224ca4782934e1f6e39f8bfe9c6263be48a030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=A4ni?= Date: Thu, 24 Oct 2024 14:53:16 +0200 Subject: [PATCH 1/4] fix doc link in propertysource-reload.adoc (#1775) * fix doc link in propertysource-reload.adoc * line break --- .../pages/property-source-config/propertysource-reload.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/property-source-config/propertysource-reload.adoc b/docs/modules/ROOT/pages/property-source-config/propertysource-reload.adoc index d656135d..6053e6a4 100644 --- a/docs/modules/ROOT/pages/property-source-config/propertysource-reload.adoc +++ b/docs/modules/ROOT/pages/property-source-config/propertysource-reload.adoc @@ -2,8 +2,8 @@ = `PropertySource` Reload WARNING: This functionality has been deprecated in the 2020.0 release. Please see -the xref:spring-cloud-kubernetes-configuration-watcher.adoc#spring-cloud-kubernetes-configuration-watcher[null] controller for an alternative way -to achieve the same functionality. +the xref:spring-cloud-kubernetes-configuration-watcher.adoc#spring-cloud-kubernetes-configuration-watcher[Spring Cloud Kubernetes Configuration Watcher] +controller for an alternative way to achieve the same functionality. Some applications may need to detect changes on external property sources and update their internal status to reflect the new configuration. The reload feature of Spring Cloud Kubernetes is able to trigger an application reload when a related `ConfigMap` or From cc374dbd6b2ebecfcd85ca6e5d633ce0b6166650 Mon Sep 17 00:00:00 2001 From: spring-builds Date: Fri, 25 Oct 2024 19:00:55 +0000 Subject: [PATCH 2/4] Bumping versions --- .../cloud/kubernetes/commons/config/ConfigUtils.java | 3 ++- .../kubernetes/fabric8/Fabric8AutoConfiguration.java | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java index 423c7269..ed5f889e 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java @@ -61,7 +61,8 @@ public final class ConfigUtils { || sourceName.endsWith("-" + activeProfile + ".yaml") || sourceName.endsWith("-" + activeProfile + ".properties"); - private static final ApplicationListener NO_OP = (e) -> { }; + private static final ApplicationListener NO_OP = (e) -> { + }; private ConfigUtils() { } diff --git a/spring-cloud-kubernetes-fabric8-autoconfig/src/main/java/org/springframework/cloud/kubernetes/fabric8/Fabric8AutoConfiguration.java b/spring-cloud-kubernetes-fabric8-autoconfig/src/main/java/org/springframework/cloud/kubernetes/fabric8/Fabric8AutoConfiguration.java index 4b66c760..fb526047 100644 --- a/spring-cloud-kubernetes-fabric8-autoconfig/src/main/java/org/springframework/cloud/kubernetes/fabric8/Fabric8AutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-autoconfig/src/main/java/org/springframework/cloud/kubernetes/fabric8/Fabric8AutoConfiguration.java @@ -123,9 +123,11 @@ public class Fabric8AutoConfiguration { @EventListener void onContextClosed(ContextClosedEvent event) { - // Clean up any open connections from the KubernetesClient when the context is closed - BeanFactoryUtils.beansOfTypeIncludingAncestors(event.getApplicationContext(), KubernetesClient.class).values() - .forEach(Client::close); + // Clean up any open connections from the KubernetesClient when the context is + // closed + BeanFactoryUtils.beansOfTypeIncludingAncestors(event.getApplicationContext(), KubernetesClient.class) + .values() + .forEach(Client::close); } } From 952d9549026ce350cd7258ab9d97b4891db2b213 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:34:14 -0500 Subject: [PATCH 3/4] Bump @antora/collector-extension in /docs (#1784) --- updated-dependencies: - dependency-name: "@antora/collector-extension" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/package.json b/docs/package.json index 37c37659..87272568 100644 --- a/docs/package.json +++ b/docs/package.json @@ -2,7 +2,7 @@ "dependencies": { "antora": "3.2.0-alpha.4", "@antora/atlas-extension": "1.0.0-alpha.2", - "@antora/collector-extension": "1.0.0-beta.3", + "@antora/collector-extension": "1.0.0-beta.4", "@asciidoctor/tabs": "1.0.0-beta.6", "@springio/antora-extensions": "1.11.1", "@springio/asciidoctor-extensions": "1.0.0-alpha.14" From aad8cd096ff027662060270c8b89d8f361abb039 Mon Sep 17 00:00:00 2001 From: erabii Date: Wed, 6 Nov 2024 17:29:05 +0200 Subject: [PATCH 4/4] clean-up for issue 1592 (#1782) * first, no tests Signed-off-by: wind57 * still broken Signed-off-by: wind57 * still broken Signed-off-by: wind57 * still broken Signed-off-by: wind57 * checkstyle Signed-off-by: wind57 * still broken Signed-off-by: wind57 * still broken Signed-off-by: wind57 * still broken Signed-off-by: wind57 * add more debug logs Signed-off-by: wind57 * rename Signed-off-by: wind57 * rename Signed-off-by: wind57 * add debug statement Signed-off-by: wind57 * more simplifications Signed-off-by: wind57 * correction Signed-off-by: wind57 * corect debug statement Signed-off-by: wind57 * disable configmap Signed-off-by: wind57 * test Signed-off-by: wind57 * cleanup Signed-off-by: wind57 * cleanup Signed-off-by: wind57 * cleanup Signed-off-by: wind57 * fix Signed-off-by: wind57 * add log statement Signed-off-by: wind57 --------- Signed-off-by: wind57 --- .../config/KubernetesClientConfigUtils.java | 2 +- .../ConfigMapPropertySourceLocator.java | 6 ++- .../commons/config/ConfigUtils.java | 5 ++- .../commons/config/LabeledSourceData.java | 3 +- .../commons/config/NamedSourceData.java | 10 ++++- .../config/SecretsPropertySourceLocator.java | 8 +++- .../kubernetes/commons/config/SourceData.java | 5 +-- .../config/SourceDataEntriesProcessor.java | 2 +- .../config/reload/ConfigReloadUtil.java | 40 +++++++++---------- .../resources/application-with-secret.yaml | 8 +++- 10 files changed, 55 insertions(+), 34 deletions(-) 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 index 21bc92b9..f4be4ef8 100644 --- 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 @@ -147,7 +147,7 @@ public final class KubernetesClientConfigUtils { private static List strippedSecrets(CoreV1Api coreV1Api, String namespace) { List strippedSecrets = KubernetesClientSecretsCache.byNamespace(coreV1Api, namespace); if (strippedSecrets.isEmpty()) { - LOG.debug("No configmaps in namespace '" + namespace + "'"); + LOG.debug("No secrets in namespace '" + namespace + "'"); } return strippedSecrets; } diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapPropertySourceLocator.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapPropertySourceLocator.java index 7c268847..f2996293 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapPropertySourceLocator.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapPropertySourceLocator.java @@ -82,7 +82,11 @@ public abstract class ConfigMapPropertySourceLocator implements PropertySourceLo if (this.properties.enableApi()) { Set sources = new LinkedHashSet<>(this.properties.determineSources(environment)); LOG.debug("Config Map normalized sources : " + sources); - sources.forEach(s -> composite.addFirstPropertySource(getMapPropertySource(s, env))); + sources.forEach(s -> { + MapPropertySource propertySource = getMapPropertySource(s, env); + LOG.debug("Adding config map property source " + propertySource.getName()); + composite.addFirstPropertySource(propertySource); + }); } addPropertySourcesFromPaths(environment, composite); diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java index ed5f889e..886e9e7b 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java @@ -210,7 +210,7 @@ public final class ConfigUtils { sourceNames.forEach(sourceName -> { StrippedSourceContainer stripped = hashByName.get(sourceName); if (stripped != null) { - LOG.debug("Found source with name : '" + sourceName + " in namespace: '" + namespace + "'"); + LOG.debug("Found source with name : '" + sourceName + "' in namespace: '" + namespace + "'"); foundSourceNames.add(sourceName); // see if data is a single yaml/properties file and if it needs decoding Map rawData = stripped.data(); @@ -229,6 +229,9 @@ public final class ConfigUtils { environment, includeDefaultProfileData)); } } + else { + LOG.warn("sourceName : " + sourceName + " was requested, but not found in namespace : " + namespace); + } }); return new MultipleSourcesContainer(foundSourceNames, data); diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/LabeledSourceData.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/LabeledSourceData.java index df4e6aab..7c306899 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/LabeledSourceData.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/LabeledSourceData.java @@ -45,8 +45,7 @@ public abstract class LabeledSourceData { data = dataSupplier(labels, profiles); // need this check because when there is no data, the name of the property - // source - // is using provided labels, + // source is using provided labels, // unlike when the data is present: when we use secret names if (data.names().isEmpty()) { String names = labels.keySet() diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/NamedSourceData.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/NamedSourceData.java index f9846465..c198e433 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/NamedSourceData.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/NamedSourceData.java @@ -17,9 +17,11 @@ package org.springframework.cloud.kubernetes.commons.config; import java.util.LinkedHashSet; -import java.util.Map; import java.util.stream.Collectors; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.onException; import static org.springframework.cloud.kubernetes.commons.config.Constants.PROPERTY_SOURCE_NAME_SEPARATOR; @@ -31,6 +33,8 @@ import static org.springframework.cloud.kubernetes.commons.config.Constants.PROP */ public abstract class NamedSourceData { + private static final Log LOG = LogFactory.getLog(NamedSourceData.class); + public final SourceData compute(String sourceName, ConfigUtils.Prefix prefix, String target, boolean profileSources, boolean failFast, String namespace, String[] activeProfiles) { @@ -51,7 +55,9 @@ public abstract class NamedSourceData { data = dataSupplier(sourceNames); if (data.names().isEmpty()) { - return new SourceData(ConfigUtils.sourceName(target, sourceName, namespace), Map.of()); + String emptySourceName = ConfigUtils.sourceName(target, sourceName, namespace); + LOG.debug("Will return empty source with name : " + emptySourceName); + return SourceData.emptyRecord(emptySourceName); } if (prefix != ConfigUtils.Prefix.DEFAULT) { diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsPropertySourceLocator.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsPropertySourceLocator.java index ca954a6e..f35e40e0 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsPropertySourceLocator.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsPropertySourceLocator.java @@ -42,6 +42,7 @@ import org.springframework.cloud.bootstrap.config.PropertySourceLocator; 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; /** @@ -87,8 +88,11 @@ public abstract class SecretsPropertySourceLocator implements PropertySourceLoca putPathConfig(composite); if (this.properties.enableApi()) { - uniqueSources - .forEach(s -> composite.addPropertySource(getSecretsPropertySourceForSingleSecret(env, s))); + uniqueSources.forEach(s -> { + MapPropertySource propertySource = getSecretsPropertySourceForSingleSecret(env, s); + LOG.debug("Adding secret property source " + propertySource.getName()); + composite.addFirstPropertySource(propertySource); + }); } cache.discardAll(); diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SourceData.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SourceData.java index 29b4280e..b9eb46c0 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SourceData.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SourceData.java @@ -16,7 +16,6 @@ package org.springframework.cloud.kubernetes.commons.config; -import java.util.Collections; import java.util.Map; /** @@ -25,10 +24,10 @@ import java.util.Map; * * @author wind57 */ -public final record SourceData(String sourceName, Map sourceData) { +public record SourceData(String sourceName, Map sourceData) { public static SourceData emptyRecord(String sourceName) { - return new SourceData(sourceName, Collections.emptyMap()); + return new SourceData(sourceName, Map.of()); } } diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SourceDataEntriesProcessor.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SourceDataEntriesProcessor.java index 7e313b70..5f51e970 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SourceDataEntriesProcessor.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SourceDataEntriesProcessor.java @@ -48,7 +48,7 @@ public class SourceDataEntriesProcessor extends MapPropertySource { private static final Log LOG = LogFactory.getLog(SourceDataEntriesProcessor.class); - private static Predicate ENDS_IN_EXTENSION = x -> x.endsWith(".yml") || x.endsWith(".yaml") + private static final Predicate ENDS_IN_EXTENSION = x -> x.endsWith(".yml") || x.endsWith(".yaml") || x.endsWith(".properties"); public SourceDataEntriesProcessor(SourceData sourceData) { diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadUtil.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadUtil.java index 90448150..c0be3d8c 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadUtil.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadUtil.java @@ -141,25 +141,25 @@ public final class ConfigReloadUtil { return result; } - static boolean changed(List left, List right) { - if (left.size() != right.size()) { + static boolean changed(List k8sSources, List appSources) { + if (k8sSources.size() != appSources.size()) { if (LOG.isDebugEnabled()) { - LOG.debug("left size: " + left.size()); - left.forEach(item -> LOG.debug(item.toString())); + LOG.debug("k8s property sources size: " + k8sSources.size()); + k8sSources.forEach(item -> LOG.debug(item.toString())); - LOG.debug("right size: " + right.size()); - right.forEach(item -> LOG.debug(item.toString())); + LOG.debug("app property sources size size: " + appSources.size()); + appSources.forEach(item -> LOG.debug(item.toString())); } - LOG.warn(() -> "The current number of ConfigMap PropertySources does not match " + LOG.warn(() -> "The current number of PropertySources does not match " + "the ones loaded from Kubernetes - No reload will take place"); return false; } - for (int i = 0; i < left.size(); i++) { - MapPropertySource leftPropertySource = left.get(i); - MapPropertySource rightPropertySource = right.get(i); - if (changed(leftPropertySource, rightPropertySource)) { - LOG.debug(() -> "found change in : " + leftPropertySource); + for (int i = 0; i < k8sSources.size(); i++) { + MapPropertySource k8sSource = k8sSources.get(i); + MapPropertySource appSource = appSources.get(i); + if (changed(k8sSource, appSource)) { + LOG.debug(() -> "found change in : " + k8sSource); return true; } } @@ -169,20 +169,20 @@ public final class ConfigReloadUtil { /** * Determines if two property sources are different. - * @param left left map property sources - * @param right right map property sources + * @param k8sSource left map property sources + * @param appSource right map property sources * @return {@code true} if source has changed */ - static boolean changed(MapPropertySource left, MapPropertySource right) { - if (left == right) { + static boolean changed(MapPropertySource k8sSource, MapPropertySource appSource) { + if (k8sSource == appSource) { return false; } - if (left == null || right == null) { + if (k8sSource == null || appSource == null) { return true; } - Map leftMap = left.getSource(); - Map rightMap = right.getSource(); - return !Objects.equals(leftMap, rightMap); + Map k8sMap = k8sSource.getSource(); + Map appMap = appSource.getSource(); + return !Objects.equals(k8sMap, appMap); } } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-with-secret.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-with-secret.yaml index fb844898..2208fa1a 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-with-secret.yaml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-with-secret.yaml @@ -1,6 +1,9 @@ logging: level: - root: DEBUG + org: + springframework: + cloud: + kubernetes: debug spring: application: @@ -18,3 +21,6 @@ spring: secrets: enabled: true enable-api: true + + config: + enabled: false