diff --git a/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigDataLocationResolver.java b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigDataLocationResolver.java index 57d0240c55..dfe3c276f8 100644 --- a/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigDataLocationResolver.java +++ b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigDataLocationResolver.java @@ -24,16 +24,16 @@ 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.KubernetesClientProperties; import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.config.ConfigDataRetryableConfigMapPropertySourceLocator; import org.springframework.cloud.kubernetes.commons.config.ConfigDataRetryableSecretsPropertySourceLocator; import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties; import org.springframework.cloud.kubernetes.commons.config.ConfigMapPropertySourceLocator; -import org.springframework.cloud.kubernetes.commons.config.KubernetesConfigDataLocationResolver; import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties; import org.springframework.cloud.kubernetes.commons.config.SecretsPropertySourceLocator; +import org.springframework.cloud.kubernetes.commons.configdata.ConfigDataPropertiesHolder; +import org.springframework.cloud.kubernetes.commons.configdata.KubernetesConfigDataLocationResolver; import org.springframework.core.env.Environment; import static org.springframework.cloud.kubernetes.client.KubernetesClientUtils.kubernetesApiClient; @@ -44,17 +44,12 @@ */ public class KubernetesClientConfigDataLocationResolver extends KubernetesConfigDataLocationResolver { - public KubernetesClientConfigDataLocationResolver(DeferredLogFactory factory) { - super(factory); - } - @Override protected void registerBeans(ConfigDataLocationResolverContext resolverContext, ConfigDataLocation location, - Profiles profiles, KubernetesConfigDataLocationResolver.PropertyHolder propertyHolder, - KubernetesNamespaceProvider namespaceProvider) { - KubernetesClientProperties kubernetesClientProperties = propertyHolder.kubernetesClientProperties(); - ConfigMapConfigProperties configMapProperties = propertyHolder.configMapConfigProperties(); - SecretsConfigProperties secretsProperties = propertyHolder.secretsProperties(); + Profiles profiles, ConfigDataPropertiesHolder properties, KubernetesNamespaceProvider namespaceProvider) { + KubernetesClientProperties kubernetesClientProperties = properties.clientProperties(); + ConfigMapConfigProperties configMapProperties = properties.configMapProperties(); + SecretsConfigProperties secretsProperties = properties.secretsProperties(); ConfigurableBootstrapContext bootstrapContext = resolverContext.getBootstrapContext(); CoreV1Api coreV1Api = registerClientAndCoreV1Api(bootstrapContext, kubernetesClientProperties); diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigDataLocationResolverTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigDataLocationResolverTests.java index 9756660b23..24d9f4f4e7 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigDataLocationResolverTests.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigDataLocationResolverTests.java @@ -16,8 +16,6 @@ package org.springframework.cloud.kubernetes.client.config; -import java.util.function.Supplier; - import io.kubernetes.client.openapi.ApiClient; import io.kubernetes.client.openapi.apis.CoreV1Api; import org.assertj.core.api.Assertions; @@ -31,7 +29,6 @@ import org.springframework.boot.context.config.Profiles; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.context.properties.source.ConfigurationPropertySources; -import org.springframework.boot.logging.DeferredLogFactory; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties; @@ -49,13 +46,10 @@ @ExtendWith(OutputCaptureExtension.class) class KubernetesClientConfigDataLocationResolverTests { - private static final DeferredLogFactory FACTORY = Supplier::get; - private static final ConfigDataLocationResolverContext RESOLVER_CONTEXT = Mockito .mock(ConfigDataLocationResolverContext.class); - private static final KubernetesClientConfigDataLocationResolver RESOLVER = new KubernetesClientConfigDataLocationResolver( - FACTORY); + private static final KubernetesClientConfigDataLocationResolver RESOLVER = new KubernetesClientConfigDataLocationResolver(); /* * both ConfigMapConfigProperties and SecretsConfigProperties are null, thus they are 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 deleted file mode 100644 index 73b200207f..0000000000 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolver.java +++ /dev/null @@ -1,223 +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.commons.config; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; - -import org.springframework.boot.bootstrap.ConfigurableBootstrapContext; -import org.springframework.boot.context.config.ConfigDataLocation; -import org.springframework.boot.context.config.ConfigDataLocationNotFoundException; -import org.springframework.boot.context.config.ConfigDataLocationResolver; -import org.springframework.boot.context.config.ConfigDataLocationResolverContext; -import org.springframework.boot.context.config.ConfigDataResourceNotFoundException; -import org.springframework.boot.context.config.Profiles; -import org.springframework.boot.context.properties.bind.Bindable; -import org.springframework.boot.context.properties.bind.Binder; -import org.springframework.boot.logging.DeferredLogFactory; -import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; -import org.springframework.core.Ordered; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.Environment; -import org.springframework.core.env.MapPropertySource; -import org.springframework.core.env.PropertySource; -import org.springframework.core.env.StandardEnvironment; - -import static org.springframework.boot.cloud.CloudPlatform.KUBERNETES; -import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.registerSingle; -import static org.springframework.util.ClassUtils.isPresent; - -/** - * @author Ryan Baxter - */ -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; - - public KubernetesConfigDataLocationResolver(DeferredLogFactory factory) { - this.log = factory.getLog(KubernetesConfigDataLocationResolver.class); - } - - protected final String getPrefix() { - return "kubernetes:"; - } - - @Override - public final int getOrder() { - return -1; - } - - @Override - public final boolean isResolvable(ConfigDataLocationResolverContext context, ConfigDataLocation location) { - return location.hasPrefix(getPrefix()) - && (KUBERNETES.isEnforced(context.getBinder()) || KUBERNETES.isDetected(new StandardEnvironment())); - } - - @Override - public final List resolve(ConfigDataLocationResolverContext context, - ConfigDataLocation location) - throws ConfigDataLocationNotFoundException, ConfigDataResourceNotFoundException { - return Collections.emptyList(); - } - - @Override - public final List resolveProfileSpecific( - ConfigDataLocationResolverContext resolverContext, ConfigDataLocation location, Profiles profiles) - throws ConfigDataLocationNotFoundException { - PropertyHolder propertyHolder = PropertyHolder.of(resolverContext); - KubernetesClientProperties clientProperties = propertyHolder.kubernetesClientProperties(); - ConfigMapConfigProperties configMapProperties = propertyHolder.configMapConfigProperties(); - SecretsConfigProperties secretsProperties = propertyHolder.secretsProperties(); - - registerProperties(resolverContext, clientProperties, configMapProperties, secretsProperties); - - HashMap kubernetesConfigData = new HashMap<>(); - kubernetesConfigData.put("spring.cloud.kubernetes.client.namespace", clientProperties.namespace()); - if (propertyHolder.applicationName() != null) { - // If its null it means sprig.application.name was not set so don't add it to - // the property source - kubernetesConfigData.put("spring.application.name", propertyHolder.applicationName()); - } - PropertySource> propertySource = new MapPropertySource("kubernetesConfigData", - kubernetesConfigData); - ConfigurableEnvironment environment = new StandardEnvironment(); - environment.getPropertySources().addLast(propertySource); - environment.setActiveProfiles(profiles.getAccepted().toArray(new String[0])); - KubernetesNamespaceProvider namespaceProvider = kubernetesNamespaceProvider(environment); - - registerBeans(resolverContext, location, profiles, propertyHolder, namespaceProvider); - - KubernetesConfigDataResource resource = new KubernetesConfigDataResource(clientProperties, configMapProperties, - secretsProperties, location.isOptional(), profiles, environment); - resource.setLog(log); - - return List.of(resource); - } - - protected abstract void registerBeans(ConfigDataLocationResolverContext resolverContext, - ConfigDataLocation location, Profiles profiles, PropertyHolder propertyHolder, - KubernetesNamespaceProvider namespaceProvider); - - protected final boolean isRetryEnabledForConfigMap(ConfigMapConfigProperties configMapProperties) { - return RETRY_IS_PRESENT && configMapProperties != null && configMapProperties.retry().enabled() - && configMapProperties.failFast(); - } - - protected final boolean isRetryEnabledForSecrets(SecretsConfigProperties secretsProperties) { - return RETRY_IS_PRESENT && secretsProperties != null && secretsProperties.retry().enabled() - && secretsProperties.failFast(); - } - - protected KubernetesNamespaceProvider kubernetesNamespaceProvider(Environment environment) { - return new KubernetesNamespaceProvider(environment); - } - - private void registerProperties(ConfigDataLocationResolverContext resolverContext, - KubernetesClientProperties clientProperties, ConfigMapConfigProperties configMapProperties, - SecretsConfigProperties secretsProperties) { - - ConfigurableBootstrapContext bootstrapContext = resolverContext.getBootstrapContext(); - registerSingle(bootstrapContext, PROPERTIES_CLASS, clientProperties, "configDataKubernetesClientProperties"); - - if (configMapProperties != null) { - registerSingle(bootstrapContext, ConfigMapConfigProperties.class, configMapProperties, - "configDataConfigMapConfigProperties"); - } - - if (secretsProperties != null) { - registerSingle(bootstrapContext, SecretsConfigProperties.class, secretsProperties, - "configDataSecretsConfigProperties"); - } - } - - protected record PropertyHolder(KubernetesClientProperties kubernetesClientProperties, - ConfigMapConfigProperties configMapConfigProperties, SecretsConfigProperties secretsProperties, - String applicationName) { - - private static PropertyHolder of(ConfigDataLocationResolverContext context) { - Binder binder = context.getBinder(); - - String applicationName = binder.bind("spring.application.name", String.class).orElse(null); - String namespace = binder.bind("spring.cloud.kubernetes.client.namespace", String.class) - .orElse(binder.bind("kubernetes.namespace", String.class).orElse("")); - - KubernetesClientProperties kubernetesClientProperties = clientProperties(context, namespace); - ConfigMapAndSecrets both = ConfigMapAndSecrets.of(binder); - - return new PropertyHolder(kubernetesClientProperties, both.configMapProperties(), - both.secretsConfigProperties(), applicationName); - } - - private static KubernetesClientProperties clientProperties(ConfigDataLocationResolverContext context, - String namespace) { - KubernetesClientProperties kubernetesClientProperties; - ConfigurableBootstrapContext bootstrapContext = context.getBootstrapContext(); - - 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(PROPERTIES_CLASS)) - .withNamespace(namespace); - } - - return kubernetesClientProperties; - - } - - } - - /** - * holds ConfigMapConfigProperties and SecretsConfigProperties, both can be null if - * using such sources is disabled. - */ - private record ConfigMapAndSecrets(ConfigMapConfigProperties configMapProperties, - SecretsConfigProperties secretsConfigProperties) { - - private static ConfigMapAndSecrets of(Binder binder) { - - boolean configEnabled = binder.bind("spring.cloud.kubernetes.config.enabled", boolean.class).orElse(true); - boolean secretsEnabled = binder.bind("spring.cloud.kubernetes.secrets.enabled", boolean.class).orElse(true); - - ConfigMapConfigProperties configMapConfigProperties = null; - if (configEnabled) { - configMapConfigProperties = binder.bindOrCreate(ConfigMapConfigProperties.PREFIX, - ConfigMapConfigProperties.class); - } - - SecretsConfigProperties secretsProperties = null; - if (secretsEnabled) { - secretsProperties = binder.bindOrCreate(SecretsConfigProperties.PREFIX, SecretsConfigProperties.class); - } - - return new ConfigMapAndSecrets(configMapConfigProperties, secretsProperties); - - } - } - -} diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataResource.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataResource.java deleted file mode 100644 index 4afd1015cc..0000000000 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataResource.java +++ /dev/null @@ -1,136 +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.commons.config; - -import java.util.List; -import java.util.Objects; - -import org.apache.commons.logging.Log; - -import org.springframework.boot.context.config.ConfigDataResource; -import org.springframework.boot.context.config.Profiles; -import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties; -import org.springframework.core.env.Environment; -import org.springframework.core.style.ToStringCreator; -import org.springframework.util.StringUtils; - -/** - * @author Ryan Baxter - */ -public class KubernetesConfigDataResource extends ConfigDataResource { - - private final KubernetesClientProperties properties; - - private final ConfigMapConfigProperties configMapProperties; - - private final SecretsConfigProperties secretsConfigProperties; - - private final boolean optional; - - private final Profiles profiles; - - private Log log; - - private Environment environment; - - public KubernetesConfigDataResource(KubernetesClientProperties properties, - ConfigMapConfigProperties configMapProperties, SecretsConfigProperties secretsConfigProperties, - boolean optional, Profiles profiles, Environment environment) { - this.properties = properties; - this.configMapProperties = configMapProperties; - this.secretsConfigProperties = secretsConfigProperties; - this.optional = optional; - this.profiles = profiles; - this.environment = environment; - } - - public KubernetesClientProperties getProperties() { - return this.properties; - } - - /** - * ConfigMapConfigProperties that might be null. - */ - public ConfigMapConfigProperties getConfigMapProperties() { - return configMapProperties; - } - - /** - * SecretsConfigProperties that might be null. - */ - public SecretsConfigProperties getSecretsConfigProperties() { - return secretsConfigProperties; - } - - public boolean isOptional() { - return this.optional; - } - - public String getProfiles() { - return StringUtils.collectionToCommaDelimitedString(getAcceptedProfiles()); - } - - List getAcceptedProfiles() { - return this.profiles.getAccepted(); - } - - public void setLog(Log log) { - this.log = log; - } - - public Log getLog() { - return this.log; - } - - public Environment getEnvironment() { - return environment; - } - - public void setEnvironment(Environment environment) { - this.environment = environment; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - KubernetesConfigDataResource that = (KubernetesConfigDataResource) o; - return Objects.equals(this.properties, that.properties) && Objects.equals(this.optional, that.optional) - && Objects.equals(this.profiles, that.profiles) - && Objects.equals(this.configMapProperties, that.configMapProperties) - && Objects.equals(this.secretsConfigProperties, that.secretsConfigProperties); - } - - @Override - public int hashCode() { - return Objects.hash(this.properties, this.optional, this.profiles, configMapProperties, - secretsConfigProperties); - } - - @Override - public String toString() { - return new ToStringCreator(this).append("optional", optional) - .append("profiles", profiles.getAccepted()) - .toString(); - - } - -} diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/configdata/ConfigDataPropertiesHolder.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/configdata/ConfigDataPropertiesHolder.java new file mode 100644 index 0000000000..2676efa71b --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/configdata/ConfigDataPropertiesHolder.java @@ -0,0 +1,104 @@ +/* + * 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.commons.configdata; + +import org.springframework.boot.bootstrap.ConfigurableBootstrapContext; +import org.springframework.boot.context.config.ConfigDataLocationResolverContext; +import org.springframework.boot.context.properties.bind.Bindable; +import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties; +import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties; +import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties; + +import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.registerSingle; + +/** + * @author wind57 + */ +public record ConfigDataPropertiesHolder(KubernetesClientProperties clientProperties, + ConfigMapConfigProperties configMapProperties, SecretsConfigProperties secretsProperties) { + + private static final Class CONFIGMAP_PROPERTIES_CLASS = ConfigMapConfigProperties.class; + + private static final Class SECRETS_PROPERTIES_CLASS = SecretsConfigProperties.class; + + private static final Class CLIENT_PROPERTIES_CLASS = KubernetesClientProperties.class; + + static ConfigDataPropertiesHolder of(ConfigDataLocationResolverContext context) { + + KubernetesClientProperties clientProperties; + ConfigMapConfigProperties configMapProperties = null; + SecretsConfigProperties secretsProperties = null; + + Binder binder = context.getBinder(); + + boolean configEnabled = binder.bind("spring.cloud.kubernetes.config.enabled", boolean.class).orElse(true); + if (configEnabled) { + configMapProperties = binder.bindOrCreate(ConfigMapConfigProperties.PREFIX, CONFIGMAP_PROPERTIES_CLASS); + } + + boolean secretsEnabled = binder.bind("spring.cloud.kubernetes.secrets.enabled", boolean.class).orElse(true); + if (secretsEnabled) { + secretsProperties = binder.bindOrCreate(SecretsConfigProperties.PREFIX, SECRETS_PROPERTIES_CLASS); + } + + String namespace = binder.bind("spring.cloud.kubernetes.client.namespace", String.class) + .orElse(binder.bind("kubernetes.namespace", String.class).orElse("")); + clientProperties = clientProperties(context, namespace); + + registerProperties(context, clientProperties, configMapProperties, secretsProperties); + return new ConfigDataPropertiesHolder(clientProperties, configMapProperties, secretsProperties); + } + + private static void registerProperties(ConfigDataLocationResolverContext resolverContext, + KubernetesClientProperties clientProperties, ConfigMapConfigProperties configMapProperties, + SecretsConfigProperties secretsProperties) { + + ConfigurableBootstrapContext bootstrapContext = resolverContext.getBootstrapContext(); + + registerSingle(bootstrapContext, CLIENT_PROPERTIES_CLASS, clientProperties, + "configDataKubernetesClientProperties"); + + if (configMapProperties != null) { + registerSingle(bootstrapContext, CONFIGMAP_PROPERTIES_CLASS, configMapProperties, + "configDataConfigMapConfigProperties"); + } + + if (secretsProperties != null) { + registerSingle(bootstrapContext, SECRETS_PROPERTIES_CLASS, secretsProperties, + "configDataSecretsConfigProperties"); + } + + } + + private static KubernetesClientProperties clientProperties(ConfigDataLocationResolverContext context, + String namespace) { + KubernetesClientProperties kubernetesClientProperties; + ConfigurableBootstrapContext bootstrapContext = context.getBootstrapContext(); + if (bootstrapContext.isRegistered(CLIENT_PROPERTIES_CLASS) + && bootstrapContext.get(CLIENT_PROPERTIES_CLASS) != null) { + kubernetesClientProperties = bootstrapContext.get(CLIENT_PROPERTIES_CLASS).withNamespace(namespace); + } + else { + kubernetesClientProperties = context.getBinder() + .bindOrCreate(KubernetesClientProperties.PREFIX, Bindable.of(CLIENT_PROPERTIES_CLASS)) + .withNamespace(namespace); + } + return kubernetesClientProperties; + } + +} diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLoader.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataLoader.java similarity index 92% rename from spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLoader.java rename to spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataLoader.java index b3fe92e4cb..74ab1724ce 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLoader.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataLoader.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.cloud.kubernetes.commons.config; +package org.springframework.cloud.kubernetes.commons.configdata; import java.io.IOException; import java.util.ArrayList; @@ -26,6 +26,8 @@ import org.springframework.boot.context.config.ConfigDataLoader; import org.springframework.boot.context.config.ConfigDataLoaderContext; import org.springframework.boot.context.config.ConfigDataResourceNotFoundException; +import org.springframework.cloud.kubernetes.commons.config.ConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.commons.config.SecretsPropertySourceLocator; import org.springframework.core.Ordered; import org.springframework.core.env.Environment; import org.springframework.core.env.PropertySource; diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataLocationResolver.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataLocationResolver.java new file mode 100644 index 0000000000..8430b53833 --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataLocationResolver.java @@ -0,0 +1,128 @@ +/* + * 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.commons.configdata; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jakarta.annotation.Nonnull; +import reactor.util.annotation.NonNull; + +import org.springframework.boot.context.config.ConfigDataLocation; +import org.springframework.boot.context.config.ConfigDataLocationNotFoundException; +import org.springframework.boot.context.config.ConfigDataLocationResolver; +import org.springframework.boot.context.config.ConfigDataLocationResolverContext; +import org.springframework.boot.context.config.ConfigDataResourceNotFoundException; +import org.springframework.boot.context.config.Profiles; +import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; +import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties; +import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties; +import org.springframework.core.Ordered; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; +import org.springframework.core.env.StandardEnvironment; + +import static org.springframework.boot.cloud.CloudPlatform.KUBERNETES; +import static org.springframework.util.ClassUtils.isPresent; + +/** + * @author Ryan Baxter + * @author wind57 + */ +public abstract class KubernetesConfigDataLocationResolver + implements ConfigDataLocationResolver, Ordered { + + private static final boolean RETRY_IS_PRESENT = isPresent("org.springframework.retry.annotation.Retryable", null); + + protected final String getPrefix() { + return "kubernetes:"; + } + + @Override + public final int getOrder() { + return -1; + } + + @Override + public final boolean isResolvable(@Nonnull ConfigDataLocationResolverContext context, ConfigDataLocation location) { + return location.hasPrefix(getPrefix()) + && (KUBERNETES.isEnforced(context.getBinder()) || KUBERNETES.isDetected(new StandardEnvironment())); + } + + @Override + public final List resolve(@NonNull ConfigDataLocationResolverContext context, + @Nonnull ConfigDataLocation location) + throws ConfigDataLocationNotFoundException, ConfigDataResourceNotFoundException { + return Collections.emptyList(); + } + + @Override + public final List resolveProfileSpecific( + @Nonnull ConfigDataLocationResolverContext resolverContext, @NonNull ConfigDataLocation location, + @Nonnull Profiles profiles) throws ConfigDataLocationNotFoundException { + + ConfigDataPropertiesHolder properties = ConfigDataPropertiesHolder.of(resolverContext); + + Map kubernetesConfigData = new HashMap<>(); + kubernetesConfigData.put("spring.cloud.kubernetes.client.namespace", properties.clientProperties().namespace()); + String applicationName = resolverContext.getBinder().bind("spring.application.name", String.class).orElse(null); + if (applicationName != null) { + kubernetesConfigData.put("spring.application.name", applicationName); + } + + Environment environment = environment(kubernetesConfigData, profiles); + KubernetesNamespaceProvider namespaceProvider = kubernetesNamespaceProvider(environment); + registerBeans(resolverContext, location, profiles, properties, namespaceProvider); + + KubernetesConfigDataResource resource = new KubernetesConfigDataResource(location.isOptional(), profiles, + environment); + + return List.of(resource); + } + + protected abstract void registerBeans(ConfigDataLocationResolverContext resolverContext, + ConfigDataLocation location, Profiles profiles, ConfigDataPropertiesHolder properties, + KubernetesNamespaceProvider namespaceProvider); + + protected final boolean isRetryEnabledForConfigMap(ConfigMapConfigProperties configMapProperties) { + return RETRY_IS_PRESENT && configMapProperties != null && configMapProperties.retry().enabled() + && configMapProperties.failFast(); + } + + protected final boolean isRetryEnabledForSecrets(SecretsConfigProperties secretsProperties) { + return RETRY_IS_PRESENT && secretsProperties != null && secretsProperties.retry().enabled() + && secretsProperties.failFast(); + } + + private KubernetesNamespaceProvider kubernetesNamespaceProvider(Environment environment) { + return new KubernetesNamespaceProvider(environment); + } + + private Environment environment(Map kubernetesConfigData, Profiles profiles) { + PropertySource> propertySource = new MapPropertySource("kubernetesConfigData", + kubernetesConfigData); + ConfigurableEnvironment environment = new StandardEnvironment(); + environment.getPropertySources().addLast(propertySource); + environment.setActiveProfiles(profiles.getAccepted().toArray(new String[0])); + return environment; + } + +} diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataResource.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataResource.java new file mode 100644 index 0000000000..e8e716a7b1 --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataResource.java @@ -0,0 +1,48 @@ +/* + * 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.commons.configdata; + +import java.util.List; + +import org.springframework.boot.context.config.ConfigDataResource; +import org.springframework.boot.context.config.Profiles; +import org.springframework.core.env.Environment; + +/** + * @author Ryan Baxter + */ +public final class KubernetesConfigDataResource extends ConfigDataResource { + + private final Profiles profiles; + + private final Environment environment; + + KubernetesConfigDataResource(boolean optional, Profiles profiles, Environment environment) { + super(optional); + this.profiles = profiles; + this.environment = environment; + } + + List getAcceptedProfiles() { + return this.profiles.getAccepted(); + } + + Environment getEnvironment() { + return this.environment; + } + +} diff --git a/spring-cloud-kubernetes-commons/src/main/resources/META-INF/spring.factories b/spring-cloud-kubernetes-commons/src/main/resources/META-INF/spring.factories index 03349b4bc7..dc467383f0 100644 --- a/spring-cloud-kubernetes-commons/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-kubernetes-commons/src/main/resources/META-INF/spring.factories @@ -3,4 +3,4 @@ org.springframework.cloud.kubernetes.commons.config.KubernetesBootstrapConfigura # ConfigData Loaders org.springframework.boot.context.config.ConfigDataLoader=\ -org.springframework.cloud.kubernetes.commons.config.KubernetesConfigDataLoader +org.springframework.cloud.kubernetes.commons.configdata.KubernetesConfigDataLoader diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SourceDataFlattenerTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SourceDataFlattenerTests.java index 02bd422f3d..783c55248a 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SourceDataFlattenerTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SourceDataFlattenerTests.java @@ -27,6 +27,11 @@ */ class SourceDataFlattenerTests { + @Test + void testEmpty() { + Assertions.assertThat(SourceData.emptyRecord("name").sourceData()).isEmpty(); + } + /** *
 	 *     - nameA -> [a, b]
diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SourceDataTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SourceDataTests.java
deleted file mode 100644
index 3c62079601..0000000000
--- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SourceDataTests.java
+++ /dev/null
@@ -1,32 +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.commons.config;
-
-import org.assertj.core.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-/**
- * @author wind57
- */
-class SourceDataTests {
-
-	@Test
-	void testEmpty() {
-		Assertions.assertThat(SourceData.emptyRecord("name").sourceData()).isEmpty();
-	}
-
-}
diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLoaderTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataLoaderTests.java
similarity index 95%
rename from spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLoaderTests.java
rename to spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataLoaderTests.java
index 0ce2a6dcaf..9ba9d0f909 100644
--- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLoaderTests.java
+++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataLoaderTests.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.springframework.cloud.kubernetes.commons.config;
+package org.springframework.cloud.kubernetes.commons.configdata;
 
 import java.io.IOException;
 import java.util.List;
@@ -27,6 +27,8 @@
 import org.springframework.boot.context.config.ConfigData;
 import org.springframework.boot.context.config.ConfigDataLoaderContext;
 import org.springframework.boot.context.config.Profiles;
+import org.springframework.cloud.kubernetes.commons.config.ConfigMapPropertySourceLocator;
+import org.springframework.cloud.kubernetes.commons.config.SecretsPropertySourceLocator;
 import org.springframework.core.env.ConfigurableEnvironment;
 import org.springframework.core.env.PropertySource;
 import org.springframework.mock.env.MockEnvironment;
@@ -50,8 +52,8 @@ class KubernetesConfigDataLoaderTests {
 
 	private static final ConfigurableEnvironment ENVIRONMENT = new MockEnvironment();
 
-	private static final KubernetesConfigDataResource EMPTY_RESOURCE = new KubernetesConfigDataResource(null, null,
-			null, false, PROFILES, ENVIRONMENT);
+	private static final KubernetesConfigDataResource EMPTY_RESOURCE = new KubernetesConfigDataResource(false, PROFILES,
+			ENVIRONMENT);
 
 	/**
 	 * we do not override this method in our implementation, so it should report true for
diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolverTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataLocationResolverTests.java
similarity index 84%
rename from spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolverTests.java
rename to spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataLocationResolverTests.java
index b73eaa1196..774f1481f6 100644
--- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolverTests.java
+++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/configdata/KubernetesConfigDataLocationResolverTests.java
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-package org.springframework.cloud.kubernetes.commons.config;
+package org.springframework.cloud.kubernetes.commons.configdata;
 
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
-import java.util.function.Supplier;
 
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.Test;
@@ -32,9 +31,11 @@
 import org.springframework.boot.context.config.Profiles;
 import org.springframework.boot.context.properties.bind.Binder;
 import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
-import org.springframework.boot.logging.DeferredLogFactory;
 import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
 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.SecretsConfigProperties;
 import org.springframework.mock.env.MockEnvironment;
 
 import static org.springframework.cloud.kubernetes.commons.config.ReadType.BATCH;
@@ -44,15 +45,16 @@
  */
 class KubernetesConfigDataLocationResolverTests {
 
-	private static final DeferredLogFactory FACTORY = Supplier::get;
-
 	// implementation that does nothing when registerBeans is called
-	private static final KubernetesConfigDataLocationResolver NOOP_RESOLVER = new KubernetesConfigDataLocationResolver(
-			FACTORY) {
+	private static final KubernetesConfigDataLocationResolver NOOP_RESOLVER = new KubernetesConfigDataLocationResolver() {
+
 		@Override
 		protected void registerBeans(ConfigDataLocationResolverContext resolverContext, ConfigDataLocation location,
-				Profiles profiles, PropertyHolder propertyHolder, KubernetesNamespaceProvider namespaceProvider) {
+				Profiles profiles, ConfigDataPropertiesHolder properties,
+				KubernetesNamespaceProvider namespaceProvider) {
+
 		}
+
 	};
 
 	private static final ConfigDataLocationResolverContext RESOLVER_CONTEXT = Mockito
@@ -111,6 +113,7 @@ void testResolve() {
 	@Test
 	void testResolveProfileSpecificOne() {
 
+		StorePropertiesResolver storePropertiesResolver = new StorePropertiesResolver();
 		MockEnvironment environment = new MockEnvironment();
 		environment.setProperty("spring.application.name", "k8s-app-name");
 		environment.setProperty("spring.cloud.kubernetes.client.namespace", "non-default-namespace");
@@ -122,7 +125,7 @@ void testResolveProfileSpecificOne() {
 
 		Profiles profiles = Mockito.mock(Profiles.class);
 		ConfigDataLocation configDataLocation = ConfigDataLocation.of("kubernetes:abc");
-		List result = NOOP_RESOLVER.resolveProfileSpecific(RESOLVER_CONTEXT,
+		List result = storePropertiesResolver.resolveProfileSpecific(RESOLVER_CONTEXT,
 				configDataLocation, profiles);
 
 		Assertions.assertThat(result.size()).isEqualTo(1);
@@ -132,9 +135,10 @@ void testResolveProfileSpecificOne() {
 			.assertThat(result.get(0).getEnvironment().getRequiredProperty("spring.cloud.kubernetes.client.namespace"))
 			.isEqualTo("non-default-namespace");
 		// ensures that we called 'bindOrCreate' and as such @Default is picked-up
-		Assertions.assertThat(result.get(0).getProperties().userAgent())
+		Assertions.assertThat(storePropertiesResolver.kubernetesClientProperties.userAgent())
 			.isEqualTo("Spring-Cloud-Kubernetes-Application");
-		Assertions.assertThat(result.get(0).getProperties().namespace()).isEqualTo("non-default-namespace");
+		Assertions.assertThat(storePropertiesResolver.kubernetesClientProperties.namespace())
+			.isEqualTo("non-default-namespace");
 
 	}
 
@@ -149,6 +153,7 @@ void testResolveProfileSpecificOne() {
 	@Test
 	void testResolveProfileSpecificTwo() {
 
+		StorePropertiesResolver storePropertiesResolver = new StorePropertiesResolver();
 		MockEnvironment environment = new MockEnvironment();
 		environment.setProperty("spring.application.name", "k8s-app-name");
 		environment.setProperty("kubernetes.namespace", "non-default-namespace");
@@ -166,7 +171,7 @@ void testResolveProfileSpecificTwo() {
 
 		Profiles profiles = Mockito.mock(Profiles.class);
 		ConfigDataLocation configDataLocation = ConfigDataLocation.of("kubernetes:abc");
-		List result = NOOP_RESOLVER.resolveProfileSpecific(RESOLVER_CONTEXT,
+		List result = storePropertiesResolver.resolveProfileSpecific(RESOLVER_CONTEXT,
 				configDataLocation, profiles);
 
 		Assertions.assertThat(result.size()).isEqualTo(1);
@@ -176,8 +181,9 @@ void testResolveProfileSpecificTwo() {
 			.assertThat(result.get(0).getEnvironment().getRequiredProperty("spring.cloud.kubernetes.client.namespace"))
 			.isEqualTo("non-default-namespace");
 		// ensures we bind existing from bootstrap context, and not call 'bindOrCreate'
-		Assertions.assertThat(result.get(0).getProperties().userAgent()).isEqualTo("user-agent");
-		Assertions.assertThat(result.get(0).getProperties().namespace()).isEqualTo("non-default-namespace");
+		Assertions.assertThat(storePropertiesResolver.kubernetesClientProperties.userAgent()).isEqualTo("user-agent");
+		Assertions.assertThat(storePropertiesResolver.kubernetesClientProperties.namespace())
+			.isEqualTo("non-default-namespace");
 	}
 
 	/**
@@ -253,6 +259,7 @@ void testResolveProfileSpecificFour() {
 	 */
 	@Test
 	void testResolveProfileSpecificFive() {
+		StorePropertiesResolver storePropertiesResolver = new StorePropertiesResolver();
 		MockEnvironment environment = new MockEnvironment();
 		ConfigurationPropertySources.attach(environment);
 		Binder binder = new Binder(ConfigurationPropertySources.get(environment));
@@ -262,11 +269,10 @@ void testResolveProfileSpecificFive() {
 
 		Profiles profiles = Mockito.mock(Profiles.class);
 		ConfigDataLocation configDataLocation = ConfigDataLocation.of("kubernetes:abc");
-		List result = NOOP_RESOLVER.resolveProfileSpecific(RESOLVER_CONTEXT,
-				configDataLocation, profiles);
+		storePropertiesResolver.resolveProfileSpecific(RESOLVER_CONTEXT, configDataLocation, profiles);
 
 		// we have @DefaultValue("false") boolean enabled
-		Assertions.assertThat(result.get(0).getSecretsConfigProperties().enabled()).isFalse();
+		Assertions.assertThat(storePropertiesResolver.secretsConfigProperties.enabled()).isFalse();
 	}
 
 	/**
@@ -275,6 +281,7 @@ void testResolveProfileSpecificFive() {
 	 */
 	@Test
 	void testResolveProfileSpecificSix() {
+		StorePropertiesResolver storePropertiesResolver = new StorePropertiesResolver();
 		MockEnvironment environment = new MockEnvironment();
 		environment.setProperty("spring.cloud.kubernetes.secret.enabled", "false");
 		environment.setProperty("spring.cloud.kubernetes.secrets.paths[0]", "a");
@@ -286,31 +293,15 @@ void testResolveProfileSpecificSix() {
 
 		Profiles profiles = Mockito.mock(Profiles.class);
 		ConfigDataLocation configDataLocation = ConfigDataLocation.of("kubernetes:abc");
-		List result = NOOP_RESOLVER.resolveProfileSpecific(RESOLVER_CONTEXT,
+		List result = storePropertiesResolver.resolveProfileSpecific(RESOLVER_CONTEXT,
 				configDataLocation, profiles);
 
 		// on the other hand, @Default will be picked here
-		Assertions.assertThat(result.get(0).getConfigMapProperties().enabled()).isTrue();
+		Assertions.assertThat(storePropertiesResolver.configMapConfigProperties.enabled()).isTrue();
 
 		// on the other hand, @Default will be picked here
-		Assertions.assertThat(result.get(0).getSecretsConfigProperties().includeProfileSpecificSources()).isTrue();
-	}
-
-	@Test
-	void testIsOptional() {
-		MockEnvironment environment = new MockEnvironment();
-		ConfigurationPropertySources.attach(environment);
-		Binder binder = new Binder(ConfigurationPropertySources.get(environment));
-
-		Mockito.when(RESOLVER_CONTEXT.getBinder()).thenReturn(binder);
-		Mockito.when(RESOLVER_CONTEXT.getBootstrapContext()).thenReturn(new DefaultBootstrapContext());
-
-		Profiles profiles = Mockito.mock(Profiles.class);
-		ConfigDataLocation configDataLocation = ConfigDataLocation.of("kubernetes:abc");
-		List result = NOOP_RESOLVER.resolveProfileSpecific(RESOLVER_CONTEXT,
-				configDataLocation, profiles);
-
-		Assertions.assertThat(result.get(0).isOptional()).isFalse();
+		Assertions.assertThat(storePropertiesResolver.configMapConfigProperties.includeProfileSpecificSources())
+			.isTrue();
 	}
 
 	@Test
@@ -331,7 +322,6 @@ void testProfiles() {
 
 		Assertions.assertThat(Arrays.stream(result.get(0).getEnvironment().getActiveProfiles()).toList())
 			.containsExactly("a", "b");
-		Assertions.assertThat(result.get(0).getProfiles()).isEqualTo("a,b");
 	}
 
 }
diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/configdata/StorePropertiesResolver.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/configdata/StorePropertiesResolver.java
new file mode 100644
index 0000000000..6aabc431fd
--- /dev/null
+++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/configdata/StorePropertiesResolver.java
@@ -0,0 +1,47 @@
+/*
+ * 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.commons.configdata;
+
+import org.springframework.boot.context.config.ConfigDataLocation;
+import org.springframework.boot.context.config.ConfigDataLocationResolverContext;
+import org.springframework.boot.context.config.Profiles;
+import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
+import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
+import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties;
+import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties;
+
+/**
+ * @author wind57
+ */
+class StorePropertiesResolver extends KubernetesConfigDataLocationResolver {
+
+	SecretsConfigProperties secretsConfigProperties;
+
+	ConfigMapConfigProperties configMapConfigProperties;
+
+	KubernetesClientProperties kubernetesClientProperties;
+
+	@Override
+	protected void registerBeans(ConfigDataLocationResolverContext resolverContext, ConfigDataLocation location,
+			Profiles profiles, ConfigDataPropertiesHolder properties, KubernetesNamespaceProvider namespaceProvider) {
+
+		secretsConfigProperties = properties.secretsProperties();
+		configMapConfigProperties = properties.configMapProperties();
+		kubernetesClientProperties = properties.clientProperties();
+	}
+
+}
diff --git a/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigDataLocationResolver.java b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigDataLocationResolver.java
index 077bb2b97e..b5dd302df7 100644
--- a/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigDataLocationResolver.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/main/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigDataLocationResolver.java
@@ -23,20 +23,19 @@
 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.KubernetesClientProperties;
 import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
 import org.springframework.cloud.kubernetes.commons.config.ConfigDataRetryableConfigMapPropertySourceLocator;
 import org.springframework.cloud.kubernetes.commons.config.ConfigDataRetryableSecretsPropertySourceLocator;
 import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties;
 import org.springframework.cloud.kubernetes.commons.config.ConfigMapPropertySourceLocator;
-import org.springframework.cloud.kubernetes.commons.config.KubernetesConfigDataLocationResolver;
 import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties;
 import org.springframework.cloud.kubernetes.commons.config.SecretsPropertySourceLocator;
+import org.springframework.cloud.kubernetes.commons.configdata.ConfigDataPropertiesHolder;
+import org.springframework.cloud.kubernetes.commons.configdata.KubernetesConfigDataLocationResolver;
 import org.springframework.cloud.kubernetes.fabric8.Fabric8AutoConfiguration;
 import org.springframework.context.ApplicationListener;
 import org.springframework.context.event.ContextClosedEvent;
-import org.springframework.core.env.Environment;
 
 import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.registerSingle;
 
@@ -45,17 +44,14 @@
  */
 public class Fabric8ConfigDataLocationResolver extends KubernetesConfigDataLocationResolver {
 
-	public Fabric8ConfigDataLocationResolver(DeferredLogFactory factory) {
-		super(factory);
-	}
-
 	@Override
 	protected void registerBeans(ConfigDataLocationResolverContext resolverContext, ConfigDataLocation location,
-			Profiles profiles, KubernetesConfigDataLocationResolver.PropertyHolder propertyHolder,
+			Profiles profiles, ConfigDataPropertiesHolder propertiesHolder,
 			KubernetesNamespaceProvider namespaceProvider) {
-		KubernetesClientProperties kubernetesClientProperties = propertyHolder.kubernetesClientProperties();
-		ConfigMapConfigProperties configMapProperties = propertyHolder.configMapConfigProperties();
-		SecretsConfigProperties secretsProperties = propertyHolder.secretsProperties();
+
+		KubernetesClientProperties kubernetesClientProperties = propertiesHolder.clientProperties();
+		ConfigMapConfigProperties configMapProperties = propertiesHolder.configMapProperties();
+		SecretsConfigProperties secretsProperties = propertiesHolder.secretsProperties();
 
 		ConfigurableBootstrapContext bootstrapContext = resolverContext.getBootstrapContext();
 		KubernetesClient kubernetesClient = registerConfigAndClient(bootstrapContext, kubernetesClientProperties);
@@ -97,9 +93,4 @@ private KubernetesClient registerConfigAndClient(ConfigurableBootstrapContext bo
 		return kubernetesClient;
 	}
 
-	@Override
-	protected KubernetesNamespaceProvider kubernetesNamespaceProvider(Environment environment) {
-		return new KubernetesNamespaceProvider(environment);
-	}
-
 }
diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigDataLocationResolverTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigDataLocationResolverTests.java
index 29c4406cd5..2f4473f8ab 100644
--- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigDataLocationResolverTests.java
+++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigDataLocationResolverTests.java
@@ -16,8 +16,6 @@
 
 package org.springframework.cloud.kubernetes.fabric8.config;
 
-import java.util.function.Supplier;
-
 import io.fabric8.kubernetes.client.Config;
 import io.fabric8.kubernetes.client.KubernetesClient;
 import org.assertj.core.api.Assertions;
@@ -30,7 +28,6 @@
 import org.springframework.boot.context.config.Profiles;
 import org.springframework.boot.context.properties.bind.Binder;
 import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
-import org.springframework.boot.logging.DeferredLogFactory;
 import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties;
 import org.springframework.cloud.kubernetes.commons.config.ConfigDataRetryableConfigMapPropertySourceLocator;
 import org.springframework.cloud.kubernetes.commons.config.ConfigDataRetryableSecretsPropertySourceLocator;
@@ -45,12 +42,10 @@
  */
 class Fabric8ConfigDataLocationResolverTests {
 
-	private static final DeferredLogFactory FACTORY = Supplier::get;
-
 	private static final ConfigDataLocationResolverContext RESOLVER_CONTEXT = Mockito
 		.mock(ConfigDataLocationResolverContext.class);
 
-	private static final Fabric8ConfigDataLocationResolver RESOLVER = new Fabric8ConfigDataLocationResolver(FACTORY);
+	private static final Fabric8ConfigDataLocationResolver RESOLVER = new Fabric8ConfigDataLocationResolver();
 
 	/*
 	 * both ConfigMapConfigProperties and SecretsConfigProperties are null, thus they are
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/fabric8/discovery/DummyConfigDataLocationResolver.java
similarity index 74%
rename from spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/DummyConfigDataLocationResolver.java
rename to spring-cloud-kubernetes-fabric8-discovery/src/test/java/org/springframework/cloud/kubernetes/fabric8/discovery/DummyConfigDataLocationResolver.java
index 8aa2366eb7..85c314df73 100644
--- 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/fabric8/discovery/DummyConfigDataLocationResolver.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package org.springframework.cloud.kubernetes;
+package org.springframework.cloud.kubernetes.fabric8.discovery;
 
 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;
+import org.springframework.cloud.kubernetes.commons.configdata.ConfigDataPropertiesHolder;
+import org.springframework.cloud.kubernetes.commons.configdata.KubernetesConfigDataLocationResolver;
 
 /**
  * @author wind57
@@ -30,14 +30,9 @@
 @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) {
+	protected void registerBeans(ConfigDataLocationResolverContext resolverContext,
+		ConfigDataLocation location, Profiles profiles, ConfigDataPropertiesHolder properties, KubernetesNamespaceProvider namespaceProvider) {
 
 	}
-
 }
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
index d92d10c6d0..df1469233d 100644
--- 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
@@ -1,2 +1,2 @@
 org.springframework.boot.context.config.ConfigDataLocationResolver=\
-org.springframework.cloud.kubernetes.DummyConfigDataLocationResolver
+org.springframework.cloud.kubernetes.fabric8.discovery.DummyConfigDataLocationResolver