From 6eac9308efce575d0c02c65dba00aa0b4eb1370f Mon Sep 17 00:00:00 2001 From: wind57 Date: Mon, 3 Feb 2025 19:04:09 +0200 Subject: [PATCH 1/4] fix issue Signed-off-by: wind57 --- .../config/KubernetesConfigDataLocationResolver.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolver.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolver.java index 95907843ad..13742445e5 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolver.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolver.java @@ -174,11 +174,12 @@ private static PropertyHolder of(ConfigDataLocationResolverContext context) { private static KubernetesClientProperties clientProperties(ConfigDataLocationResolverContext context, String namespace) { KubernetesClientProperties kubernetesClientProperties; + ConfigurableBootstrapContext bootstrapContext = context.getBootstrapContext(); - if (context.getBootstrapContext().isRegistered(KubernetesClientProperties.class)) { - kubernetesClientProperties = context.getBootstrapContext() - .get(KubernetesClientProperties.class) - .withNamespace(namespace); + KubernetesClientProperties clientProperties; + if (bootstrapContext.isRegistered(KubernetesClientProperties.class) && + (clientProperties = bootstrapContext.get(KubernetesClientProperties.class)) != null) { + kubernetesClientProperties = clientProperties.withNamespace(namespace); } else { kubernetesClientProperties = context.getBinder() From fe28576451be227b96650c4d498c39813ed8d08d Mon Sep 17 00:00:00 2001 From: wind57 Date: Mon, 3 Feb 2025 19:08:34 +0200 Subject: [PATCH 2/4] refactor Signed-off-by: wind57 --- .../KubernetesConfigDataLocationResolver.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolver.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolver.java index 13742445e5..51acafc280 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolver.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolver.java @@ -52,6 +52,8 @@ public abstract class KubernetesConfigDataLocationResolver implements ConfigDataLocationResolver, Ordered { + private static final Class PROPERTIES_CLASS = KubernetesClientProperties.class; + private static final boolean RETRY_IS_PRESENT = isPresent("org.springframework.retry.annotation.Retryable", null); private final Log log; @@ -139,8 +141,7 @@ private void registerProperties(ConfigDataLocationResolverContext resolverContex SecretsConfigProperties secretsProperties) { ConfigurableBootstrapContext bootstrapContext = resolverContext.getBootstrapContext(); - registerSingle(bootstrapContext, KubernetesClientProperties.class, clientProperties, - "configDataKubernetesClientProperties"); + registerSingle(bootstrapContext, PROPERTIES_CLASS, clientProperties, "configDataKubernetesClientProperties"); if (configMapProperties != null) { registerSingle(bootstrapContext, ConfigMapConfigProperties.class, configMapProperties, @@ -176,14 +177,12 @@ private static KubernetesClientProperties clientProperties(ConfigDataLocationRes KubernetesClientProperties kubernetesClientProperties; ConfigurableBootstrapContext bootstrapContext = context.getBootstrapContext(); - KubernetesClientProperties clientProperties; - if (bootstrapContext.isRegistered(KubernetesClientProperties.class) && - (clientProperties = bootstrapContext.get(KubernetesClientProperties.class)) != null) { - kubernetesClientProperties = clientProperties.withNamespace(namespace); + if (bootstrapContext.isRegistered(PROPERTIES_CLASS) && bootstrapContext.get(PROPERTIES_CLASS) != null) { + kubernetesClientProperties = bootstrapContext.get(PROPERTIES_CLASS).withNamespace(namespace); } else { kubernetesClientProperties = context.getBinder() - .bindOrCreate(KubernetesClientProperties.PREFIX, Bindable.of(KubernetesClientProperties.class)) + .bindOrCreate(KubernetesClientProperties.PREFIX, Bindable.of(PROPERTIES_CLASS)) .withNamespace(namespace); } From 53fc3b241be772adc01fcdb992322f11a226b692 Mon Sep 17 00:00:00 2001 From: wind57 Date: Tue, 4 Feb 2025 21:51:45 +0200 Subject: [PATCH 3/4] fix issue Signed-off-by: wind57 --- .../commons/config/ConfigUtils.java | 9 ++- .../pom.xml | 7 ++ .../discovery/Fabric8ConfigServerTest.java | 77 +++++++++++++++++++ 3 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerTest.java diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java index 886e9e7b2f..95cf263616 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigUtils.java @@ -339,10 +339,11 @@ public static void registerSingle(ConfigurableBootstrapContext bootstrapCont String name, ApplicationListener listener) { bootstrapContext.registerIfAbsent(cls, BootstrapRegistry.InstanceSupplier.of(instance)); bootstrapContext.addCloseListener(event -> { - if (event.getApplicationContext().getBeanFactory().getSingleton(name) == null) { - event.getApplicationContext() - .getBeanFactory() - .registerSingleton(name, event.getBootstrapContext().get(cls)); + + T singleton = event.getBootstrapContext().get(cls); + + if (event.getApplicationContext().getBeanFactory().getSingleton(name) == null && singleton != null) { + event.getApplicationContext().getBeanFactory().registerSingleton(name, singleton); event.getApplicationContext().addApplicationListener(listener); } }); diff --git a/spring-cloud-kubernetes-fabric8-discovery/pom.xml b/spring-cloud-kubernetes-fabric8-discovery/pom.xml index 943924cad7..926835cc4c 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/pom.xml +++ b/spring-cloud-kubernetes-fabric8-discovery/pom.xml @@ -49,6 +49,13 @@ + + + org.springframework.cloud + spring-cloud-kubernetes-fabric8-config + test + + org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerTest.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerTest.java new file mode 100644 index 0000000000..26b1335d1b --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2013-2025 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.discovery; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; + +/** + * Test that proves that this + * issue + * is fixed. + * + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { + "spring.main.cloud-platform=KUBERNETES", "spring.config.import=kubernetes:, optional:configserver:" }) +class Fabric8ConfigServerTest { + + private static WireMockServer wireMockServer; + + @Autowired + private ApplicationContext applicationContext; + + @BeforeAll + static void beforeAll() { + wireMockServer = new WireMockServer(options().port(8888)); + wireMockServer.start(); + WireMock.configureFor("localhost", wireMockServer.port()); + } + + @AfterAll + static void after() { + WireMock.shutdownServer(); + wireMockServer.stop(); + } + + @Test + void test() { + stubFor(get(urlEqualTo("/application/default")).willReturn(aResponse().withStatus(200).withBody("{}"))); + Assertions.assertThat(applicationContext).isNotNull(); + } + + @SpringBootApplication + protected static class TestConfig { + + } + +} From 21837568a7f43f1e851d7ff9b97fc59f862b0c53 Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 5 Feb 2025 22:03:12 +0200 Subject: [PATCH 4/4] review comments Signed-off-by: wind57 --- .../pom.xml | 7 --- .../DummyConfigDataLocationResolver.java | 43 +++++++++++++++++++ .../discovery/Fabric8ConfigServerTest.java | 5 ++- .../test/resources/META-INF/spring.factories | 2 + 4 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/DummyConfigDataLocationResolver.java create mode 100644 spring-cloud-kubernetes-fabric8-discovery/src/test/resources/META-INF/spring.factories diff --git a/spring-cloud-kubernetes-fabric8-discovery/pom.xml b/spring-cloud-kubernetes-fabric8-discovery/pom.xml index 926835cc4c..943924cad7 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/pom.xml +++ b/spring-cloud-kubernetes-fabric8-discovery/pom.xml @@ -49,13 +49,6 @@ - - - org.springframework.cloud - spring-cloud-kubernetes-fabric8-config - test - - org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/DummyConfigDataLocationResolver.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/DummyConfigDataLocationResolver.java new file mode 100644 index 0000000000..42e8552270 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/DummyConfigDataLocationResolver.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013-2025 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; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.config.ConfigDataLocation; +import org.springframework.boot.context.config.ConfigDataLocationResolverContext; +import org.springframework.boot.context.config.Profiles; +import org.springframework.boot.logging.DeferredLogFactory; +import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; +import org.springframework.cloud.kubernetes.commons.config.KubernetesConfigDataLocationResolver; + +/** + * @author wind57 + */ +@ConditionalOnProperty(value = "dummy.config.loader.enabled", havingValue = "true", matchIfMissing = false) +class DummyConfigDataLocationResolver extends KubernetesConfigDataLocationResolver { + + DummyConfigDataLocationResolver(DeferredLogFactory factory) { + super(factory); + } + + @Override + protected void registerBeans(ConfigDataLocationResolverContext resolverContext, ConfigDataLocation location, + Profiles profiles, PropertyHolder propertyHolder, KubernetesNamespaceProvider namespaceProvider) { + + } + +} diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerTest.java b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerTest.java index 26b1335d1b..685cb443fb 100644 --- a/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerTest.java +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/Fabric8ConfigServerTest.java @@ -41,8 +41,9 @@ * * @author wind57 */ -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { - "spring.main.cloud-platform=KUBERNETES", "spring.config.import=kubernetes:, optional:configserver:" }) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = { "spring.main.cloud-platform=KUBERNETES", + "spring.config.import=kubernetes:, optional:configserver:", "dummy.config.loader.enabled=true" }) class Fabric8ConfigServerTest { private static WireMockServer wireMockServer; diff --git a/spring-cloud-kubernetes-fabric8-discovery/src/test/resources/META-INF/spring.factories b/spring-cloud-kubernetes-fabric8-discovery/src/test/resources/META-INF/spring.factories new file mode 100644 index 0000000000..d92d10c6d0 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-discovery/src/test/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.context.config.ConfigDataLocationResolver=\ +org.springframework.cloud.kubernetes.DummyConfigDataLocationResolver