From ba0288cf6d8482fef5ec99108c31a5fa29e9182d Mon Sep 17 00:00:00 2001 From: wind57 Date: Thu, 9 Apr 2026 15:38:20 +0300 Subject: [PATCH 1/9] 2208: breaking changes Signed-off-by: wind57 --- .../config/reload/ConfigReloadProperties.java | 44 ++----------------- .../config/ConfigReloadPropertiesTests.java | 4 -- 2 files changed, 3 insertions(+), 45 deletions(-) diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java index 8fd85f0c11..0141c3c967 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java @@ -21,7 +21,6 @@ import java.util.Set; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.bind.ConstructorBinding; import org.springframework.boot.context.properties.bind.DefaultValue; /** @@ -37,9 +36,6 @@ * @param period Sets the polling period to use when the detection mode is POLLING. * @param namespaces namespaces where an informer will be set-up. this property is only * relevant for event based reloading. - * @param enableReloadFiltering create an informer only for sources that have - * 'spring.cloud.kubernetes.config.informer.enabled=true' label. This property is only - * relevant for event based reloading. * @param maxWaitForRestart Restart or Shutdown strategies are used, Spring Cloud * Kubernetes waits a random amount of time before restarting. This is done in order to * avoid having all instances of the same application restart at the same time. This @@ -48,53 +44,19 @@ * @author Nicola Ferraro */ @ConfigurationProperties(prefix = "spring.cloud.kubernetes.reload") -public record ConfigReloadProperties(boolean enabled, boolean monitoringConfigMaps, - Map configMapsLabels, - boolean monitoringSecrets, Map secretsLabels, - ReloadStrategy strategy, - ReloadDetectionMode mode, Duration period, - Set namespaces, boolean enableReloadFiltering, - Duration maxWaitForRestart) { - - @ConstructorBinding - public ConfigReloadProperties(boolean enabled, @DefaultValue("true") boolean monitoringConfigMaps, +public record ConfigReloadProperties(boolean enabled, @DefaultValue("true") boolean monitoringConfigMaps, @DefaultValue Map configMapsLabels, boolean monitoringSecrets, @DefaultValue Map secretsLabels, @DefaultValue("REFRESH") ReloadStrategy strategy, @DefaultValue("EVENT") ReloadDetectionMode mode, @DefaultValue("15000ms") Duration period, - @DefaultValue Set namespaces, boolean enableReloadFiltering, + @DefaultValue Set namespaces, @DefaultValue("2s") Duration maxWaitForRestart) { - this.enabled = enabled; - this.monitoringConfigMaps = monitoringConfigMaps; - this.configMapsLabels = configMapsLabels; - this.monitoringSecrets = monitoringSecrets; - this.secretsLabels = secretsLabels; - this.strategy = strategy; - this.mode = mode; - this.period = period; - this.namespaces = namespaces; - this.enableReloadFiltering = enableReloadFiltering; - this.maxWaitForRestart = maxWaitForRestart; - } - - @Deprecated(forRemoval = true) - public ConfigReloadProperties(boolean enabled, @DefaultValue("true") boolean monitoringConfigMaps, - boolean monitoringSecrets, - @DefaultValue("REFRESH") ReloadStrategy strategy, - @DefaultValue("EVENT") ReloadDetectionMode mode, @DefaultValue("15000ms") Duration period, - @DefaultValue Set namespaces, boolean enableReloadFiltering, - @DefaultValue("2s") Duration maxWaitForRestart) { - - this(enabled, monitoringConfigMaps, Map.of(), monitoringSecrets, Map.of(), - strategy, mode, period, namespaces, enableReloadFiltering, maxWaitForRestart); - } - /** * default instance. */ public static final ConfigReloadProperties DEFAULT = new ConfigReloadProperties(false, true, Map.of(), false, - Map.of(), ReloadStrategy.REFRESH, ReloadDetectionMode.EVENT, Duration.ofMillis(15000), Set.of(), false, + Map.of(), ReloadStrategy.REFRESH, ReloadDetectionMode.EVENT, Duration.ofMillis(15000), Set.of(), Duration.ofSeconds(2)); /** diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigReloadPropertiesTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigReloadPropertiesTests.java index 43d5b50863..63abc13eb7 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigReloadPropertiesTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigReloadPropertiesTests.java @@ -19,7 +19,6 @@ import java.time.Duration; import java.util.Map; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -54,7 +53,6 @@ void testDefaults() { assertThat(ConfigReloadProperties.ReloadDetectionMode.EVENT).isEqualTo(properties.mode()); assertThat(Duration.ofMillis(15000)).isEqualTo(properties.period()); assertThat(properties.namespaces().isEmpty()).isTrue(); - assertThat(properties.enableReloadFiltering()).isFalse(); assertThat(Duration.ofSeconds(2)).isEqualTo(properties.maxWaitForRestart()); }); } @@ -70,7 +68,6 @@ void testNonDefaults() { "spring.cloud.kubernetes.reload.strategy=SHUTDOWN", "spring.cloud.kubernetes.reload.mode=POLLING", "spring.cloud.kubernetes.reload.period=1000ms", "spring.cloud.kubernetes.reload.namespaces[0]=a", "spring.cloud.kubernetes.reload.namespaces[1]=b", - "spring.cloud.kubernetes.reload.enable-reload-filtering=true", "spring.cloud.kubernetes.reload.max-wait-for-restart=5s") .run(context -> { ConfigReloadProperties properties = context.getBean(ConfigReloadProperties.class); @@ -84,7 +81,6 @@ void testNonDefaults() { assertThat(ConfigReloadProperties.ReloadDetectionMode.POLLING).isEqualTo(properties.mode()); assertThat(Duration.ofMillis(1000)).isEqualTo(properties.period()); assertThat(properties.namespaces()).containsExactlyInAnyOrder("a", "b"); - assertThat(properties.enableReloadFiltering()).isTrue(); assertThat(Duration.ofSeconds(5)).isEqualTo(properties.maxWaitForRestart()); }); } From eac9eb7879b66a5b341e6f4a015c0d0dbe07480b Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 15 Apr 2026 12:24:54 +0300 Subject: [PATCH 2/9] first test on removal Signed-off-by: wind57 --- .../namespace-label-filtering.adoc | 23 +- ...loud-kubernetes-configuration-watcher.adoc | 14 +- docs/modules/ROOT/partials/_configprops.adoc | 3 +- ...ientEventBasedConfigMapChangeDetector.java | 3 +- .../KubernetesClientConfigUtilsTests.java | 5 +- .../reload/ConfigMapReloadWithFilterTest.java | 212 ------------------ .../reload/ConfigMapReloadWithLabelsTest.java | 3 +- ...tEventBasedSecretsChangeDetectorTests.java | 4 +- .../reload/SecretReloadWithFilterTest.java | 212 ------------------ .../reload/SecretReloadWithLabelsTest.java | 3 +- .../reload_it/EventReloadConfigMapTest.java | 6 +- .../reload_it/EventReloadSecretTest.java | 6 +- .../reload_it/PollingReloadConfigMapTest.java | 6 +- .../reload_it/PollingReloadSecretTest.java | 6 +- .../config/reload/ConfigReloadProperties.java | 9 +- ...ric8EventBasedConfigMapChangeDetector.java | 23 +- ...abric8EventBasedSecretsChangeDetector.java | 22 +- .../config/Fabric8ConfigUtilsTests.java | 8 +- .../reload_it/EventReloadConfigMapTest.java | 6 +- .../reload_it/EventReloadSecretTest.java | 6 +- .../PollingReloadConfigMapAndSecretTest.java | 6 +- .../reload_it/PollingReloadConfigMapTest.java | 6 +- .../reload_it/PollingReloadSecretTest.java | 6 +- .../labels/ConfigMapReloadWithFilterTest.java | 200 ----------------- .../labels/ConfigMapReloadWithLabelsTest.java | 3 +- .../labels/SecretReloadWithFilterTest.java | 202 ----------------- .../labels/SecretReloadWithLabelsTest.java | 3 +- .../src/main/resources/application-three.yaml | 3 +- .../src/main/resources/application-three.yaml | 3 +- 29 files changed, 61 insertions(+), 951 deletions(-) delete mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/ConfigMapReloadWithFilterTest.java delete mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/SecretReloadWithFilterTest.java delete mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/ConfigMapReloadWithFilterTest.java delete mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/SecretReloadWithFilterTest.java diff --git a/docs/modules/ROOT/pages/property-source-config/namespace-label-filtering.adoc b/docs/modules/ROOT/pages/property-source-config/namespace-label-filtering.adoc index 4123fff339..90f92fa89e 100644 --- a/docs/modules/ROOT/pages/property-source-config/namespace-label-filtering.adoc +++ b/docs/modules/ROOT/pages/property-source-config/namespace-label-filtering.adoc @@ -25,27 +25,7 @@ spring: Such a configuration will make the app watch changes only in the `my-namespace` namespace. Mind that this will watch _all_ configmaps/secrets (depending on which one you enable). If you want an even more fine-grained approach, -you can enable "label-filtering". First we need to enable such support via : `enable-reload-filtering: true` - -[source,yaml] ----- -spring: - application: - name: event-reload - cloud: - kubernetes: - reload: - enabled: true - strategy: shutdown - mode: event - namespaces: - - my-namespaces - monitoring-config-maps: true - enable-reload-filtering: true ----- - -What this will do, is watch configmaps/secrets that only have the `spring.cloud.kubernetes.config.informer.enabled: true` label. -In the next major release this support will be removed and replaced with: +you can set the labels that are supposed to be watched, via: [source,yaml] ---- @@ -80,7 +60,6 @@ spring: | `spring.cloud.kubernetes.reload.mode` | `Enum` | `event` | Specifies how to listen for changes in property sources (`event` or `polling`) | `spring.cloud.kubernetes.reload.period` | `Duration`| `15s` | The period for verifying changes when using the `polling` strategy | `spring.cloud.kubernetes.reload.namespaces` | `String[]`| | namespaces where we should watch for changes -| `spring.cloud.kubernetes.reload.enable-reload-filtering` | `String` | | enabled labeled filtering for reload functionality |=== Notes: diff --git a/docs/modules/ROOT/pages/spring-cloud-kubernetes-configuration-watcher.adoc b/docs/modules/ROOT/pages/spring-cloud-kubernetes-configuration-watcher.adoc index 84021ecd5e..35302b5077 100644 --- a/docs/modules/ROOT/pages/spring-cloud-kubernetes-configuration-watcher.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-kubernetes-configuration-watcher.adoc @@ -43,26 +43,18 @@ Changes from configmaps/secrets will only trigger an event being fired from conf To put it simpler, if you change a configmap (or secret), that does _not_ have the label above, configuration watcher will skip firing an event for it (if you enabled debug logging, this will be visible in logs). -By default, configuration watcher will monitor all configmaps/secrets in the configured namespace(s). If you want to filter to watch only particular sources, you can do that by setting: +By default, configuration watcher will monitor all configmaps/secrets in the configured namespace(s). If you want to watch only particular sources, you can do that by choosing only sources with some labels: [source] ---- -SPRING_CLOUD_KUBERNETES_CONFIG_INFORMER_ENABLED=TRUE ----- - -This will tell watcher to only monitor sources that have a label: `spring.cloud.kubernetes.config.informer.enabled=true`. -This support will be dropped in the next major release and will be replaced with: - -[source] ----- -spring.cloud.kubernetes.reload.config-maps-labels +spring.cloud.kubernetes.reload.config-maps-labels[a]=b ---- and [source] ---- -spring.cloud.kubernetes.reload.secrets-labels +spring.cloud.kubernetes.reload.secrets-labels[c]=d ---- One more important configuration, especially for configmaps and secrets that are mounted as volumes (via `spring.config.import`) is: diff --git a/docs/modules/ROOT/partials/_configprops.adoc b/docs/modules/ROOT/partials/_configprops.adoc index 3a6a94e5ba..9c144fb8d4 100644 --- a/docs/modules/ROOT/partials/_configprops.adoc +++ b/docs/modules/ROOT/partials/_configprops.adoc @@ -101,7 +101,6 @@ |spring.cloud.kubernetes.loadbalancer.enabled | `+++true+++` | Load balancer enabled,default true. |spring.cloud.kubernetes.loadbalancer.mode | `+++pod+++` | {@link KubernetesLoadBalancerMode} setting load balancer server list with ip of pod or service name. default value is POD. |spring.cloud.kubernetes.loadbalancer.port-name | `+++http+++` | service port name. -|spring.cloud.kubernetes.reload.enable-reload-filtering | `+++false+++` | create an informer only for sources that have 'spring.cloud.kubernetes.config.informer.enabled=true' label. This property is only relevant for event based reloading. |spring.cloud.kubernetes.reload.enabled | `+++false+++` | Enables the Kubernetes configuration reload on change. |spring.cloud.kubernetes.reload.max-wait-for-restart | `+++2s+++` | Restart or Shutdown strategies are used, Spring Cloud Kubernetes waits a random amount of time before restarting. This is done in order to avoid having all instances of the same application restart at the same time. This property configures the maximum of amount of wait time from the moment the signal is received that a restart is needed until the moment the restart is actually triggered |spring.cloud.kubernetes.reload.mode | `+++EVENT+++` | Sets the detection mode for Kubernetes configuration reload. @@ -121,4 +120,4 @@ |spring.cloud.kubernetes.secrets.sources | | |spring.cloud.kubernetes.secrets.use-name-as-prefix | `+++false+++` | -|=== \ No newline at end of file +|=== 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 index 421a3d9c71..8272298953 100644 --- 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 @@ -137,7 +137,8 @@ void inform() { .labelSelector(labelSelector(configMapsLabels)) .buildCall(null), V1ConfigMap.class, V1ConfigMapList.class); - LOG.debug(() -> "configmap informer for namespace : " + namespace + " with labels : " + configMapsLabels); + LOG.debug( + () -> "configmap informer for namespace : " + namespace + " with labels : " + configMapsLabels); informer.addEventHandler(handler); informers.add(informer); diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigUtilsTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigUtilsTests.java index 96a47a883b..d19ff769ff 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigUtilsTests.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigUtilsTests.java @@ -17,6 +17,7 @@ package org.springframework.cloud.kubernetes.client.config; import java.time.Duration; +import java.util.Map; import java.util.Set; import org.assertj.core.api.Assertions; @@ -33,9 +34,9 @@ class KubernetesClientConfigUtilsTests { @Test void testNamespacesFromProperties() { - ConfigReloadProperties properties = new ConfigReloadProperties(false, false, false, + ConfigReloadProperties properties = new ConfigReloadProperties(false, false, Map.of(), false, Map.of(), ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, - Duration.ofMillis(15000), Set.of("non-default"), false, Duration.ofSeconds(2)); + Duration.ofMillis(15000), Set.of("non-default"), Duration.ofSeconds(2)); Set namespaces = KubernetesClientConfigUtils .namespaces(new KubernetesNamespaceProvider(new MockEnvironment()), properties, "configmap"); Assertions.assertThat(1).isEqualTo(namespaces.size()); diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/ConfigMapReloadWithFilterTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/ConfigMapReloadWithFilterTest.java deleted file mode 100644 index 35b6ba3e80..0000000000 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/ConfigMapReloadWithFilterTest.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2012-present 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.List; -import java.util.Map; -import java.util.Set; - -import com.github.tomakehurst.wiremock.WireMockServer; -import com.github.tomakehurst.wiremock.client.VerificationException; -import com.github.tomakehurst.wiremock.client.WireMock; -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 org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.system.OutputCaptureExtension; -import org.springframework.cloud.kubernetes.client.KubernetesClientUtils; -import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySource; -import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; -import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties; -import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy; -import org.springframework.cloud.kubernetes.integration.tests.commons.Awaitilities; -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.getRequestedFor; -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 io.kubernetes.client.informer.EventType.ADDED; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.springframework.cloud.kubernetes.client.KubernetesClientUtils.getApplicationNamespace; - -/** - * @author wind57 - */ -@SpringBootTest(properties = { "spring.main.allow-bean-definition-overriding=true" }) -@ExtendWith(OutputCaptureExtension.class) -class ConfigMapReloadWithFilterTest { - - private static WireMockServer wireMockServer; - - private static final String PATH = "^/api/v1/namespaces/default/configmaps.*"; - - private static CoreV1Api coreV1Api; - - private static final MockedStatic MOCK_STATIC = Mockito - .mockStatic(KubernetesClientUtils.class); - - @BeforeAll - 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(); - MOCK_STATIC.when(KubernetesClientUtils::createApiClientForInformerClient).thenReturn(client); - MOCK_STATIC.when(() -> getApplicationNamespace(Mockito.nullable(String.class), anyString(), any())) - .thenReturn("default"); - coreV1Api = new CoreV1Api(client); - } - - @AfterAll - static void after() { - MOCK_STATIC.close(); - wireMockServer.stop(); - } - - @Test - void test() { - - V1ConfigMap myConfigMap = new V1ConfigMap() - .metadata(new V1ObjectMeta().namespace("default") - .name("my-config-map") - .labels(Map.of("spring.cloud.kubernetes.config.informer.enabled", "true"))) - .data(Map.of("shape", "round")); - - V1ConfigMapList configMapList = new V1ConfigMapList().metadata(new V1ListMeta().resourceVersion("1")) - .items(List.of(myConfigMap)); - - // 1. first call to informer - stubFor(get(urlMatching(PATH)).withQueryParam("watch", equalTo("false")) - .withQueryParam("resourceVersion", equalTo("0")) - .withQueryParam("labelSelector", equalTo("spring.cloud.kubernetes.config.informer.enabled=true")) - .willReturn(aResponse().withStatus(200).withBody(JSON.serialize(configMapList)))); - - // 2. second call to informer - V1ConfigMap second = new V1ConfigMap() - .metadata(new V1ObjectMeta().namespace("default") - .name("second") - .labels(Map.of("spring.cloud.kubernetes.config.informer.enabled", "true")) - .resourceVersion("2")) - .data(Map.of("a", "b")); - Watch.Response watchResponse = new Watch.Response<>(ADDED.name(), second); - - stubFor(get(urlMatching(PATH)).withQueryParam("watch", equalTo("true")) - .withQueryParam("resourceVersion", equalTo("1")) - .withQueryParam("labelSelector", equalTo("spring.cloud.kubernetes.config.informer.enabled=true")) - .willReturn(aResponse().withStatus(200).withBody(JSON.serialize(watchResponse)))); - - // 3. all future calls to informer ( any call with resourceVersion >= 2 ) - stubFor(get(urlMatching(PATH)).atPriority(10) - .withQueryParam("watch", equalTo("true")) - .withQueryParam("resourceVersion", WireMock.matching("[2-9][0-9]*")) - .withQueryParam("labelSelector", equalTo("spring.cloud.kubernetes.config.informer.enabled=true")) - .willReturn(aResponse().withStatus(200).withBody(""))); - - // update strategy - ConfigurationUpdateStrategy strategy = new ConfigurationUpdateStrategy("strategy", () -> { - - }); - - // mock environment - KubernetesMockEnvironment environment = new KubernetesMockEnvironment( - mock(KubernetesClientConfigMapPropertySource.class)); - - // change locator - KubernetesClientConfigMapPropertySourceLocator locator = mock( - KubernetesClientConfigMapPropertySourceLocator.class); - when(locator.locate(environment)).thenAnswer(x -> new MockPropertySource()); - - // namespace provider - KubernetesNamespaceProvider namespaceProvider = mock(KubernetesNamespaceProvider.class); - when(namespaceProvider.getNamespace()).thenReturn("default"); - - // properties - boolean enableReloadFiltering = true; - boolean monitorConfigMaps = true; - boolean monitorSecrets = false; - Map configMapsLabels = Map.of(); - Map secretsLabels = Map.of(); - ConfigReloadProperties properties = new ConfigReloadProperties(true, monitorConfigMaps, configMapsLabels, - monitorSecrets, secretsLabels, ConfigReloadProperties.ReloadStrategy.REFRESH, - ConfigReloadProperties.ReloadDetectionMode.EVENT, Duration.ofMillis(15000), Set.of(), - enableReloadFiltering, Duration.ofSeconds(2)); - - // change detector - KubernetesClientEventBasedConfigMapChangeDetector changeDetector = new KubernetesClientEventBasedConfigMapChangeDetector( - coreV1Api, environment, properties, strategy, locator, namespaceProvider); - - changeDetector.inform(); - - // assert that both requests from informer are label based - Awaitilities.awaitUntil(10, 1000, () -> { - try { - - WireMock.verify(WireMock.moreThanOrExactly(1), - getRequestedFor(urlMatching(PATH)).withQueryParam("watch", equalTo("false")) - .withQueryParam("labelSelector", - equalTo("spring.cloud.kubernetes.config.informer.enabled=true"))); - - WireMock.verify(WireMock.moreThanOrExactly(1), - getRequestedFor(urlMatching(PATH)).withQueryParam("watch", equalTo("true")) - .withQueryParam("labelSelector", - equalTo("spring.cloud.kubernetes.config.informer.enabled=true"))); - - WireMock.verify(0, getRequestedFor(urlMatching(PATH)).withQueryParam("watch", equalTo("false")) - .withoutQueryParam("labelSelector")); - - WireMock.verify(0, getRequestedFor(urlMatching(PATH)).withQueryParam("watch", equalTo("true")) - .withoutQueryParam("labelSelector")); - - return true; - } - catch (VerificationException e) { - return false; - } - }); - - changeDetector.shutdown(); - - assertThat(wireMockServer.findAllUnmatchedRequests()).isEmpty(); - - } - -} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/ConfigMapReloadWithLabelsTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/ConfigMapReloadWithLabelsTest.java index bd05a81b72..45e3c6c319 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/ConfigMapReloadWithLabelsTest.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/ConfigMapReloadWithLabelsTest.java @@ -159,7 +159,6 @@ void test() { when(namespaceProvider.getNamespace()).thenReturn("default"); // properties - boolean enableReloadFiltering = false; boolean monitorConfigMaps = true; boolean monitorSecrets = false; Map configMapsLabels = Map.of("only-shape", "round"); @@ -167,7 +166,7 @@ void test() { ConfigReloadProperties properties = new ConfigReloadProperties(true, monitorConfigMaps, configMapsLabels, monitorSecrets, secretsLabels, ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, Duration.ofMillis(15000), Set.of(), - enableReloadFiltering, Duration.ofSeconds(2)); + Duration.ofSeconds(2)); // change detector KubernetesClientEventBasedConfigMapChangeDetector changeDetector = new KubernetesClientEventBasedConfigMapChangeDetector( 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 index e8bbd8fa44..1d958ff9a8 100644 --- 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 @@ -280,9 +280,9 @@ private void changeDetectorAssert() { .thenAnswer(ignoreMe -> new MockPropertySource().withProperty("db-password", "p455w0rd2")); // properties - ConfigReloadProperties properties = new ConfigReloadProperties(false, false, true, + ConfigReloadProperties properties = new ConfigReloadProperties(false, false, Map.of(), true, Map.of(), ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, - Duration.ofMillis(15000), Set.of(), false, Duration.ofSeconds(2)); + Duration.ofMillis(15000), Set.of(), Duration.ofSeconds(2)); // namespace provider KubernetesNamespaceProvider kubernetesNamespaceProvider = mock(KubernetesNamespaceProvider.class); diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/SecretReloadWithFilterTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/SecretReloadWithFilterTest.java deleted file mode 100644 index 2bb9f64bf2..0000000000 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/SecretReloadWithFilterTest.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2012-present 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.List; -import java.util.Map; -import java.util.Set; - -import com.github.tomakehurst.wiremock.WireMockServer; -import com.github.tomakehurst.wiremock.client.VerificationException; -import com.github.tomakehurst.wiremock.client.WireMock; -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 org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.system.OutputCaptureExtension; -import org.springframework.cloud.kubernetes.client.KubernetesClientUtils; -import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySource; -import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; -import org.springframework.cloud.kubernetes.commons.config.reload.ConfigReloadProperties; -import org.springframework.cloud.kubernetes.commons.config.reload.ConfigurationUpdateStrategy; -import org.springframework.cloud.kubernetes.integration.tests.commons.Awaitilities; -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.getRequestedFor; -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 io.kubernetes.client.informer.EventType.ADDED; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.springframework.cloud.kubernetes.client.KubernetesClientUtils.getApplicationNamespace; - -/** - * @author wind57 - */ -@SpringBootTest(properties = { "spring.main.allow-bean-definition-overriding=true" }) -@ExtendWith(OutputCaptureExtension.class) -class SecretReloadWithFilterTest { - - private static WireMockServer wireMockServer; - - private static final String PATH = "^/api/v1/namespaces/default/secrets.*"; - - private static CoreV1Api coreV1Api; - - private static final MockedStatic MOCK_STATIC = Mockito - .mockStatic(KubernetesClientUtils.class); - - @BeforeAll - 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(); - MOCK_STATIC.when(KubernetesClientUtils::createApiClientForInformerClient).thenReturn(client); - MOCK_STATIC.when(() -> getApplicationNamespace(Mockito.nullable(String.class), anyString(), any())) - .thenReturn("default"); - coreV1Api = new CoreV1Api(client); - } - - @AfterAll - static void after() { - MOCK_STATIC.close(); - wireMockServer.stop(); - } - - @Test - void test() { - - V1Secret mySecret = new V1Secret() - .metadata(new V1ObjectMeta().namespace("default") - .name("my-secret") - .labels(Map.of("spring.cloud.kubernetes.config.informer.enabled", "true"))) - .data(Map.of("shape", "round".getBytes())); - - V1SecretList secretList = new V1SecretList().metadata(new V1ListMeta().resourceVersion("1")) - .items(List.of(mySecret)); - - // 1. first call to informer - stubFor(get(urlMatching(PATH)).withQueryParam("watch", equalTo("false")) - .withQueryParam("resourceVersion", equalTo("0")) - .withQueryParam("labelSelector", equalTo("spring.cloud.kubernetes.config.informer.enabled=true")) - .willReturn(aResponse().withStatus(200).withBody(JSON.serialize(secretList)))); - - // 2. second call to informer - V1Secret second = new V1Secret() - .metadata(new V1ObjectMeta().namespace("default") - .name("second") - .labels(Map.of("spring.cloud.kubernetes.config.informer.enabled", "true")) - .resourceVersion("2")) - .data(Map.of("a", "b".getBytes())); - Watch.Response watchResponse = new Watch.Response<>(ADDED.name(), second); - - stubFor(get(urlMatching(PATH)).withQueryParam("watch", equalTo("true")) - .withQueryParam("resourceVersion", equalTo("1")) - .withQueryParam("labelSelector", equalTo("spring.cloud.kubernetes.config.informer.enabled=true")) - .willReturn(aResponse().withStatus(200).withBody(JSON.serialize(watchResponse)))); - - // 3. all future calls to informer ( any call with resourceVersion >= 2 ) - stubFor(get(urlMatching(PATH)).atPriority(10) - .withQueryParam("watch", equalTo("true")) - .withQueryParam("resourceVersion", WireMock.matching("[2-9][0-9]*")) - .withQueryParam("labelSelector", equalTo("spring.cloud.kubernetes.config.informer.enabled=true")) - .willReturn(aResponse().withStatus(200).withBody(""))); - - // update strategy - ConfigurationUpdateStrategy strategy = new ConfigurationUpdateStrategy("strategy", () -> { - - }); - - // mock environment - KubernetesMockEnvironment environment = new KubernetesMockEnvironment( - mock(KubernetesClientSecretsPropertySource.class)); - - // change locator - KubernetesClientSecretsPropertySourceLocator locator = mock(KubernetesClientSecretsPropertySourceLocator.class); - when(locator.locate(environment)).thenAnswer(x -> new MockPropertySource()); - - // namespace provider - KubernetesNamespaceProvider namespaceProvider = mock(KubernetesNamespaceProvider.class); - when(namespaceProvider.getNamespace()).thenReturn("default"); - - // properties - boolean enableReloadFiltering = true; - boolean monitorConfigMaps = false; - boolean monitorSecrets = true; - Map configMapsLabels = Map.of(); - Map secretsLabels = Map.of(); - ConfigReloadProperties properties = new ConfigReloadProperties(true, monitorConfigMaps, configMapsLabels, - monitorSecrets, secretsLabels, ConfigReloadProperties.ReloadStrategy.REFRESH, - ConfigReloadProperties.ReloadDetectionMode.EVENT, Duration.ofMillis(15000), Set.of(), - enableReloadFiltering, Duration.ofSeconds(2)); - - // change detector - KubernetesClientEventBasedSecretsChangeDetector changeDetector = new KubernetesClientEventBasedSecretsChangeDetector( - coreV1Api, environment, properties, strategy, locator, namespaceProvider); - - changeDetector.inform(); - - // assert that both requests from informer are label based - Awaitilities.awaitUntil(10, 1000, () -> { - try { - - WireMock.verify(WireMock.moreThanOrExactly(1), - getRequestedFor(urlMatching(PATH)).withQueryParam("watch", equalTo("false")) - .withQueryParam("labelSelector", - equalTo("spring.cloud.kubernetes.config.informer.enabled=true"))); - - WireMock.verify(WireMock.moreThanOrExactly(1), - getRequestedFor(urlMatching(PATH)).withQueryParam("watch", equalTo("true")) - .withQueryParam("labelSelector", - equalTo("spring.cloud.kubernetes.config.informer.enabled=true"))); - - WireMock.verify(0, getRequestedFor(urlMatching(PATH)).withQueryParam("watch", equalTo("false")) - .withoutQueryParam("labelSelector")); - - WireMock.verify(0, getRequestedFor(urlMatching(PATH)).withQueryParam("watch", equalTo("true")) - .withoutQueryParam("labelSelector")); - - return true; - - } - catch (VerificationException e) { - return false; - } - }); - - changeDetector.shutdown(); - - assertThat(wireMockServer.findAllUnmatchedRequests()).isEmpty(); - - } - -} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/SecretReloadWithLabelsTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/SecretReloadWithLabelsTest.java index d5149fc153..b1876c199a 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/SecretReloadWithLabelsTest.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/SecretReloadWithLabelsTest.java @@ -157,7 +157,6 @@ void test() { when(namespaceProvider.getNamespace()).thenReturn("default"); // properties - boolean enableReloadFiltering = false; boolean monitorConfigMaps = false; boolean monitorSecrets = true; Map configMapsLabels = Map.of(); @@ -165,7 +164,7 @@ void test() { ConfigReloadProperties properties = new ConfigReloadProperties(true, monitorConfigMaps, configMapsLabels, monitorSecrets, secretsLabels, ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, Duration.ofMillis(15000), Set.of(), - enableReloadFiltering, Duration.ofSeconds(2)); + Duration.ofSeconds(2)); // change detector KubernetesClientEventBasedSecretsChangeDetector changeDetector = new KubernetesClientEventBasedSecretsChangeDetector( diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadConfigMapTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadConfigMapTest.java index eb1f25cb0a..c4c3b2e666 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadConfigMapTest.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadConfigMapTest.java @@ -197,9 +197,9 @@ VisibleKubernetesClientEventBasedConfigMapChangeDetector kubernetesClientEventBa @Bean @Primary ConfigReloadProperties configReloadProperties() { - return new ConfigReloadProperties(true, true, false, ConfigReloadProperties.ReloadStrategy.REFRESH, - ConfigReloadProperties.ReloadDetectionMode.POLLING, Duration.ofMillis(2000), Set.of("spring-k8s"), - false, Duration.ofSeconds(2)); + return new ConfigReloadProperties(true, true, Map.of(), false, Map.of(), + ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.POLLING, + Duration.ofMillis(2000), Set.of("spring-k8s"), Duration.ofSeconds(2)); } @Bean diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadSecretTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadSecretTest.java index a4b838206a..137eb32fe3 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadSecretTest.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadSecretTest.java @@ -202,9 +202,9 @@ VisibleKubernetesClientEventBasedSecretsChangeDetector kubernetesClientEventBase @Bean @Primary ConfigReloadProperties configReloadProperties() { - return new ConfigReloadProperties(true, true, false, ConfigReloadProperties.ReloadStrategy.REFRESH, - ConfigReloadProperties.ReloadDetectionMode.POLLING, Duration.ofMillis(2000), Set.of("spring-k8s"), - false, Duration.ofSeconds(2)); + return new ConfigReloadProperties(true, true, Map.of(), false, Map.of(), + ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.POLLING, + Duration.ofMillis(2000), Set.of("spring-k8s"), Duration.ofSeconds(2)); } @Bean diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadConfigMapTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadConfigMapTest.java index 610bb42a36..58f3311a64 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadConfigMapTest.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadConfigMapTest.java @@ -173,9 +173,9 @@ PollingConfigMapChangeDetector pollingConfigMapChangeDetector(AbstractEnvironmen @Bean @Primary ConfigReloadProperties configReloadProperties() { - return new ConfigReloadProperties(true, true, false, ConfigReloadProperties.ReloadStrategy.REFRESH, - ConfigReloadProperties.ReloadDetectionMode.POLLING, Duration.ofMillis(2000), Set.of("non-default"), - false, Duration.ofSeconds(2)); + return new ConfigReloadProperties(true, true, Map.of(), false, Map.of(), + ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.POLLING, + Duration.ofMillis(2000), Set.of("non-default"), Duration.ofSeconds(2)); } @Bean diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadSecretTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadSecretTest.java index d961f02269..9b2401f61f 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadSecretTest.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadSecretTest.java @@ -175,9 +175,9 @@ PollingSecretsChangeDetector pollingSecretsChangeDetector(AbstractEnvironment en @Bean @Primary ConfigReloadProperties configReloadProperties() { - return new ConfigReloadProperties(true, false, true, ConfigReloadProperties.ReloadStrategy.REFRESH, - ConfigReloadProperties.ReloadDetectionMode.POLLING, Duration.ofMillis(2000), Set.of("non-default"), - false, Duration.ofSeconds(2)); + return new ConfigReloadProperties(true, false, Map.of(), true, Map.of(), + ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.POLLING, + Duration.ofMillis(2000), Set.of("non-default"), Duration.ofSeconds(2)); } @Bean diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java index 992218fe7c..c10bcb5079 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java @@ -45,12 +45,11 @@ */ @ConfigurationProperties(prefix = "spring.cloud.kubernetes.reload") public record ConfigReloadProperties(boolean enabled, @DefaultValue("true") boolean monitoringConfigMaps, - @DefaultValue Map configMapsLabels, - boolean monitoringSecrets, @DefaultValue Map secretsLabels, - @DefaultValue("REFRESH") ReloadStrategy strategy, + @DefaultValue Map configMapsLabels, boolean monitoringSecrets, + @DefaultValue Map secretsLabels, @DefaultValue("REFRESH") ReloadStrategy strategy, @DefaultValue("EVENT") ReloadDetectionMode mode, @DefaultValue("15000ms") Duration period, - @DefaultValue Set namespaces, - @DefaultValue("2s") Duration maxWaitForRestart) { + @DefaultValue Set namespaces, @DefaultValue("2s") Duration maxWaitForRestart) { + /** * default instance. */ diff --git a/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/Fabric8EventBasedConfigMapChangeDetector.java b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/Fabric8EventBasedConfigMapChangeDetector.java index 7cd2da0bff..682a85b63c 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/Fabric8EventBasedConfigMapChangeDetector.java +++ b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/Fabric8EventBasedConfigMapChangeDetector.java @@ -66,8 +66,6 @@ public class Fabric8EventBasedConfigMapChangeDetector extends ConfigurationChang private final ConfigurableEnvironment environment; - private final boolean enableReloadFiltering; - private final boolean monitorConfigMaps; private final Map configMapsLabels; @@ -80,7 +78,6 @@ public Fabric8EventBasedConfigMapChangeDetector(AbstractEnvironment environment, this.environment = environment; this.kubernetesClient = kubernetesClient; this.fabric8ConfigMapPropertySourceLocator = fabric8ConfigMapPropertySourceLocator; - this.enableReloadFiltering = properties.enableReloadFiltering(); this.monitorConfigMaps = properties.monitoringConfigMaps(); this.configMapsLabels = properties.configMapsLabels(); namespaces = namespaces(kubernetesClient, namespaceProvider, properties, "configmap"); @@ -92,25 +89,11 @@ private void inform() { LOG.info("Kubernetes event-based configMap change detector activated"); - Map labelSelector; - - if (enableReloadFiltering) { - LOG.warn(() -> "enable reload filtering is deprecated and will be removed in the next major release"); - LOG.warn(() -> "use spring.cloud.kubernetes.reload.config-maps-labels instead"); - if (!configMapsLabels.isEmpty()) { - LOG.warn(() -> "spring.cloud.kubernetes.reload.config-maps-labels is not empty, but " - + "spring.cloud.kubernetes.reload.enable-reload-filtering is enabled and will override the former"); - } - labelSelector = Map.of(ConfigReloadProperties.RELOAD_LABEL_FILTER, "true"); - } - else { - labelSelector = configMapsLabels; - } - namespaces.forEach(namespace -> { SharedIndexInformer informer; - informer = kubernetesClient.configMaps().inNamespace(namespace).withLabels(labelSelector).inform(); - LOG.debug("added configmap informer for namespace : " + namespace + " with labels : " + labelSelector); + informer = kubernetesClient.configMaps().inNamespace(namespace).withLabels(configMapsLabels).inform(); + LOG.debug( + "added configmap informer for namespace : " + namespace + " with labels : " + configMapsLabels); informer.addEventHandler(new ConfigMapInformerAwareEventHandler(informer)); informers.add(informer); diff --git a/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/Fabric8EventBasedSecretsChangeDetector.java b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/Fabric8EventBasedSecretsChangeDetector.java index 95e893118d..dd92996240 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/Fabric8EventBasedSecretsChangeDetector.java +++ b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/reload/Fabric8EventBasedSecretsChangeDetector.java @@ -66,8 +66,6 @@ public class Fabric8EventBasedSecretsChangeDetector extends ConfigurationChangeD private final ConfigurableEnvironment environment; - private final boolean enableReloadFiltering; - private final boolean monitorSecrets; private final Map secretsLabels; @@ -80,7 +78,6 @@ public Fabric8EventBasedSecretsChangeDetector(AbstractEnvironment environment, C this.environment = environment; this.kubernetesClient = kubernetesClient; this.fabric8SecretsPropertySourceLocator = fabric8SecretsPropertySourceLocator; - this.enableReloadFiltering = properties.enableReloadFiltering(); this.monitorSecrets = properties.monitoringSecrets(); secretsLabels = properties.secretsLabels(); namespaces = namespaces(kubernetesClient, namespaceProvider, properties, "secrets"); @@ -100,25 +97,10 @@ private void inform() { LOG.info("Kubernetes event-based secrets change detector activated"); - Map labelSelector; - - if (enableReloadFiltering) { - LOG.warn(() -> "enable reload filtering is deprecated and will be removed in the next major release"); - LOG.warn(() -> "use spring.cloud.kubernetes.secrets-labels instead"); - if (!secretsLabels.isEmpty()) { - LOG.warn(() -> "spring.cloud.kubernetes.reload.secrets-labels is not empty, but " - + "spring.cloud.kubernetes.reload.enable-reload-filtering is enabled and will override the former"); - } - labelSelector = Map.of(ConfigReloadProperties.RELOAD_LABEL_FILTER, "true"); - } - else { - labelSelector = secretsLabels; - } - namespaces.forEach(namespace -> { SharedIndexInformer informer; - informer = kubernetesClient.secrets().inNamespace(namespace).withLabels(labelSelector).inform(); - LOG.debug("added secret informer for namespace : " + namespace + " with labels : " + labelSelector); + informer = kubernetesClient.secrets().inNamespace(namespace).withLabels(secretsLabels).inform(); + LOG.debug("added secret informer for namespace : " + namespace + " with labels : " + secretsLabels); informer.addEventHandler(new SecretInformerAwareEventHandler(informer)); informers.add(informer); diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigUtilsTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigUtilsTests.java index bd0c09fd39..592a68f936 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigUtilsTests.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigUtilsTests.java @@ -17,6 +17,7 @@ package org.springframework.cloud.kubernetes.fabric8.config; import java.time.Duration; +import java.util.Map; import java.util.Set; import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; @@ -35,9 +36,10 @@ class Fabric8ConfigUtilsTests { @Test void testNamespacesFromProperties() { - ConfigReloadProperties configReloadProperties = new ConfigReloadProperties(false, true, false, - ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, - Duration.ofMillis(15000), Set.of("non-default"), false, Duration.ofSeconds(2)); + ConfigReloadProperties configReloadProperties = new ConfigReloadProperties(false, true, Map.of(), false, + Map.of(), ConfigReloadProperties.ReloadStrategy.REFRESH, + ConfigReloadProperties.ReloadDetectionMode.EVENT, Duration.ofMillis(15000), Set.of("non-default"), + Duration.ofSeconds(2)); Set namespaces = Fabric8ConfigUtils.namespaces(null, new KubernetesNamespaceProvider(new MockEnvironment()), configReloadProperties, "configmap"); Assertions.assertThat(namespaces.size()).isEqualTo(1); diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadConfigMapTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadConfigMapTest.java index 0279f5e8b2..6c03398cdb 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadConfigMapTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadConfigMapTest.java @@ -158,9 +158,9 @@ Fabric8EventBasedConfigMapChangeDetector fabric8EventBasedSecretsChangeDetector( @Bean @Primary ConfigReloadProperties configReloadProperties() { - return new ConfigReloadProperties(true, true, false, ConfigReloadProperties.ReloadStrategy.REFRESH, - ConfigReloadProperties.ReloadDetectionMode.EVENT, Duration.ofMillis(2000), Set.of(NAMESPACE), false, - Duration.ofSeconds(2)); + return new ConfigReloadProperties(true, true, Map.of(), false, Map.of(), + ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, + Duration.ofMillis(2000), Set.of(NAMESPACE), Duration.ofSeconds(2)); } @Bean diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadSecretTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadSecretTest.java index 35b77c24ee..8743525e33 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadSecretTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadSecretTest.java @@ -163,9 +163,9 @@ Fabric8EventBasedSecretsChangeDetector fabric8EventBasedSecretsChangeDetector(Ab @Bean @Primary ConfigReloadProperties configReloadProperties() { - return new ConfigReloadProperties(true, true, true, ConfigReloadProperties.ReloadStrategy.REFRESH, - ConfigReloadProperties.ReloadDetectionMode.EVENT, Duration.ofMillis(2000), Set.of(NAMESPACE), false, - Duration.ofSeconds(2)); + return new ConfigReloadProperties(true, true, Map.of(), true, Map.of(), + ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, + Duration.ofMillis(2000), Set.of(NAMESPACE), Duration.ofSeconds(2)); } @Bean diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapAndSecretTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapAndSecretTest.java index 71b53398f7..ef6d628fbb 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapAndSecretTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapAndSecretTest.java @@ -177,9 +177,9 @@ PollingConfigMapChangeDetector pollingConfigMapChangeDetector(AbstractEnvironmen @Bean @Primary ConfigReloadProperties configReloadProperties() { - return new ConfigReloadProperties(true, true, true, ConfigReloadProperties.ReloadStrategy.REFRESH, - ConfigReloadProperties.ReloadDetectionMode.POLLING, Duration.ofMillis(200), Set.of(NAMESPACE), - false, Duration.ofSeconds(2)); + return new ConfigReloadProperties(true, true, Map.of(), true, Map.of(), + ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.POLLING, + Duration.ofMillis(200), Set.of(NAMESPACE), Duration.ofSeconds(2)); } @Bean diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapTest.java index a381e1e810..57b9d8d672 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapTest.java @@ -139,9 +139,9 @@ PollingConfigMapChangeDetector pollingConfigMapChangeDetector(AbstractEnvironmen @Bean @Primary ConfigReloadProperties configReloadProperties() { - return new ConfigReloadProperties(true, true, false, ConfigReloadProperties.ReloadStrategy.REFRESH, - ConfigReloadProperties.ReloadDetectionMode.POLLING, Duration.ofMillis(2000), Set.of("non-default"), - false, Duration.ofSeconds(2)); + return new ConfigReloadProperties(true, true, Map.of(), false, Map.of(), + ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.POLLING, + Duration.ofMillis(2000), Set.of("non-default"), Duration.ofSeconds(2)); } @Bean diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadSecretTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadSecretTest.java index c69754c1df..226c026ef8 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadSecretTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadSecretTest.java @@ -145,9 +145,9 @@ PollingSecretsChangeDetector pollingSecretsChangeDetector(AbstractEnvironment en @Bean @Primary ConfigReloadProperties configReloadProperties() { - return new ConfigReloadProperties(true, true, true, ConfigReloadProperties.ReloadStrategy.REFRESH, - ConfigReloadProperties.ReloadDetectionMode.POLLING, Duration.ofMillis(2000), Set.of("non-default"), - false, Duration.ofSeconds(2)); + return new ConfigReloadProperties(true, true, Map.of(), true, Map.of(), + ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.POLLING, + Duration.ofMillis(2000), Set.of("non-default"), Duration.ofSeconds(2)); } @Bean diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/ConfigMapReloadWithFilterTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/ConfigMapReloadWithFilterTest.java deleted file mode 100644 index 521013d757..0000000000 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/ConfigMapReloadWithFilterTest.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2012-present 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.reload_it.labels; - -import java.time.Duration; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - -import io.fabric8.kubernetes.api.model.ConfigMap; -import io.fabric8.kubernetes.api.model.ConfigMapBuilder; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; -import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties; -import org.springframework.cloud.kubernetes.commons.config.ReadType; -import org.springframework.cloud.kubernetes.commons.config.RetryProperties; -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.VisibleFabric8ConfigMapPropertySourceLocator; -import org.springframework.cloud.kubernetes.fabric8.config.reload.Fabric8EventBasedConfigMapChangeDetector; -import org.springframework.cloud.kubernetes.integration.tests.commons.Awaitilities; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Primary; -import org.springframework.core.env.AbstractEnvironment; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.PropertySource; -import org.springframework.test.context.ContextConfiguration; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author wind57 - */ -@SpringBootTest(properties = { "spring.main.allow-bean-definition-overriding=true" }, - classes = { ConfigMapReloadWithFilterTest.TestConfig.class }) -@ContextConfiguration(initializers = ConfigMapReloadWithFilterTest.Initializer.class) -@EnableKubernetesMockClient(crud = true, https = false) -class ConfigMapReloadWithFilterTest { - - private static KubernetesClient kubernetesClient; - - private static final boolean FAIL_FAST = false; - - private static final String CONFIG_MAP_NAME = "mine"; - - private static final String NAMESPACE = "spring-k8s"; - - private static final AtomicBoolean STRATEGY_CALLED = new AtomicBoolean(false); - - /** - *
-	 *     - we enable reload filtering, via 'spring.cloud.kubernetes.reload.enable-reload-filtering=true'
-	 *       ( this is done in ConfigReloadProperties )
-	 *     - as such, only configmaps that have 'spring.cloud.kubernetes.config.informer.enabled=true'
-	 *       label are being watched. This is what the informer is created with.
-	 * 
- */ - @Test - void test() throws InterruptedException { - ConfigMap configMapOne = configMap(CONFIG_MAP_NAME, Map.of("a", "b"), - Map.of("spring.cloud.kubernetes.config.informer.enabled", "true")); - - kubernetesClient.configMaps().inNamespace(NAMESPACE).resource(configMapOne).create(); - Awaitilities.awaitUntil(10, 1000, STRATEGY_CALLED::get); - kubernetesClient.configMaps().inAnyNamespace().delete(); - Awaitilities.awaitUntil(10, 1000, - () -> kubernetesClient.configMaps().inNamespace(NAMESPACE).withName(CONFIG_MAP_NAME).get() == null); - - // reset the strategy - STRATEGY_CALLED.set(false); - - // create a configMap without label, the informer does not pick it up - configMapOne = configMap(CONFIG_MAP_NAME, Map.of("c", "d"), Map.of()); - kubernetesClient.configMaps().inNamespace(NAMESPACE).resource(configMapOne).create(); - - // wait a bit so that the informer potentially picks it up - Thread.sleep(3_000); - - assertThat(STRATEGY_CALLED.get()).isFalse(); - - } - - private static ConfigMap configMap(String name, Map data, Map labels) { - return new ConfigMapBuilder().withNewMetadata() - .withResourceVersion("1") - .withLabels(labels) - .withName(name) - .endMetadata() - .withData(data) - .build(); - } - - @TestConfiguration - static class TestConfig { - - @Bean - @Primary - Fabric8EventBasedConfigMapChangeDetector fabric8EventBasedSecretsChangeDetector(AbstractEnvironment environment, - ConfigReloadProperties configReloadProperties, ConfigurationUpdateStrategy configurationUpdateStrategy, - Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator, - KubernetesNamespaceProvider namespaceProvider) { - return new Fabric8EventBasedConfigMapChangeDetector(environment, configReloadProperties, kubernetesClient, - configurationUpdateStrategy, fabric8ConfigMapPropertySourceLocator, namespaceProvider); - } - - @Bean - @Primary - ConfigReloadProperties configReloadProperties() { - - boolean monitorConfigMaps = true; - boolean monitorSecrets = false; - boolean enableReloadFiltering = true; - Map configMapsLabels = Map.of(); - Map secretsLabels = Map.of(); - - return new ConfigReloadProperties(true, monitorConfigMaps, configMapsLabels, monitorSecrets, secretsLabels, - ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, - Duration.ofMillis(2000), Set.of(NAMESPACE), enableReloadFiltering, Duration.ofSeconds(2)); - } - - @Bean - @Primary - ConfigMapConfigProperties configMapConfigProperties() { - return new ConfigMapConfigProperties(true, List.of(), Map.of(), CONFIG_MAP_NAME, NAMESPACE, false, true, - FAIL_FAST, RetryProperties.DEFAULT, ReadType.SINGLE); - } - - @Bean - @Primary - KubernetesNamespaceProvider namespaceProvider(AbstractEnvironment environment) { - return new KubernetesNamespaceProvider(environment); - } - - // this is called by reloadProperties() and we simulated that - // informer correctly caught the update for the configmap. - @Bean - @Primary - ConfigurationUpdateStrategy configurationUpdateStrategy() { - return new ConfigurationUpdateStrategy("to-console", () -> STRATEGY_CALLED.set(true)); - } - - @Bean - @Primary - Fabric8ConfigMapPropertySourceLocator fabric8ConfigMapPropertySourceLocator( - ConfigMapConfigProperties configMapConfigProperties, KubernetesNamespaceProvider namespaceProvider) { - return new VisibleFabric8ConfigMapPropertySourceLocator(kubernetesClient, configMapConfigProperties, - namespaceProvider); - } - - } - - /** - * we need a bean of type 'Fabric8ConfigMapPropertySourceLocator' in the context - * ('VisibleFabric8ConfigMapPropertySourceLocator'), otherwise the reload will not - * work. This one is called before the context is refreshed. - */ - static class Initializer implements ApplicationContextInitializer { - - @Override - public void initialize(ConfigurableApplicationContext context) { - ConfigurableEnvironment environment = context.getEnvironment(); - - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), - Map.of(), CONFIG_MAP_NAME, NAMESPACE, false, true, true, RetryProperties.DEFAULT, ReadType.SINGLE); - - KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(environment); - - PropertySource propertySource = new VisibleFabric8ConfigMapPropertySourceLocator(kubernetesClient, - configMapConfigProperties, namespaceProvider) - .locate(environment); - - environment.getPropertySources().addFirst(propertySource); - } - - } - -} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/ConfigMapReloadWithLabelsTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/ConfigMapReloadWithLabelsTest.java index 02e9153536..cc4579cf6d 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/ConfigMapReloadWithLabelsTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/ConfigMapReloadWithLabelsTest.java @@ -128,13 +128,12 @@ ConfigReloadProperties configReloadProperties() { boolean monitorConfigMaps = true; boolean monitorSecrets = false; - boolean enableReloadFiltering = false; Map configMapsLabels = Map.of("only-shape", "round"); Map secretsLabels = Map.of(); return new ConfigReloadProperties(true, monitorConfigMaps, configMapsLabels, monitorSecrets, secretsLabels, ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, - Duration.ofMillis(2000), Set.of(NAMESPACE), enableReloadFiltering, Duration.ofSeconds(2)); + Duration.ofMillis(2000), Set.of(NAMESPACE), Duration.ofSeconds(2)); } @Bean diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/SecretReloadWithFilterTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/SecretReloadWithFilterTest.java deleted file mode 100644 index c6adcb4d65..0000000000 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/SecretReloadWithFilterTest.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright 2012-present 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.reload_it.labels; - -import java.time.Duration; -import java.util.Base64; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Collectors; - -import io.fabric8.kubernetes.api.model.Secret; -import io.fabric8.kubernetes.api.model.SecretBuilder; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; -import org.springframework.cloud.kubernetes.commons.config.ReadType; -import org.springframework.cloud.kubernetes.commons.config.RetryProperties; -import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties; -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.VisibleFabric8SecretsPropertySourceLocator; -import org.springframework.cloud.kubernetes.fabric8.config.reload.Fabric8EventBasedSecretsChangeDetector; -import org.springframework.cloud.kubernetes.integration.tests.commons.Awaitilities; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Primary; -import org.springframework.core.env.AbstractEnvironment; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.PropertySource; -import org.springframework.test.context.ContextConfiguration; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author wind57 - */ -@SpringBootTest(properties = { "spring.main.allow-bean-definition-overriding=true" }, - classes = { SecretReloadWithFilterTest.TestConfig.class }) -@ContextConfiguration(initializers = SecretReloadWithFilterTest.Initializer.class) -@EnableKubernetesMockClient(crud = true, https = false) -class SecretReloadWithFilterTest { - - private static KubernetesClient kubernetesClient; - - private static final boolean FAIL_FAST = false; - - private static final String SECRET_NAME = "mine"; - - private static final String NAMESPACE = "spring-k8s"; - - private static final AtomicBoolean STRATEGY_CALLED = new AtomicBoolean(false); - - /** - *
-	 *     - we enable reload filtering, via 'spring.cloud.kubernetes.reload.enable-reload-filtering=true'
-	 *       ( this is done in ConfigReloadProperties )
-	 *     - as such, only secrets that have 'spring.cloud.kubernetes.config.informer.enabled=true'
-	 *       label are being watched. This is what the informer is created with.
-	 * 
- */ - @Test - void test() throws InterruptedException { - Secret secret = secret(SECRET_NAME, Map.of("a", "b"), - Map.of("spring.cloud.kubernetes.config.informer.enabled", "true")); - - kubernetesClient.secrets().inNamespace(NAMESPACE).resource(secret).create(); - Awaitilities.awaitUntil(10, 1000, STRATEGY_CALLED::get); - kubernetesClient.secrets().inAnyNamespace().delete(); - Awaitilities.awaitUntil(10, 1000, - () -> kubernetesClient.secrets().inNamespace(NAMESPACE).withName(SECRET_NAME).get() == null); - - // reset the strategy - STRATEGY_CALLED.set(false); - - // create a secret without label, the informer does not pick it up - secret = secret(SECRET_NAME, Map.of("c", "d"), Map.of()); - kubernetesClient.secrets().inNamespace(NAMESPACE).resource(secret).create(); - - // wait a bit so that the informer potentially picks it up - Thread.sleep(3_000); - - assertThat(STRATEGY_CALLED.get()).isFalse(); - - } - - private static Secret secret(String name, Map data, Map labels) { - Map encoded = data.entrySet() - .stream() - .collect(Collectors.toMap(Map.Entry::getKey, - e -> new String(Base64.getEncoder().encode(e.getValue().getBytes())))); - return new SecretBuilder().withNewMetadata() - .withLabels(labels) - .withName(name) - .endMetadata() - .withData(encoded) - .build(); - } - - @TestConfiguration - static class TestConfig { - - @Bean - @Primary - Fabric8EventBasedSecretsChangeDetector fabric8EventBasedSecretsChangeDetector(AbstractEnvironment environment, - ConfigReloadProperties configReloadProperties, ConfigurationUpdateStrategy configurationUpdateStrategy, - Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator, - KubernetesNamespaceProvider namespaceProvider) { - return new Fabric8EventBasedSecretsChangeDetector(environment, configReloadProperties, kubernetesClient, - configurationUpdateStrategy, fabric8SecretsPropertySourceLocator, namespaceProvider); - } - - @Bean - @Primary - ConfigReloadProperties configReloadProperties() { - - boolean monitorConfigMaps = false; - boolean monitorSecrets = true; - boolean enableReloadFiltering = true; - Map configMapsLabels = Map.of(); - Map secretsLabels = Map.of(); - - return new ConfigReloadProperties(true, monitorConfigMaps, configMapsLabels, monitorSecrets, secretsLabels, - ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, - Duration.ofMillis(2000), Set.of(NAMESPACE), enableReloadFiltering, Duration.ofSeconds(2)); - } - - @Bean - @Primary - SecretsConfigProperties secretsConfigProperties() { - return new SecretsConfigProperties(true, List.of(), Map.of(), SECRET_NAME, NAMESPACE, false, true, - FAIL_FAST, RetryProperties.DEFAULT, ReadType.SINGLE); - } - - @Bean - @Primary - KubernetesNamespaceProvider namespaceProvider(AbstractEnvironment environment) { - return new KubernetesNamespaceProvider(environment); - } - - @Bean - @Primary - ConfigurationUpdateStrategy configurationUpdateStrategy() { - return new ConfigurationUpdateStrategy("to-console", () -> STRATEGY_CALLED.set(true)); - } - - @Bean - @Primary - Fabric8SecretsPropertySourceLocator fabric8SecretsPropertySourceLocator( - SecretsConfigProperties secretsConfigProperties, KubernetesNamespaceProvider namespaceProvider) { - return new VisibleFabric8SecretsPropertySourceLocator(kubernetesClient, secretsConfigProperties, - namespaceProvider); - } - - } - - /** - * This one is called before the context is refreshed. - */ - static class Initializer implements ApplicationContextInitializer { - - @Override - public void initialize(ConfigurableApplicationContext context) { - ConfigurableEnvironment environment = context.getEnvironment(); - - // simulate that environment already has a Fabric8SecretsPropertySource, - // otherwise we can't properly test reload functionality - SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, List.of(), Map.of(), - SECRET_NAME, NAMESPACE, false, true, true, RetryProperties.DEFAULT, ReadType.BATCH); - KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(environment); - - PropertySource propertySource = new VisibleFabric8SecretsPropertySourceLocator(kubernetesClient, - secretsConfigProperties, namespaceProvider) - .locate(environment); - - environment.getPropertySources().addFirst(propertySource); - } - - } - -} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/SecretReloadWithLabelsTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/SecretReloadWithLabelsTest.java index adb15ec121..21ef184b25 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/SecretReloadWithLabelsTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/SecretReloadWithLabelsTest.java @@ -133,13 +133,12 @@ ConfigReloadProperties configReloadProperties() { boolean monitorConfigMaps = false; boolean monitorSecrets = true; - boolean enableReloadFiltering = false; Map configMapsLabels = Map.of(); Map secretsLabels = Map.of("only-shape", "round"); return new ConfigReloadProperties(true, monitorConfigMaps, configMapsLabels, monitorSecrets, secretsLabels, ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, - Duration.ofMillis(2000), Set.of(NAMESPACE), enableReloadFiltering, Duration.ofSeconds(2)); + Duration.ofMillis(2000), Set.of(NAMESPACE), Duration.ofSeconds(2)); } @Bean diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-three.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-three.yaml index 72f6a44c1e..e94a919948 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-three.yaml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-three.yaml @@ -10,4 +10,5 @@ spring: namespaces: - right monitoring-config-maps: true - enable-reload-filtering: true + config-maps-labels: + spring.cloud.kubernetes.config.informer.enabled : "true" diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-three.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-three.yaml index 72f6a44c1e..e94a919948 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-three.yaml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-three.yaml @@ -10,4 +10,5 @@ spring: namespaces: - right monitoring-config-maps: true - enable-reload-filtering: true + config-maps-labels: + spring.cloud.kubernetes.config.informer.enabled : "true" From 5cb5fd1aa75d0ea7cc996cba5c048e4ec4042ae2 Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 17 Apr 2026 16:58:56 +0300 Subject: [PATCH 3/9] fix test Signed-off-by: wind57 --- .../client/reload/it/K8sClientConfigMapEventTriggeredIT.java | 4 ++-- .../reload/it/K8sClientConfigMapLabelEventTriggeredIT.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientConfigMapEventTriggeredIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientConfigMapEventTriggeredIT.java index b44cc34cb8..4d8a1a8673 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientConfigMapEventTriggeredIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientConfigMapEventTriggeredIT.java @@ -99,8 +99,8 @@ static void afterAllLocal() { @Test void test(CapturedOutput output) { - assertReloadLogStatements("added configmap informer for namespace : right with labels : {}", - "added secret informer for namespace", output); + assertReloadLogStatements("configmap informer for namespace : right with labels : {}", + "secret informer for namespace", output); Assertions.assertThat(rightProperties.getValue()).isEqualTo("right-initial"); diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientConfigMapLabelEventTriggeredIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientConfigMapLabelEventTriggeredIT.java index 1414b5c886..2bdef4662f 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientConfigMapLabelEventTriggeredIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientConfigMapLabelEventTriggeredIT.java @@ -106,9 +106,9 @@ static void afterAllLocal() { void test(CapturedOutput output) { assertReloadLogStatements( - "added configmap informer for namespace : " + "configmap informer for namespace : " + "right with labels : {spring.cloud.kubernetes.config.informer.enabled=true}", - "added secret informer for namespace", output); + "secret informer for namespace", output); // read the initial value from the right-configmap Assertions.assertThat(rightProperties.getValue()).isEqualTo("right-initial"); From d229922af5f54126bf1b3caa47780f57f65943ab Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 22 May 2026 20:30:54 +0300 Subject: [PATCH 4/9] trigger Signed-off-by: wind57 From da81f9359a79d7247777001fd0f5de459e6f6fbb Mon Sep 17 00:00:00 2001 From: wind57 Date: Sat, 23 May 2026 09:47:03 +0300 Subject: [PATCH 5/9] trigger Signed-off-by: wind57 From 234e2128ed921aebf914a94fae7870a2ec8bc751 Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 7 Jul 2026 10:28:44 +0300 Subject: [PATCH 6/9] drop all labels and update the doc Signed-off-by: wind57 --- ...loud-kubernetes-configuration-watcher.adoc | 44 ++++++--------- .../watcher/ConfigMapKubernetesSource.java | 5 -- ...urationWatcherConfigurationProperties.java | 24 --------- .../watcher/KubernetesSource.java | 2 - .../watcher/SecretKubernetesSource.java | 5 -- .../configuration/watcher/WatcherUtil.java | 8 --- .../KubernetesSourceProviderTests.java | 3 -- .../watcher/WatcherUtilTests.java | 54 ------------------- 8 files changed, 15 insertions(+), 130 deletions(-) delete mode 100644 spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/WatcherUtilTests.java diff --git a/docs/modules/ROOT/pages/spring-cloud-kubernetes-configuration-watcher.adoc b/docs/modules/ROOT/pages/spring-cloud-kubernetes-configuration-watcher.adoc index 692334e138..0c5fc83e95 100644 --- a/docs/modules/ROOT/pages/spring-cloud-kubernetes-configuration-watcher.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-kubernetes-configuration-watcher.adoc @@ -36,49 +36,39 @@ env: value: "namespace-a" ---- -This one lets watcher know where to search for secrets and configmaps. You have two options here: selective namespaces (the setting above) and a namespace chosen by xref:property-source-config.adoc#namespace-resolution[Namespace Resolution] (this is the default option). +This tells the watcher where to search for Secrets and ConfigMaps. You have two options here: selective namespaces (the setting above) and a namespace chosen by xref:property-source-config.adoc#namespace-resolution[Namespace Resolution] (this is the default option). Keep in mind that all these options require proper RBAC rules. -<<<<<<< HEAD -Changes from configmaps/secrets will only trigger an event being fired from configuration watcher if that particular change came from a source that has a label: `spring.cloud.kubernetes.config=true` or `spring.cloud.kubernetes.secret=true`. - -To put it simpler, if you change a configmap (or secret), that does _not_ have the label above, configuration watcher will skip firing an event for it (if you enabled debug logging, this will be visible in logs). - -By default, configuration watcher will monitor all configmaps/secrets in the configured namespace(s). If you want to watch only particular sources, you can do that by choosing only sources with some labels: +Configuration Watcher can monitor ConfigMaps and Secrets in the configured namespace(s). If you want it to react only to particular sources, configure label filters for the watched resources: [source] ---- spring.cloud.kubernetes.reload.config-maps-labels[a]=b -======= -By default, Configuration Watcher monitors only ConfigMaps labeled: - -[source] ----- -spring.cloud.kubernetes.config: "true" +spring.cloud.kubernetes.reload.secrets-labels[x]=y ---- -Secrets are not monitored by default. To enable Secret monitoring, set: +or via environment variables in the watcher deployment: [source,yaml] ---- env: - - name: SPRING_CLOUD_KUBERNETES_SECRETS_ENABLED - value: "TRUE" + - name: SPRING_CLOUD_KUBERNETES_RELOAD_CONFIG_MAPS_LABELS_A + value: "b" + - name: SPRING_CLOUD_KUBERNETES_RELOAD_SECRETS_LABELS_X + value: "y" ---- +When such filters are configured, only ConfigMaps or Secrets matching those labels will trigger a refresh event. -or via environment variables in the watcher Deployment: +Secrets are not monitored by default. To enable Secret monitoring, set: [source,yaml] ---- env: - - name: SPRING_CLOUD_KUBERNETES_RELOAD_CONFIG_MAPS_LABELS_MY_CONFIGMAP_LABEL - value: "my-configmap-value" - - name: SPRING_CLOUD_KUBERNETES_RELOAD_SECRETS_LABELS_MY_SECRET_LABEL - value: "my-secret-value" + - name: SPRING_CLOUD_KUBERNETES_SECRETS_ENABLED + value: "TRUE" ---- - One more important configuration, especially for configmaps and secrets that are mounted as volumes (via `spring.config.import`) is: [source] @@ -87,7 +77,7 @@ One more important configuration, especially for configmaps and secrets that are value: "10000" ---- -This tells how many milliseconds should we wait before firing the event from configuration watcher. This is important because kubernetes documentation says: +This tells the watcher how many milliseconds to wait before firing the refresh event. This is important because Kubernetes documentation says: > When a ConfigMap currently consumed in a volume is updated, projected keys are eventually updated as well. @@ -186,13 +176,13 @@ The controller needs access to read data about ConfigMaps, Pods, Services, Endpo ## Monitoring ConfigMaps and Secrets -If a change is made to a ConfigMap or Secret with valid labels (as detailed above), then Spring Cloud Kubernetes Configuration Watcher will take the name of the ConfigMap or Secret +If a change is made to a ConfigMap or Secret that matches the configured watcher labels, then Spring Cloud Kubernetes Configuration Watcher will take the name of the ConfigMap or Secret and send a notification to the application with that name. This might not be enough for your use-case though, you could for example want to: - bind a config-map to multiple applications, so that a change inside a single configmap triggers a refresh for many services - have profile based sources trigger events for your application -For that reasons there is an addition annotation you could specify: +For those cases there are additional annotations you can specify: `spring.cloud.kubernetes.configmap.apps` or `spring.cloud.kubernetes.secret.apps`. It takes a String of apps separated by comma, that specifies the names of applications that will receive a notification when changes happen in this secret/configmap. @@ -205,8 +195,6 @@ kind: ConfigMap apiVersion: v1 metadata: name: example-configmap - labels: - spring.cloud.kubernetes.config: "true" annotations: spring.cloud.kubernetes.configmap.apps: "app-a, app-b" ---- @@ -234,8 +222,6 @@ kind: ConfigMap apiVersion: v1 metadata: name: example-configmap - labels: - spring.cloud.kubernetes.config: "true" annotations: spring.cloud.kubernetes.configmap.labels: "app=demo,tier=backend" ---- diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigMapKubernetesSource.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigMapKubernetesSource.java index 49d4c7e28e..0694d036d3 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigMapKubernetesSource.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigMapKubernetesSource.java @@ -34,11 +34,6 @@ public String description() { return "configmap"; } - @Override - public String requiredResourceLabel() { - return ConfigurationWatcherConfigurationProperties.CONFIG_MAP_LABEL; - } - @Override public String toString() { return "ConfigMapKubernetesSource{" + "resourceName='" + resourceName + '\'' + ", serviceNames=" + serviceNames diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherConfigurationProperties.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherConfigurationProperties.java index b261ea28d2..928303335d 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherConfigurationProperties.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherConfigurationProperties.java @@ -43,30 +43,6 @@ public class ConfigurationWatcherConfigurationProperties { */ static final String NOT_AMQP_NOT_KAFKA = "!" + AMQP + " & !" + KAFKA; - /** - * label to enable refresh/restart when using configmaps. - */ - @Deprecated(forRemoval = true) - public static final String CONFIG_MAP_LABEL = "spring.cloud.kubernetes.config"; - - /** - * label to enable refresh/restart when using secrets. - */ - @Deprecated(forRemoval = true) - public static final String SECRET_LABEL = "spring.cloud.kubernetes.secret"; - - /** - * annotation name to enable refresh/restart for specific apps when using configmaps. - */ - @Deprecated(forRemoval = true) - public static final String CONFIG_MAP_APPS_ANNOTATION = "spring.cloud.kubernetes.configmap.apps"; - - /** - * annotation name to enable refresh/restart for specific apps when using secrets. - */ - @Deprecated(forRemoval = true) - public static final String SECRET_APPS_ANNOTATION = "spring.cloud.kubernetes.secret.apps"; - /** * Annotation key for actuator port and path. */ diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSource.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSource.java index 65138b10b3..d7fb6fe151 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSource.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSource.java @@ -34,8 +34,6 @@ sealed interface KubernetesSource permits ConfigMapKubernetesSource, SecretKuber String description(); - String requiredResourceLabel(); - Set serviceNames(); Map serviceLabels(); diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/SecretKubernetesSource.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/SecretKubernetesSource.java index be0f56a8e6..71f5067839 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/SecretKubernetesSource.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/SecretKubernetesSource.java @@ -34,11 +34,6 @@ public String description() { return "secret"; } - @Override - public String requiredResourceLabel() { - return ConfigurationWatcherConfigurationProperties.SECRET_LABEL; - } - @Override public String toString() { return "SecretKubernetesSource{" + "resourceName='" + resourceName + '\'' + ", serviceNames=" + serviceNames diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/WatcherUtil.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/WatcherUtil.java index e4d8c83245..7456550e0c 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/WatcherUtil.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/WatcherUtil.java @@ -47,14 +47,6 @@ static void onEvent(KubernetesObject kubernetesObject, long refreshDelay, Schedu Function> triggerRefresh) { KubernetesSource kubernetesSource = kubernetesSource(kubernetesObject); - String name = kubernetesObject.getMetadata().getName(); - String label = kubernetesSource.requiredResourceLabel(); - - if (!isSpringCloudKubernetes(kubernetesObject, label)) { - LOG.debug(() -> "Not publishing event : " + kubernetesSource.description() + ": " + name - + " does not contain the label " + label); - return; - } // we need defer, because otherwise triggerRefresh.apply(kubernetesSource) is // called when the pipeline is being built, not when it's run. diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProviderTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProviderTests.java index b386dcfe8f..f599b09c76 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProviderTests.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProviderTests.java @@ -165,8 +165,6 @@ void kubernetesSourceForConfigMap() { assertThat(source).isInstanceOf(ConfigMapKubernetesSource.class); assertThat(source.description()).isEqualTo("configmap"); - assertThat(source.requiredResourceLabel()) - .isEqualTo(ConfigurationWatcherConfigurationProperties.CONFIG_MAP_LABEL); assertThat(source.serviceNames()).containsExactlyInAnyOrder("app-one", "app-two"); assertThat(source.serviceLabels()) .containsExactlyInAnyOrderEntriesOf(Map.of("app", "my-app", "tier", "backend")); @@ -185,7 +183,6 @@ void kubernetesSourceForSecret() { assertThat(source).isInstanceOf(SecretKubernetesSource.class); assertThat(source.description()).isEqualTo("secret"); - assertThat(source.requiredResourceLabel()).isEqualTo(ConfigurationWatcherConfigurationProperties.SECRET_LABEL); assertThat(source.serviceNames()).containsExactlyInAnyOrder("app-one", "app-two"); assertThat(source.serviceLabels()) .containsExactlyInAnyOrderEntriesOf(Map.of("app", "my-app", "tier", "backend")); diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/WatcherUtilTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/WatcherUtilTests.java deleted file mode 100644 index 711d8ce022..0000000000 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/WatcherUtilTests.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2013-present 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.configuration.watcher; - -import java.util.Map; - -import io.kubernetes.client.openapi.models.V1ConfigMap; -import io.kubernetes.client.openapi.models.V1ConfigMapBuilder; -import io.kubernetes.client.openapi.models.V1ObjectMeta; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class WatcherUtilTests { - - @Test - void configMapWithRequiredLabelIsAccepted() { - V1ConfigMap configMap = configMap(Map.of(ConfigurationWatcherConfigurationProperties.CONFIG_MAP_LABEL, "true")); - - boolean accepted = WatcherUtil.isSpringCloudKubernetes(configMap, - ConfigurationWatcherConfigurationProperties.CONFIG_MAP_LABEL); - - assertThat(accepted).isTrue(); - } - - @Test - void configMapWithoutRequiredLabelIsRejected() { - V1ConfigMap configMap = configMap(Map.of()); - - boolean accepted = WatcherUtil.isSpringCloudKubernetes(configMap, - ConfigurationWatcherConfigurationProperties.CONFIG_MAP_LABEL); - - assertThat(accepted).isFalse(); - } - - private static V1ConfigMap configMap(Map labels) { - return new V1ConfigMapBuilder().withMetadata(new V1ObjectMeta().name("my-configmap").labels(labels)).build(); - } - -} From 51fc24d87a03243ff05f193c9001eeee421e0f6a Mon Sep 17 00:00:00 2001 From: wind57 Date: Sat, 11 Jul 2026 09:58:29 +0300 Subject: [PATCH 7/9] before more tests Signed-off-by: wind57 --- .../config/reload/ConfigReloadProperties.java | 10 ++++- .../config/ConfigReloadPropertiesTests.java | 9 +++- .../ConfigMapWatcherChangeDetector.java | 7 ++- .../watcher/KubernetesSourceProvider.java | 19 ++++++-- .../watcher/SecretsWatcherChangeDetector.java | 7 ++- .../configuration/watcher/WatcherUtil.java | 14 ++---- .../watcher/HttpRefreshTriggerTests.java | 5 ++- .../KubernetesSourceProviderTests.java | 43 +++++++++++++++---- 8 files changed, 83 insertions(+), 31 deletions(-) diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java index 1d1ad56b6c..3229f0391b 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java @@ -17,6 +17,7 @@ package org.springframework.cloud.kubernetes.commons.config.reload; import java.time.Duration; +import java.util.List; import java.util.Map; import java.util.Set; @@ -41,6 +42,10 @@ * avoid having all instances of the same application restart at the same time. This * property configures the maximum of amount of wait time from the moment the signal is * received that a restart is needed until the moment the restart is actually triggered + * @param configMapsApps Applications to refresh when a watched ConfigMap changes. Takes + * precedence over the {@code spring.cloud.kubernetes.configmap.apps} annotation. + * @param secretsApps Applications to refresh when a watched Secret changes. Takes + * precedence over the {@code spring.cloud.kubernetes.secret.apps} annotation. * @author Nicola Ferraro */ @ConfigurationProperties(prefix = "spring.cloud.kubernetes.reload") @@ -48,14 +53,15 @@ public record ConfigReloadProperties(boolean enabled, @DefaultValue("true") bool @DefaultValue Map configMapsLabels, boolean monitoringSecrets, @DefaultValue Map secretsLabels, @DefaultValue("REFRESH") ReloadStrategy strategy, @DefaultValue("EVENT") ReloadDetectionMode mode, @DefaultValue("15000ms") Duration period, - @DefaultValue Set namespaces, @DefaultValue("2s") Duration maxWaitForRestart) { + @DefaultValue Set namespaces, @DefaultValue("2s") Duration maxWaitForRestart, + @DefaultValue List configMapsApps, @DefaultValue List secretsApps) { /** * default instance. */ public static final ConfigReloadProperties DEFAULT = new ConfigReloadProperties(false, true, Map.of(), false, Map.of(), ReloadStrategy.REFRESH, ReloadDetectionMode.EVENT, Duration.ofMillis(15000), Set.of(), - Duration.ofSeconds(2)); + Duration.ofSeconds(2), List.of(), List.of()); /** * Reload strategies. diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigReloadPropertiesTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigReloadPropertiesTests.java index 3de0fdeae8..c0baedac67 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigReloadPropertiesTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigReloadPropertiesTests.java @@ -48,6 +48,8 @@ void testDefaults() { assertThat(Duration.ofMillis(15000)).isEqualTo(properties.period()); assertThat(properties.namespaces().isEmpty()).isTrue(); assertThat(Duration.ofSeconds(2)).isEqualTo(properties.maxWaitForRestart()); + assertThat(properties.configMapsApps()).isEmpty(); + assertThat(properties.secretsApps()).isEmpty(); }); } @@ -62,7 +64,10 @@ void testNonDefaults() { "spring.cloud.kubernetes.reload.strategy=SHUTDOWN", "spring.cloud.kubernetes.reload.mode=POLLING", "spring.cloud.kubernetes.reload.period=1000ms", "spring.cloud.kubernetes.reload.namespaces[0]=a", "spring.cloud.kubernetes.reload.namespaces[1]=b", - "spring.cloud.kubernetes.reload.max-wait-for-restart=5s") + "spring.cloud.kubernetes.reload.max-wait-for-restart=5s", + "spring.cloud.kubernetes.reload.config-maps-apps[0]=app-one", + "spring.cloud.kubernetes.reload.config-maps-apps[1]=app-two", + "spring.cloud.kubernetes.reload.secrets-apps[0]=app-three") .run(context -> { ConfigReloadProperties properties = context.getBean(ConfigReloadProperties.class); assertThat(properties).isNotNull(); @@ -76,6 +81,8 @@ void testNonDefaults() { assertThat(Duration.ofMillis(1000)).isEqualTo(properties.period()); assertThat(properties.namespaces()).containsExactlyInAnyOrder("a", "b"); assertThat(Duration.ofSeconds(5)).isEqualTo(properties.maxWaitForRestart()); + assertThat(properties.configMapsApps()).containsExactly("app-one", "app-two"); + assertThat(properties.secretsApps()).containsExactly("app-three"); }); } 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 5e0176d36d..c19095a982 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 @@ -41,6 +41,8 @@ abstract sealed class ConfigMapWatcherChangeDetector extends KubernetesClientEve private final Scheduler scheduler; + private final ConfigReloadProperties reloadProperties; + /** *
 	 * Read refreshDelay from the properties bean when handling an event instead of
@@ -67,13 +69,14 @@ abstract sealed class ConfigMapWatcherChangeDetector extends KubernetesClientEve
 		super(coreV1Api, environment, properties, strategy, propertySourceLocator, kubernetesNamespaceProvider);
 		scheduler = Schedulers.fromExecutor(
 				newScheduledThreadPool(k8SConfigurationProperties.getThreadPoolSize(), threadPoolTaskExecutor));
+		this.reloadProperties = properties;
 		this.k8SConfigurationProperties = k8SConfigurationProperties;
 	}
 
 	@Override
 	protected final void onEvent(KubernetesObject configMap) {
-		WatcherUtil.onEvent(configMap, k8SConfigurationProperties.getRefreshDelay().toMillis(), scheduler,
-				this::triggerRefresh);
+		WatcherUtil.onEvent(configMap, reloadProperties.configMapsApps(),
+				k8SConfigurationProperties.getRefreshDelay().toMillis(), scheduler, this::triggerRefresh);
 	}
 
 }
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProvider.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProvider.java
index c404d26644..b98fb3f5ae 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProvider.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProvider.java
@@ -17,6 +17,7 @@
 package org.springframework.cloud.kubernetes.configuration.watcher;
 
 import java.util.Arrays;
+import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
@@ -56,15 +57,16 @@ private KubernetesSourceProvider() {
 
 	}
 
-	static KubernetesSource kubernetesSource(KubernetesObject kubernetesObject) {
+	static KubernetesSource kubernetesSource(KubernetesObject kubernetesObject, List configuredApps) {
 
 		if (kubernetesObject instanceof V1ConfigMap v1ConfigMap) {
-			Set serviceNames = serviceNames(kubernetesObject, CONFIGMAP_SERVICE_NAMES_ANNOTATION);
+			Set serviceNames = serviceNames(kubernetesObject, CONFIGMAP_SERVICE_NAMES_ANNOTATION,
+					configuredApps);
 			Map serviceLabels = serviceLabels(kubernetesObject, CONFIGMAP_SERVICE_LABELS_ANNOTATION);
 			return new ConfigMapKubernetesSource(serviceNames, serviceLabels, v1ConfigMap.getMetadata().getName());
 		}
 		if (kubernetesObject instanceof V1Secret v1Secret) {
-			Set serviceNames = serviceNames(kubernetesObject, SECRET_SERVICE_NAMES_ANNOTATION);
+			Set serviceNames = serviceNames(kubernetesObject, SECRET_SERVICE_NAMES_ANNOTATION, configuredApps);
 			Map serviceLabels = serviceLabels(kubernetesObject, SECRET_SERVICE_LABELS_ANNOTATION);
 			return new SecretKubernetesSource(serviceNames, serviceLabels, v1Secret.getMetadata().getName());
 		}
@@ -117,10 +119,19 @@ static Map serviceLabels(KubernetesObject kubernetesObject, Stri
 	 * example {@code app-one,app-two}.
 	 *
 	 * 

+ * When configured apps are present, they take precedence over the annotation. + * + *

* If the annotation is not present or contains only blanks, the Kubernetes resource * name ({@code .metadata.name}) is used as the default target. */ - static Set serviceNames(KubernetesObject kubernetesObject, String annotationName) { + static Set serviceNames(KubernetesObject kubernetesObject, String annotationName, + List configuredApps) { + + if (!configuredApps.isEmpty()) { + LOG.debug(() -> "using configured apps instead of " + annotationName + " : " + configuredApps); + return Set.copyOf(configuredApps); + } String metadataName = kubernetesObject.getMetadata().getName(); Map annotations = annotations(kubernetesObject); 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 fa4bcad950..607d0f1fd7 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 @@ -40,6 +40,8 @@ abstract sealed class SecretsWatcherChangeDetector extends KubernetesClientEvent private final Scheduler scheduler; + private final ConfigReloadProperties reloadProperties; + /** *

 	 * Read refreshDelay from the properties bean when handling an event instead of
@@ -66,13 +68,14 @@ abstract sealed class SecretsWatcherChangeDetector extends KubernetesClientEvent
 		super(coreV1Api, environment, properties, strategy, propertySourceLocator, kubernetesNamespaceProvider);
 		scheduler = Schedulers.fromExecutor(
 				newScheduledThreadPool(k8SConfigurationProperties.getThreadPoolSize(), threadPoolTaskExecutor));
+		this.reloadProperties = properties;
 		this.k8SConfigurationProperties = k8SConfigurationProperties;
 	}
 
 	@Override
 	protected final void onEvent(KubernetesObject secret) {
-		WatcherUtil.onEvent(secret, k8SConfigurationProperties.getRefreshDelay().toMillis(), scheduler,
-				this::triggerRefresh);
+		WatcherUtil.onEvent(secret, reloadProperties.secretsApps(),
+				k8SConfigurationProperties.getRefreshDelay().toMillis(), scheduler, this::triggerRefresh);
 	}
 
 }
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/WatcherUtil.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/WatcherUtil.java
index 7456550e0c..c5fde2d672 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/WatcherUtil.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/WatcherUtil.java
@@ -17,6 +17,7 @@
 package org.springframework.cloud.kubernetes.configuration.watcher;
 
 import java.time.Duration;
+import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.function.Function;
@@ -43,10 +44,10 @@ final class WatcherUtil {
 	private WatcherUtil() {
 	}
 
-	static void onEvent(KubernetesObject kubernetesObject, long refreshDelay, Scheduler scheduler,
-			Function> triggerRefresh) {
+	static void onEvent(KubernetesObject kubernetesObject, List configuredApps, long refreshDelay,
+			Scheduler scheduler, Function> triggerRefresh) {
 
-		KubernetesSource kubernetesSource = kubernetesSource(kubernetesObject);
+		KubernetesSource kubernetesSource = kubernetesSource(kubernetesObject, configuredApps);
 
 		// we need defer, because otherwise triggerRefresh.apply(kubernetesSource) is
 		// called when the pipeline is being built, not when it's run.
@@ -57,13 +58,6 @@ static void onEvent(KubernetesObject kubernetesObject, long refreshDelay, Schedu
 			.subscribe();
 	}
 
-	static boolean isSpringCloudKubernetes(KubernetesObject kubernetesObject, String label) {
-		if (kubernetesObject.getMetadata() == null) {
-			return false;
-		}
-		return Boolean.parseBoolean(labels(kubernetesObject).getOrDefault(label, "false"));
-	}
-
 	static boolean matchesByLabels(ServiceInstance serviceInstance, Map inputLabels) {
 		Map metadata = serviceInstance.getMetadata();
 
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpRefreshTriggerTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpRefreshTriggerTests.java
index 00d93f3c7c..73e4d07701 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpRefreshTriggerTests.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpRefreshTriggerTests.java
@@ -17,6 +17,7 @@
 package org.springframework.cloud.kubernetes.configuration.watcher;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -182,7 +183,7 @@ void refreshesServiceInstancesByMetadataNameWhenServiceNamesAnnotationMissing()
 		V1ConfigMap configMap = new V1ConfigMapBuilder().withMetadata(new V1ObjectMeta().name("service-wiremock"))
 			.build();
 
-		KubernetesSource source = KubernetesSourceProvider.kubernetesSource(configMap);
+		KubernetesSource source = KubernetesSourceProvider.kubernetesSource(configMap, List.of());
 
 		StepVerifier.create(refreshTrigger.triggerRefresh(source)).verifyComplete();
 
@@ -226,7 +227,7 @@ void refreshesServiceInstancesByMetadataLabelsWhenServiceLabelsAnnotationPresent
 								"app=demo,tier=backend")))
 			.build();
 
-		KubernetesSource source = KubernetesSourceProvider.kubernetesSource(configMap);
+		KubernetesSource source = KubernetesSourceProvider.kubernetesSource(configMap, List.of());
 
 		StepVerifier.create(refreshTrigger.triggerRefresh(source)).verifyComplete();
 
diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProviderTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProviderTests.java
index f599b09c76..f961ff2e00 100644
--- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProviderTests.java
+++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProviderTests.java
@@ -16,6 +16,7 @@
 
 package org.springframework.cloud.kubernetes.configuration.watcher;
 
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -38,7 +39,7 @@ void serviceNamesFallsBackToMetadataNameWhenAnnotationsMissing() {
 		V1Secret secret = new V1SecretBuilder().withMetadata(new V1ObjectMeta().name("my-secret")).build();
 
 		Set serviceNames = KubernetesSourceProvider.serviceNames(secret,
-				SecretKubernetesSource.SECRET_SERVICE_NAMES_ANNOTATION);
+				SecretKubernetesSource.SECRET_SERVICE_NAMES_ANNOTATION, List.of());
 
 		assertThat(serviceNames).containsExactly("my-secret");
 	}
@@ -50,7 +51,7 @@ void serviceNamesFallsBackToMetadataNameWhenAnnotationMissing() {
 			.build();
 
 		Set serviceNames = KubernetesSourceProvider.serviceNames(secret,
-				SecretKubernetesSource.SECRET_SERVICE_NAMES_ANNOTATION);
+				SecretKubernetesSource.SECRET_SERVICE_NAMES_ANNOTATION, List.of());
 
 		assertThat(serviceNames).containsExactly("my-secret");
 	}
@@ -63,7 +64,7 @@ void serviceNamesFallsBackToMetadataNameWhenAnnotationBlank() {
 			.build();
 
 		Set serviceNames = KubernetesSourceProvider.serviceNames(secret,
-				SecretKubernetesSource.SECRET_SERVICE_NAMES_ANNOTATION);
+				SecretKubernetesSource.SECRET_SERVICE_NAMES_ANNOTATION, List.of());
 
 		assertThat(serviceNames).containsExactly("my-secret");
 	}
@@ -76,7 +77,7 @@ void serviceNamesSingleValue() {
 			.build();
 
 		Set serviceNames = KubernetesSourceProvider.serviceNames(secret,
-				SecretKubernetesSource.SECRET_SERVICE_NAMES_ANNOTATION);
+				SecretKubernetesSource.SECRET_SERVICE_NAMES_ANNOTATION, List.of());
 
 		assertThat(serviceNames).containsExactly("one-app");
 	}
@@ -89,7 +90,7 @@ void serviceNamesMultipleValuesTrimmed() {
 			.build();
 
 		Set serviceNames = KubernetesSourceProvider.serviceNames(secret,
-				SecretKubernetesSource.SECRET_SERVICE_NAMES_ANNOTATION);
+				SecretKubernetesSource.SECRET_SERVICE_NAMES_ANNOTATION, List.of());
 
 		assertThat(serviceNames).containsExactlyInAnyOrder("one", "two", "three");
 	}
@@ -161,7 +162,7 @@ void kubernetesSourceForConfigMap() {
 						ConfigMapKubernetesSource.CONFIGMAP_SERVICE_LABELS_ANNOTATION, "app=my-app,tier=backend")))
 			.build();
 
-		KubernetesSource source = KubernetesSourceProvider.kubernetesSource(configMap);
+		KubernetesSource source = KubernetesSourceProvider.kubernetesSource(configMap, List.of());
 
 		assertThat(source).isInstanceOf(ConfigMapKubernetesSource.class);
 		assertThat(source.description()).isEqualTo("configmap");
@@ -179,7 +180,7 @@ void kubernetesSourceForSecret() {
 								SecretKubernetesSource.SECRET_SERVICE_LABELS_ANNOTATION, "app=my-app,tier=backend")))
 			.build();
 
-		KubernetesSource source = KubernetesSourceProvider.kubernetesSource(secret);
+		KubernetesSource source = KubernetesSourceProvider.kubernetesSource(secret, List.of());
 
 		assertThat(source).isInstanceOf(SecretKubernetesSource.class);
 		assertThat(source.description()).isEqualTo("secret");
@@ -192,9 +193,35 @@ void kubernetesSourceForSecret() {
 	void kubernetesSourceUnsupportedType() {
 		KubernetesObject kubernetesObject = Mockito.mock(KubernetesObject.class);
 
-		assertThatThrownBy(() -> KubernetesSourceProvider.kubernetesSource(kubernetesObject))
+		assertThatThrownBy(() -> KubernetesSourceProvider.kubernetesSource(kubernetesObject, List.of()))
 			.isInstanceOf(IllegalArgumentException.class)
 			.hasMessageContaining("Unsupported KubernetesObject type");
 	}
 
+	@Test
+	void configuredConfigMapAppsOverrideServiceNamesAnnotation() {
+		V1ConfigMap configMap = new V1ConfigMapBuilder()
+			.withMetadata(
+					new V1ObjectMeta().name("my-configmap")
+						.annotations(Map.of(ConfigMapKubernetesSource.CONFIGMAP_SERVICE_NAMES_ANNOTATION,
+								"app-from-annotation")))
+			.build();
+
+		KubernetesSource source = KubernetesSourceProvider.kubernetesSource(configMap, List.of("app-from-property"));
+
+		assertThat(source.serviceNames()).containsExactly("app-from-property");
+	}
+
+	@Test
+	void configuredSecretAppsOverrideServiceNamesAnnotation() {
+		V1Secret secret = new V1SecretBuilder()
+			.withMetadata(new V1ObjectMeta().name("my-secret")
+				.annotations(Map.of(SecretKubernetesSource.SECRET_SERVICE_NAMES_ANNOTATION, "app-from-annotation")))
+			.build();
+
+		KubernetesSource source = KubernetesSourceProvider.kubernetesSource(secret, List.of("app-from-property"));
+
+		assertThat(source.serviceNames()).containsExactly("app-from-property");
+	}
+
 }

From b460302432f5b77f61273f464d65ee432ca22914 Mon Sep 17 00:00:00 2001
From: wind57 
Date: Sun, 12 Jul 2026 15:28:24 +0300
Subject: [PATCH 8/9] fix-1657-part-2 : first final PR

Signed-off-by: wind57 
---
 .../KubernetesClientConfigUtilsTests.java     |  3 +-
 .../reload/ConfigMapReloadWithLabelsTest.java |  2 +-
 ...tEventBasedSecretsChangeDetectorTests.java |  2 +-
 .../reload/SecretReloadWithLabelsTest.java    |  2 +-
 .../reload_it/EventReloadConfigMapTest.java   |  2 +-
 .../reload_it/EventReloadSecretTest.java      |  2 +-
 .../reload_it/PollingReloadConfigMapTest.java |  2 +-
 .../reload_it/PollingReloadSecretTest.java    |  2 +-
 .../config/reload/ConfigReloadProperties.java |  6 +-
 .../config/ConfigReloadPropertiesTests.java   | 14 ++--
 .../ConfigMapWatcherChangeDetector.java       |  2 +-
 .../watcher/SecretsWatcherChangeDetector.java |  2 +-
 ...edConfigMapWatcherChangeDetectorTests.java | 66 ++++++++++++++++-
 ...asedSecretsWatcherChangeDetectorTests.java | 67 ++++++++++++++++-
 .../KubernetesSourceProviderTests.java        | 72 +++++++++++++++++++
 .../config/Fabric8ConfigUtilsTests.java       |  3 +-
 .../reload_it/EventReloadConfigMapTest.java   |  2 +-
 .../reload_it/EventReloadSecretTest.java      |  2 +-
 .../PollingReloadConfigMapAndSecretTest.java  |  3 +-
 .../reload_it/PollingReloadConfigMapTest.java |  2 +-
 .../reload_it/PollingReloadSecretTest.java    |  2 +-
 .../labels/CommonAbstractFiltering.java       |  4 +-
 22 files changed, 230 insertions(+), 34 deletions(-)

diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigUtilsTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigUtilsTests.java
index d19ff769ff..efddc96ecd 100644
--- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigUtilsTests.java
+++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigUtilsTests.java
@@ -17,6 +17,7 @@
 package org.springframework.cloud.kubernetes.client.config;
 
 import java.time.Duration;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -36,7 +37,7 @@ class KubernetesClientConfigUtilsTests {
 	void testNamespacesFromProperties() {
 		ConfigReloadProperties properties = new ConfigReloadProperties(false, false, Map.of(), false, Map.of(),
 				ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT,
-				Duration.ofMillis(15000), Set.of("non-default"), Duration.ofSeconds(2));
+				Duration.ofMillis(15000), Set.of("non-default"), Duration.ofSeconds(2), List.of(), List.of());
 		Set namespaces = KubernetesClientConfigUtils
 			.namespaces(new KubernetesNamespaceProvider(new MockEnvironment()), properties, "configmap");
 		Assertions.assertThat(1).isEqualTo(namespaces.size());
diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/ConfigMapReloadWithLabelsTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/ConfigMapReloadWithLabelsTest.java
index 45e3c6c319..11cf0e3221 100644
--- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/ConfigMapReloadWithLabelsTest.java
+++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/ConfigMapReloadWithLabelsTest.java
@@ -166,7 +166,7 @@ void test() {
 		ConfigReloadProperties properties = new ConfigReloadProperties(true, monitorConfigMaps, configMapsLabels,
 				monitorSecrets, secretsLabels, ConfigReloadProperties.ReloadStrategy.REFRESH,
 				ConfigReloadProperties.ReloadDetectionMode.EVENT, Duration.ofMillis(15000), Set.of(),
-				Duration.ofSeconds(2));
+				Duration.ofSeconds(2), List.of(), List.of());
 
 		// change detector
 		KubernetesClientEventBasedConfigMapChangeDetector changeDetector = new KubernetesClientEventBasedConfigMapChangeDetector(
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
index 1d958ff9a8..2790f5d30b 100644
--- 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
@@ -282,7 +282,7 @@ private void changeDetectorAssert() {
 		// properties
 		ConfigReloadProperties properties = new ConfigReloadProperties(false, false, Map.of(), true, Map.of(),
 				ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT,
-				Duration.ofMillis(15000), Set.of(), Duration.ofSeconds(2));
+				Duration.ofMillis(15000), Set.of(), Duration.ofSeconds(2), List.of(), List.of());
 
 		// namespace provider
 		KubernetesNamespaceProvider kubernetesNamespaceProvider = mock(KubernetesNamespaceProvider.class);
diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/SecretReloadWithLabelsTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/SecretReloadWithLabelsTest.java
index b1876c199a..f47d2037af 100644
--- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/SecretReloadWithLabelsTest.java
+++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload/SecretReloadWithLabelsTest.java
@@ -164,7 +164,7 @@ void test() {
 		ConfigReloadProperties properties = new ConfigReloadProperties(true, monitorConfigMaps, configMapsLabels,
 				monitorSecrets, secretsLabels, ConfigReloadProperties.ReloadStrategy.REFRESH,
 				ConfigReloadProperties.ReloadDetectionMode.EVENT, Duration.ofMillis(15000), Set.of(),
-				Duration.ofSeconds(2));
+				Duration.ofSeconds(2), List.of(), List.of());
 
 		// change detector
 		KubernetesClientEventBasedSecretsChangeDetector changeDetector = new KubernetesClientEventBasedSecretsChangeDetector(
diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadConfigMapTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadConfigMapTest.java
index c4c3b2e666..0061b5995c 100644
--- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadConfigMapTest.java
+++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadConfigMapTest.java
@@ -199,7 +199,7 @@ VisibleKubernetesClientEventBasedConfigMapChangeDetector kubernetesClientEventBa
 		ConfigReloadProperties configReloadProperties() {
 			return new ConfigReloadProperties(true, true, Map.of(), false, Map.of(),
 					ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.POLLING,
-					Duration.ofMillis(2000), Set.of("spring-k8s"), Duration.ofSeconds(2));
+					Duration.ofMillis(2000), Set.of("spring-k8s"), Duration.ofSeconds(2), List.of(), List.of());
 		}
 
 		@Bean
diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadSecretTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadSecretTest.java
index 137eb32fe3..a4288d16b7 100644
--- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadSecretTest.java
+++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadSecretTest.java
@@ -204,7 +204,7 @@ VisibleKubernetesClientEventBasedSecretsChangeDetector kubernetesClientEventBase
 		ConfigReloadProperties configReloadProperties() {
 			return new ConfigReloadProperties(true, true, Map.of(), false, Map.of(),
 					ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.POLLING,
-					Duration.ofMillis(2000), Set.of("spring-k8s"), Duration.ofSeconds(2));
+					Duration.ofMillis(2000), Set.of("spring-k8s"), Duration.ofSeconds(2), List.of(), List.of());
 		}
 
 		@Bean
diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadConfigMapTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadConfigMapTest.java
index 58f3311a64..dfa86a5458 100644
--- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadConfigMapTest.java
+++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadConfigMapTest.java
@@ -175,7 +175,7 @@ PollingConfigMapChangeDetector pollingConfigMapChangeDetector(AbstractEnvironmen
 		ConfigReloadProperties configReloadProperties() {
 			return new ConfigReloadProperties(true, true, Map.of(), false, Map.of(),
 					ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.POLLING,
-					Duration.ofMillis(2000), Set.of("non-default"), Duration.ofSeconds(2));
+					Duration.ofMillis(2000), Set.of("non-default"), Duration.ofSeconds(2), List.of(), List.of());
 		}
 
 		@Bean
diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadSecretTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadSecretTest.java
index 9b2401f61f..6d38d418fe 100644
--- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadSecretTest.java
+++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadSecretTest.java
@@ -177,7 +177,7 @@ PollingSecretsChangeDetector pollingSecretsChangeDetector(AbstractEnvironment en
 		ConfigReloadProperties configReloadProperties() {
 			return new ConfigReloadProperties(true, false, Map.of(), true, Map.of(),
 					ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.POLLING,
-					Duration.ofMillis(2000), Set.of("non-default"), Duration.ofSeconds(2));
+					Duration.ofMillis(2000), Set.of("non-default"), Duration.ofSeconds(2), List.of(), List.of());
 		}
 
 		@Bean
diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java
index 3229f0391b..f3bf48b53d 100644
--- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java
+++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadProperties.java
@@ -42,9 +42,9 @@
  * avoid having all instances of the same application restart at the same time. This
  * property configures the maximum of amount of wait time from the moment the signal is
  * received that a restart is needed until the moment the restart is actually triggered
- * @param configMapsApps Applications to refresh when a watched ConfigMap changes. Takes
+ * @param configMapApps Applications to refresh when a watched ConfigMap changes. Takes
  * precedence over the {@code spring.cloud.kubernetes.configmap.apps} annotation.
- * @param secretsApps Applications to refresh when a watched Secret changes. Takes
+ * @param secretApps Applications to refresh when a watched Secret changes. Takes
  * precedence over the {@code spring.cloud.kubernetes.secret.apps} annotation.
  * @author Nicola Ferraro
  */
@@ -54,7 +54,7 @@ public record ConfigReloadProperties(boolean enabled, @DefaultValue("true") bool
 		@DefaultValue Map secretsLabels, @DefaultValue("REFRESH") ReloadStrategy strategy,
 		@DefaultValue("EVENT") ReloadDetectionMode mode, @DefaultValue("15000ms") Duration period,
 		@DefaultValue Set namespaces, @DefaultValue("2s") Duration maxWaitForRestart,
-		@DefaultValue List configMapsApps, @DefaultValue List secretsApps) {
+		@DefaultValue List configMapApps, @DefaultValue List secretApps) {
 
 	/**
 	 * default instance.
diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigReloadPropertiesTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigReloadPropertiesTests.java
index c0baedac67..4e89ca6234 100644
--- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigReloadPropertiesTests.java
+++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigReloadPropertiesTests.java
@@ -48,8 +48,8 @@ void testDefaults() {
 			assertThat(Duration.ofMillis(15000)).isEqualTo(properties.period());
 			assertThat(properties.namespaces().isEmpty()).isTrue();
 			assertThat(Duration.ofSeconds(2)).isEqualTo(properties.maxWaitForRestart());
-			assertThat(properties.configMapsApps()).isEmpty();
-			assertThat(properties.secretsApps()).isEmpty();
+			assertThat(properties.configMapApps()).isEmpty();
+			assertThat(properties.secretApps()).isEmpty();
 		});
 	}
 
@@ -65,9 +65,9 @@ void testNonDefaults() {
 					"spring.cloud.kubernetes.reload.period=1000ms", "spring.cloud.kubernetes.reload.namespaces[0]=a",
 					"spring.cloud.kubernetes.reload.namespaces[1]=b",
 					"spring.cloud.kubernetes.reload.max-wait-for-restart=5s",
-					"spring.cloud.kubernetes.reload.config-maps-apps[0]=app-one",
-					"spring.cloud.kubernetes.reload.config-maps-apps[1]=app-two",
-					"spring.cloud.kubernetes.reload.secrets-apps[0]=app-three")
+					"spring.cloud.kubernetes.reload.config-map-apps[0]=app-one",
+					"spring.cloud.kubernetes.reload.config-map-apps[1]=app-two",
+					"spring.cloud.kubernetes.reload.secret-apps[0]=app-three")
 			.run(context -> {
 				ConfigReloadProperties properties = context.getBean(ConfigReloadProperties.class);
 				assertThat(properties).isNotNull();
@@ -81,8 +81,8 @@ void testNonDefaults() {
 				assertThat(Duration.ofMillis(1000)).isEqualTo(properties.period());
 				assertThat(properties.namespaces()).containsExactlyInAnyOrder("a", "b");
 				assertThat(Duration.ofSeconds(5)).isEqualTo(properties.maxWaitForRestart());
-				assertThat(properties.configMapsApps()).containsExactly("app-one", "app-two");
-				assertThat(properties.secretsApps()).containsExactly("app-three");
+				assertThat(properties.configMapApps()).containsExactly("app-one", "app-two");
+				assertThat(properties.secretApps()).containsExactly("app-three");
 			});
 	}
 
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 c19095a982..98ca6ae0a0 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
@@ -75,7 +75,7 @@ abstract sealed class ConfigMapWatcherChangeDetector extends KubernetesClientEve
 
 	@Override
 	protected final void onEvent(KubernetesObject configMap) {
-		WatcherUtil.onEvent(configMap, reloadProperties.configMapsApps(),
+		WatcherUtil.onEvent(configMap, reloadProperties.configMapApps(),
 				k8SConfigurationProperties.getRefreshDelay().toMillis(), scheduler, this::triggerRefresh);
 	}
 
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 607d0f1fd7..e8856b4a67 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
@@ -74,7 +74,7 @@ abstract sealed class SecretsWatcherChangeDetector extends KubernetesClientEvent
 
 	@Override
 	protected final void onEvent(KubernetesObject secret) {
-		WatcherUtil.onEvent(secret, reloadProperties.secretsApps(),
+		WatcherUtil.onEvent(secret, reloadProperties.secretApps(),
 				k8SConfigurationProperties.getRefreshDelay().toMillis(), scheduler, this::triggerRefresh);
 	}
 
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 7a4aa15bc4..b3baec584e 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
@@ -16,10 +16,15 @@
 
 package org.springframework.cloud.kubernetes.configuration.watcher;
 
+import java.time.Duration;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import io.kubernetes.client.openapi.apis.CoreV1Api;
+import io.kubernetes.client.openapi.models.V1ConfigMapBuilder;
+import io.kubernetes.client.openapi.models.V1ObjectMeta;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -44,6 +49,8 @@
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 import static org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider.NAMESPACE_PROPERTY;
 import static org.springframework.cloud.kubernetes.configuration.watcher.ConfigurationWatcherConfigurationProperties.RefreshStrategy;
@@ -66,8 +73,7 @@ class BusEventBasedConfigMapWatcherChangeDetectorTests {
 	@Mock
 	private KubernetesClientConfigMapPropertySourceLocator configMapPropertySourceLocator;
 
-	@Mock
-	private ThreadPoolTaskExecutor threadPoolTaskExecutor;
+	private static final ThreadPoolTaskExecutor THREAD_POOL_TASK_EXECUTOR = new ThreadPoolTaskExecutor();
 
 	@Mock
 	private ApplicationEventPublisher applicationEventPublisher;
@@ -86,6 +92,11 @@ void setup() {
 		busProperties = new BusProperties();
 	}
 
+	@BeforeAll
+	static void beforeAll() {
+		THREAD_POOL_TASK_EXECUTOR.setDaemon(true);
+	}
+
 	@Test
 	void triggerRefreshWithConfigMapUsingServiceNames() {
 		ArgumentCaptor argumentCaptor = ArgumentCaptor
@@ -100,6 +111,48 @@ void triggerRefreshWithConfigMapUsingServiceNamesAndShutdown() {
 		triggerRefreshWithConfigMapUsingServiceNames(RefreshStrategy.SHUTDOWN, argumentCaptor);
 	}
 
+	/**
+	 * 
+	 * 	- watcher-level configMapApps is configured
+	 * 	- configMap also has spring.cloud.kubernetes.configmap.apps
+	 * 	- watcher-level configured apps must win when onEvent builds the KubernetesSource
+	 * 	  ( meaning properties that are configured in the watcher itself take precedence
+	 * 	    over the ones coming from the configmap )
+	 * 
+ */ + @Test + void onEventUsesConfiguredConfigMapAppsInsteadOfAnnotationApps() { + + List configmapApps = List.of("app-from-property"); + List secretApps = List.of(); + + ConfigurationWatcherConfigurationProperties configurationWatcherConfigurationProperties = new ConfigurationWatcherConfigurationProperties(); + configurationWatcherConfigurationProperties.setRefreshDelay(Duration.ZERO); + + BusEventBasedConfigMapWatcherChangeDetector changeDetector = new BusEventBasedConfigMapWatcherChangeDetector( + coreV1Api, mockEnvironment, configReloadProperties(configmapApps, secretApps), UPDATE_STRATEGY, + configMapPropertySourceLocator, new KubernetesNamespaceProvider(mockEnvironment), + configurationWatcherConfigurationProperties, THREAD_POOL_TASK_EXECUTOR, + new BusRefreshTrigger(applicationEventPublisher, busProperties.getId(), + configurationWatcherConfigurationProperties, reactiveDiscoveryClientProvider)); + + changeDetector.onEvent( + new V1ConfigMapBuilder() + .withMetadata(new V1ObjectMeta().name("my-configmap") + .annotations(Map.of(ConfigMapKubernetesSource.CONFIGMAP_SERVICE_NAMES_ANNOTATION, + "app-from-annotation"))) + .build()); + + verify(applicationEventPublisher, timeout(1000)).publishEvent(argThat(event -> { + if (!(event instanceof RefreshRemoteApplicationEvent refreshRemoteApplicationEvent)) { + return false; + } + KubernetesSource kubernetesSource = (KubernetesSource) refreshRemoteApplicationEvent.getSource(); + return kubernetesSource.serviceNames().equals(Set.of("app-from-property")) + && refreshRemoteApplicationEvent.getDestinationService().equals("app-from-property:**"); + })); + } + void triggerRefreshWithConfigMapUsingServiceNames(RefreshStrategy refreshStrategy, ArgumentCaptor argumentCaptor) { @@ -130,11 +183,18 @@ private void triggerRefresh(RefreshStrategy refreshStrategy) { BusEventBasedConfigMapWatcherChangeDetector changeDetector = new BusEventBasedConfigMapWatcherChangeDetector( coreV1Api, mockEnvironment, ConfigReloadProperties.DEFAULT, UPDATE_STRATEGY, configMapPropertySourceLocator, new KubernetesNamespaceProvider(mockEnvironment), - configurationWatcherConfigurationProperties, threadPoolTaskExecutor, + configurationWatcherConfigurationProperties, THREAD_POOL_TASK_EXECUTOR, new BusRefreshTrigger(applicationEventPublisher, busProperties.getId(), configurationWatcherConfigurationProperties, reactiveDiscoveryClientProvider)); Mono result = changeDetector.triggerRefresh(configMapKubernetesSource); StepVerifier.create(result).verifyComplete(); } + private ConfigReloadProperties configReloadProperties(List configMapApps, List secretApps) { + return new ConfigReloadProperties(true, true, Map.of(), false, Map.of(), + ConfigReloadProperties.DEFAULT.strategy(), ConfigReloadProperties.DEFAULT.mode(), + ConfigReloadProperties.DEFAULT.period(), ConfigReloadProperties.DEFAULT.namespaces(), + ConfigReloadProperties.DEFAULT.maxWaitForRestart(), configMapApps, secretApps); + } + } 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 f1daa3eb5e..9c39367d8e 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 @@ -16,10 +16,15 @@ package org.springframework.cloud.kubernetes.configuration.watcher; +import java.time.Duration; +import java.util.List; import java.util.Map; import java.util.Set; import io.kubernetes.client.openapi.apis.CoreV1Api; +import io.kubernetes.client.openapi.models.V1ObjectMeta; +import io.kubernetes.client.openapi.models.V1SecretBuilder; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -44,6 +49,8 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import static org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider.NAMESPACE_PROPERTY; import static org.springframework.cloud.kubernetes.configuration.watcher.ConfigurationWatcherConfigurationProperties.RefreshStrategy; @@ -66,8 +73,7 @@ class BusEventBasedSecretsWatcherChangeDetectorTests { @Mock private KubernetesClientSecretsPropertySourceLocator secretsPropertySourceLocator; - @Mock - private ThreadPoolTaskExecutor threadPoolTaskExecutor; + private static final ThreadPoolTaskExecutor THREAD_POOL_TASK_EXECUTOR = new ThreadPoolTaskExecutor(); @Mock private ApplicationEventPublisher applicationEventPublisher; @@ -86,6 +92,11 @@ void setup() { busProperties = new BusProperties(); } + @BeforeAll + static void beforeAll() { + THREAD_POOL_TASK_EXECUTOR.setDaemon(true); + } + @Test void triggerRefreshWithSecretUsingServiceNames() { ArgumentCaptor argumentCaptor = ArgumentCaptor @@ -100,6 +111,49 @@ void triggerRefreshWithSecretUsingServiceNamesAndShutdown() { triggerRefreshWithSecretUsingServiceNames(RefreshStrategy.SHUTDOWN, argumentCaptor); } + /** + *
+	 * 	- watcher-level secretApps property is configured
+	 * 	- secret also has spring.cloud.kubernetes.secret.apps
+	 * 	- watcher-level configured apps must win when onEvent builds the KubernetesSource
+	 * 	  ( meaning properties that are configured in the watcher itself take precedence
+	 * 	    over the ones coming from the secret )
+	 * 
+ */ + @Test + void onEventUsesConfiguredSecretAppsInsteadOfAnnotationApps() { + + List configmapApps = List.of(); + List secretApps = List.of("app-from-property"); + + ConfigurationWatcherConfigurationProperties configurationWatcherConfigurationProperties = new ConfigurationWatcherConfigurationProperties(); + configurationWatcherConfigurationProperties.setRefreshDelay(Duration.ZERO); + BusEventBasedSecretsWatcherChangeDetector changeDetector = new BusEventBasedSecretsWatcherChangeDetector( + coreV1Api, mockEnvironment, configReloadProperties(configmapApps, secretApps), UPDATE_STRATEGY, + secretsPropertySourceLocator, new KubernetesNamespaceProvider(mockEnvironment), + configurationWatcherConfigurationProperties, THREAD_POOL_TASK_EXECUTOR, + new BusRefreshTrigger(applicationEventPublisher, busProperties.getId(), + configurationWatcherConfigurationProperties, reactiveDiscoveryClientProvider)); + + changeDetector.onEvent( + new V1SecretBuilder() + .withMetadata( + new V1ObjectMeta() + .name("my-secret") + .annotations(Map.of(SecretKubernetesSource.SECRET_SERVICE_NAMES_ANNOTATION, + "app-from-annotation"))) + .build()); + + verify(applicationEventPublisher, timeout(1000)).publishEvent(argThat(event -> { + if (!(event instanceof RefreshRemoteApplicationEvent refreshRemoteApplicationEvent)) { + return false; + } + KubernetesSource kubernetesSource = (KubernetesSource) refreshRemoteApplicationEvent.getSource(); + return kubernetesSource.serviceNames().equals(Set.of("app-from-property")) + && refreshRemoteApplicationEvent.getDestinationService().equals("app-from-property:**"); + })); + } + void triggerRefreshWithSecretUsingServiceNames(RefreshStrategy refreshStrategy, ArgumentCaptor argumentCaptor) { @@ -130,11 +184,18 @@ private void triggerRefresh(RefreshStrategy refreshStrategy) { BusEventBasedSecretsWatcherChangeDetector changeDetector = new BusEventBasedSecretsWatcherChangeDetector( coreV1Api, mockEnvironment, ConfigReloadProperties.DEFAULT, UPDATE_STRATEGY, secretsPropertySourceLocator, new KubernetesNamespaceProvider(mockEnvironment), - configurationWatcherConfigurationProperties, threadPoolTaskExecutor, + configurationWatcherConfigurationProperties, THREAD_POOL_TASK_EXECUTOR, new BusRefreshTrigger(applicationEventPublisher, busProperties.getId(), configurationWatcherConfigurationProperties, reactiveDiscoveryClientProvider)); Mono result = changeDetector.triggerRefresh(secretKubernetesSource); StepVerifier.create(result).verifyComplete(); } + private ConfigReloadProperties configReloadProperties(List configMapApps, List secretApps) { + return new ConfigReloadProperties(true, true, Map.of(), false, Map.of(), + ConfigReloadProperties.DEFAULT.strategy(), ConfigReloadProperties.DEFAULT.mode(), + ConfigReloadProperties.DEFAULT.period(), ConfigReloadProperties.DEFAULT.namespaces(), + ConfigReloadProperties.DEFAULT.maxWaitForRestart(), configMapApps, secretApps); + } + } diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProviderTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProviderTests.java index f961ff2e00..a730d13a9f 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProviderTests.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/KubernetesSourceProviderTests.java @@ -224,4 +224,76 @@ void configuredSecretAppsOverrideServiceNamesAnnotation() { assertThat(source.serviceNames()).containsExactly("app-from-property"); } + /** + *
+	 * 	- no apps are configured on the watcher itself
+	 * 	- the ConfigMap has spring.cloud.kubernetes.configmap.apps
+	 * 	- that annotation must win over the ConfigMap metadata.name fallback
+	 * 
+ */ + @Test + void configMapServiceNamesAnnotationOverridesMetadataNameWhenConfiguredAppsMissing() { + V1ConfigMap configMap = new V1ConfigMapBuilder() + .withMetadata( + new V1ObjectMeta().name("my-configmap") + .annotations(Map.of(ConfigMapKubernetesSource.CONFIGMAP_SERVICE_NAMES_ANNOTATION, + "app-from-annotation"))) + .build(); + + KubernetesSource source = KubernetesSourceProvider.kubernetesSource(configMap, List.of()); + + assertThat(source.serviceNames()).containsExactly("app-from-annotation"); + } + + /** + *
+	 * 	- no apps are configured on the watcher itself
+	 * 	- the Secret has spring.cloud.kubernetes.secret.apps
+	 * 	- that annotation must win over the Secret metadata.name fallback
+	 * 
+ */ + @Test + void secretServiceNamesAnnotationOverridesMetadataNameWhenConfiguredAppsMissing() { + V1Secret secret = new V1SecretBuilder() + .withMetadata(new V1ObjectMeta().name("my-secret") + .annotations(Map.of(SecretKubernetesSource.SECRET_SERVICE_NAMES_ANNOTATION, "app-from-annotation"))) + .build(); + + KubernetesSource source = KubernetesSourceProvider.kubernetesSource(secret, List.of()); + + assertThat(source.serviceNames()).containsExactly("app-from-annotation"); + } + + /** + *
+	 * 	- no apps are configured on the watcher itself
+	 * 	- the ConfigMap has no spring.cloud.kubernetes.configmap.apps annotation
+	 * 	- we must fall back to ConfigMap metadata.name
+	 * 
+ */ + @Test + void configMapServiceNamesFallbackToMetadataNameWhenConfiguredAppsAndAnnotationMissing() { + V1ConfigMap configMap = new V1ConfigMapBuilder().withMetadata(new V1ObjectMeta().name("my-configmap")).build(); + + KubernetesSource source = KubernetesSourceProvider.kubernetesSource(configMap, List.of()); + + assertThat(source.serviceNames()).containsExactly("my-configmap"); + } + + /** + *
+	 * 	- no apps are configured on the watcher itself
+	 * 	- the Secret has no spring.cloud.kubernetes.secret.apps annotation
+	 * 	- we must fall back to Secret metadata.name
+	 * 
+ */ + @Test + void secretServiceNamesFallbackToMetadataNameWhenConfiguredAppsAndAnnotationMissing() { + V1Secret secret = new V1SecretBuilder().withMetadata(new V1ObjectMeta().name("my-secret")).build(); + + KubernetesSource source = KubernetesSourceProvider.kubernetesSource(secret, List.of()); + + assertThat(source.serviceNames()).containsExactly("my-secret"); + } + } diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigUtilsTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigUtilsTests.java index 592a68f936..cbddc41a89 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigUtilsTests.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigUtilsTests.java @@ -17,6 +17,7 @@ package org.springframework.cloud.kubernetes.fabric8.config; import java.time.Duration; +import java.util.List; import java.util.Map; import java.util.Set; @@ -39,7 +40,7 @@ void testNamespacesFromProperties() { ConfigReloadProperties configReloadProperties = new ConfigReloadProperties(false, true, Map.of(), false, Map.of(), ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, Duration.ofMillis(15000), Set.of("non-default"), - Duration.ofSeconds(2)); + Duration.ofSeconds(2), List.of(), List.of()); Set namespaces = Fabric8ConfigUtils.namespaces(null, new KubernetesNamespaceProvider(new MockEnvironment()), configReloadProperties, "configmap"); Assertions.assertThat(namespaces.size()).isEqualTo(1); diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadConfigMapTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadConfigMapTest.java index 6c03398cdb..6efd78196b 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadConfigMapTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadConfigMapTest.java @@ -160,7 +160,7 @@ Fabric8EventBasedConfigMapChangeDetector fabric8EventBasedSecretsChangeDetector( ConfigReloadProperties configReloadProperties() { return new ConfigReloadProperties(true, true, Map.of(), false, Map.of(), ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, - Duration.ofMillis(2000), Set.of(NAMESPACE), Duration.ofSeconds(2)); + Duration.ofMillis(2000), Set.of(NAMESPACE), Duration.ofSeconds(2), List.of(), List.of()); } @Bean diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadSecretTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadSecretTest.java index 8743525e33..842f7c795c 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadSecretTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadSecretTest.java @@ -165,7 +165,7 @@ Fabric8EventBasedSecretsChangeDetector fabric8EventBasedSecretsChangeDetector(Ab ConfigReloadProperties configReloadProperties() { return new ConfigReloadProperties(true, true, Map.of(), true, Map.of(), ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, - Duration.ofMillis(2000), Set.of(NAMESPACE), Duration.ofSeconds(2)); + Duration.ofMillis(2000), Set.of(NAMESPACE), Duration.ofSeconds(2), List.of(), List.of()); } @Bean diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapAndSecretTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapAndSecretTest.java index 77206bec58..f3e664dd74 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapAndSecretTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapAndSecretTest.java @@ -20,6 +20,7 @@ import java.time.Duration; import java.util.Base64; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; @@ -174,7 +175,7 @@ private static ConfigurationUpdateStrategy secretConfigurationUpdateStrategy() { private static ConfigReloadProperties configReloadProperties() { return new ConfigReloadProperties(true, true, Map.of(), true, Map.of(), ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.POLLING, - Duration.ofMillis(200), Set.of(NAMESPACE), Duration.ofSeconds(2)); + Duration.ofMillis(200), Set.of(NAMESPACE), Duration.ofSeconds(2), List.of(), List.of()); } @TestConfiguration diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapTest.java index 57b9d8d672..0001581f91 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapTest.java @@ -141,7 +141,7 @@ PollingConfigMapChangeDetector pollingConfigMapChangeDetector(AbstractEnvironmen ConfigReloadProperties configReloadProperties() { return new ConfigReloadProperties(true, true, Map.of(), false, Map.of(), ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.POLLING, - Duration.ofMillis(2000), Set.of("non-default"), Duration.ofSeconds(2)); + Duration.ofMillis(2000), Set.of("non-default"), Duration.ofSeconds(2), List.of(), List.of()); } @Bean diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadSecretTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadSecretTest.java index 226c026ef8..aa2e46db6b 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadSecretTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadSecretTest.java @@ -147,7 +147,7 @@ PollingSecretsChangeDetector pollingSecretsChangeDetector(AbstractEnvironment en ConfigReloadProperties configReloadProperties() { return new ConfigReloadProperties(true, true, Map.of(), true, Map.of(), ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.POLLING, - Duration.ofMillis(2000), Set.of("non-default"), Duration.ofSeconds(2)); + Duration.ofMillis(2000), Set.of("non-default"), Duration.ofSeconds(2), List.of(), List.of()); } @Bean diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/CommonAbstractFiltering.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/CommonAbstractFiltering.java index 1f61ff0188..599cf230a1 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/CommonAbstractFiltering.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/labels/CommonAbstractFiltering.java @@ -204,7 +204,7 @@ ConfigReloadProperties configReloadPropertiesB() { return new ConfigReloadProperties(true, monitorConfigMaps, configMapsLabels, monitorSecrets, secretsLabels, ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, - Duration.ofMillis(2000), Set.of(NAMESPACE), Duration.ofSeconds(2)); + Duration.ofMillis(2000), Set.of(NAMESPACE), Duration.ofSeconds(2), List.of(), List.of()); } @Bean @@ -219,7 +219,7 @@ ConfigReloadProperties configReloadProperties() { return new ConfigReloadProperties(true, monitorConfigMaps, configMapsLabels, monitorSecrets, secretsLabels, ConfigReloadProperties.ReloadStrategy.REFRESH, ConfigReloadProperties.ReloadDetectionMode.EVENT, - Duration.ofMillis(2000), Set.of(NAMESPACE), Duration.ofSeconds(2)); + Duration.ofMillis(2000), Set.of(NAMESPACE), Duration.ofSeconds(2), List.of(), List.of()); } } From 6e685ad053a216b0fe1739483a30f09ea07b3b59 Mon Sep 17 00:00:00 2001 From: wind57 Date: Mon, 13 Jul 2026 13:32:18 +0300 Subject: [PATCH 9/9] trigger Signed-off-by: wind57