Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to detect that a configmap is present #1682

Closed
c4rth opened this issue Aug 5, 2024 · 10 comments
Closed

How to detect that a configmap is present #1682

c4rth opened this issue Aug 5, 2024 · 10 comments
Milestone

Comments

@c4rth
Copy link

c4rth commented Aug 5, 2024

I have a spring boot 3 application deployed in Kubernetes and also a configmap
The spring app uses :
implementation("org.springframework.cloud:spring-cloud-starter")
implementation("org.springframework.cloud:spring-cloud-starter-kubernetes-fabric8-all")

In Kubernetes, the app has an environment variable SPRING_CLOUD_BOOTSTRAP_ENABLED to true.

I would like to verify that a configmap linked to the application is available and has been loaded.

rem: I don't known which values will be defined in it, I cannot check one value, I just want check its existence.

What I tried

  • I tried to detect this in an org.springframework.boot.env.EnvironmentPostProcessor (maybe not the best place) loaded with spring.factories
    Detect that the application is running in Kubernetes is easily done with CloudPlatform.KUBERNETES.isActive(environment)

  • But I don't find a way to detect the configmap.
    I tried in the EnvironmentPostProcessor to check the different property sources of the environment, I found one named 'KUBERNETES_NAMESPACE_PROPERTY_SOURCE' but with or without a configmap, it exists.
    And my EnvironmentPostProcessor is executed before my app starts and

  • I tried combinations:
    with and without org.springframework.cloud:spring-cloud-starter-bootstrap
    with and without SPRING_CLOUD_BOOTSTRAP_ENABLED

Here is the code of my EnvironmentPostProcessor

public class TestEnvironmentPostProcessor implements EnvironmentPostProcessor {

    private final Log log;

    public TestEnvironmentPostProcessor(DeferredLogFactory logFactory) {
        this.log = logFactory.getLog(getClass());
    }

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        if (isKubernetes(environment)) {
            log.info("Running in Kubernetes");
        } else {
            log.info("NOT running in Kubernetes");
            return;
        }
        environment.getPropertySources().forEach(ps -> {
            log.info(ps.getName() + " = " + ps.getClass().getName());
            if (ps.getName().equals("KUBERNETES_NAMESPACE_PROPERTY_SOURCE")) {
                log.info("--> KUBERNETES_NAMESPACE_PROPERTY_SOURCE");
                MapPropertySource mps = (MapPropertySource) ps;
                var str1 = Arrays.stream(mps.getPropertyNames()).map(key -> key + " = " + mps.getProperty(key))
                        .collect(Collectors.joining(", ", "{", "}"));
                log.info("properties = " + str1);
                var source = mps.getSource();
                var str2 = source.keySet().stream()
                        .map(key -> key + " = " + source.get(key))
                        .collect(Collectors.joining(", ", "{", "}"));
                log.info("source = " + str2);
                List.of("spring.application.name", "k8s.key1", "k8s.key2").forEach(key -> {
                var x= environment.getProperty(key);
                log.warn(key + " = " + x);
              });
            }
        });

    }

    private boolean isKubernetes(ConfigurableEnvironment environment) {
        return CloudPlatform.KUBERNETES.isActive(environment);
    }
}

An other strange thing: the TestEnvironmentPostProcessor runs before the app starts and after.
In both case the properties defined in configmap are unknow.
When my app has started, the values are known, here is the log

[           main] g.p.b.v.TestEnvironmentPostProcessor     : *******************************
[           main] g.p.b.v.TestEnvironmentPostProcessor     : Running in Kubernetes
[           main] g.p.b.v.TestEnvironmentPostProcessor     : configurationProperties = org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertySource
[           main] g.p.b.v.TestEnvironmentPostProcessor     : bootstrap = org.springframework.core.env.MapPropertySource
[           main] g.p.b.v.TestEnvironmentPostProcessor     : systemProperties = org.springframework.core.env.PropertiesPropertySource
[           main] g.p.b.v.TestEnvironmentPostProcessor     : systemEnvironment = org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource
[           main] g.p.b.v.TestEnvironmentPostProcessor     : random = org.springframework.boot.env.RandomValuePropertySource
[           main] g.p.b.v.TestEnvironmentPostProcessor     : cachedrandom = org.springframework.cloud.util.random.CachedRandomPropertySource
[           main] g.p.b.v.TestEnvironmentPostProcessor     : KUBERNETES_NAMESPACE_PROPERTY_SOURCE = org.springframework.core.env.MapPropertySource
[           main] g.p.b.v.TestEnvironmentPostProcessor     : --> KUBERNETES_NAMESPACE_PROPERTY_SOURCE
[           main] g.p.b.v.TestEnvironmentPostProcessor     : properties = {spring.cloud.kubernetes.client.namespace = default}
[           main] g.p.b.v.TestEnvironmentPostProcessor     : source = {spring.cloud.kubernetes.client.namespace = default}
[           main] g.p.b.v.TestEnvironmentPostProcessor     : springCloudClientHostInfo = org.springframework.core.env.MapPropertySource
[           main] g.p.b.v.TestEnvironmentPostProcessor     : spring.application.name = null
[           main] g.p.b.v.TestEnvironmentPostProcessor     : k8s.key1 = null
[           main] g.p.b.v.TestEnvironmentPostProcessor     : k8s.key2 = null

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.3.2)

[spring-app-virtual] [           main] o.s.c.k.commons.config.ConfigUtils       : ConfigMap name has not been set, taking it from property/env spring.application.name (default=application)
[spring-app-virtual] [           main] s.c.k.c.c.ConfigMapPropertySourceLocator : Config Map normalized sources : [{ config-map name : 'Optional[spring-app-virtual]', namespace : 'Optional.empty', prefix : '[ConfigUtils.Prefix@36417a54 name = 'DEFAULT']' }]
[spring-app-virtual] [           main] o.s.c.kubernetes.fabric8.Fabric8Utils    : configmap namespace from provider : default
[spring-app-virtual] [           main] o.s.c.k.f.config.Fabric8ConfigMapsCache  : Loaded all config maps in namespace 'default'
[spring-app-virtual] [           main] o.s.c.k.commons.config.ConfigUtils       : Found source with name : 'spring-app-virtual in namespace: 'default'
[spring-app-virtual] [           main] o.s.c.k.c.c.SourceDataEntriesProcessor   : The single property with name: [application.yaml] will be treated as a yaml file
[spring-app-virtual] [           main] s.c.k.c.c.ConfigMapPropertySourceLocator : paths property sources : []
[spring-app-virtual] [           main] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-configmap.spring-app-virtual.default'}]
[spring-app-virtual] [           main] o.s.c.k.commons.config.ConfigUtils       : Secret name has not been set, taking it from property/env spring.application.name (default=application)
[spring-app-virtual] [           main] o.s.c.k.c.c.SecretsPropertySourceLocator : Secrets normalized sources : [{ secret name : 'Optional[spring-app-virtual]', namespace : 'Optional.empty']
[spring-app-virtual] [           main] ubernetesProfileEnvironmentPostProcessor : 'kubernetes' already in list of active profiles
[spring-app-virtual] [           main] gae.piaz.boot.virtual.Application        : The following 1 profile is active: "kubernetes"
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : *******************************
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : Running in Kubernetes
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : configurationProperties = org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertySource
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : servletConfigInitParams = org.springframework.core.env.PropertySource$StubPropertySource
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : servletContextInitParams = org.springframework.core.env.PropertySource$StubPropertySource
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : systemProperties = org.springframework.core.env.PropertiesPropertySource
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : systemEnvironment = org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : random = org.springframework.boot.env.RandomValuePropertySource
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : springCloudDefaultProperties = org.springframework.cloud.bootstrap.BootstrapApplicationListener$ExtendedDefaultPropertySource
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : cachedrandom = org.springframework.cloud.util.random.CachedRandomPropertySource
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : KUBERNETES_NAMESPACE_PROPERTY_SOURCE = org.springframework.core.env.MapPropertySource
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : --> KUBERNETES_NAMESPACE_PROPERTY_SOURCE
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : properties = {spring.cloud.kubernetes.client.namespace = default}
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : source = {spring.cloud.kubernetes.client.namespace = default}
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : Config resource 'class path resource [application.yaml]' via location 'optional:classpath:/' = org.springframework.boot.env.OriginTrackedMapPropertySource
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : springCloudClientHostInfo = org.springframework.core.env.MapPropertySource
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : applicationConfig: [classpath:/application.yaml] = org.springframework.boot.env.OriginTrackedMapPropertySource
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : spring.application.name = spring-app-virtual
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : k8s.key1 = null
[spring-app-virtual] [           main] g.p.b.v.TestEnvironmentPostProcessor     : k8s.key2 = null
[spring-app-virtual] [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
[spring-app-virtual] [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 100 ms. Found 3 JPA repository interfaces.
[spring-app-virtual] [           main] led$OnBlockingOrReactiveDiscoveryEnabled : Condition ConditionalOnBlockingOrReactiveDiscoveryEnabled.OnBlockingOrReactiveDiscoveryEnabled on org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesCatalogWatchAutoConfiguration matched due to AnyNestedCondition 1 matched 1 did not; NestedCondition on ConditionalOnBlockingOrReactiveDiscoveryEnabled.OnBlockingOrReactiveDiscoveryEnabled.OnReactiveDiscoveryEnabled found non-matching nested conditions @ConditionalOnClass did not find required class 'org.springframework.web.reactive.function.client.WebClient'; NestedCondition on ConditionalOnBlockingOrReactiveDiscoveryEnabled.OnBlockingOrReactiveDiscoveryEnabled.OnBlockingDiscoveryEnabled @ConditionalOnProperty (spring.cloud.discovery.blocking.enabled) matched
[spring-app-virtual] [           main] o.s.cloud.context.scope.GenericScope     : BeanFactory id=aa14e53e-a512-3d44-9df4-9fdd14a1a107
[spring-app-virtual] [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration$DeferringLoadBalancerInterceptorConfig' of type [org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration$DeferringLoadBalancerInterceptorConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). The currently created BeanPostProcessor [lbRestClientPostProcessor] is declared through a non-static factory method on that class; consider declaring it as static instead.
[spring-app-virtual] [           main] trationDelegate$BeanPostProcessorChecker : Bean 'deferringLoadBalancerInterceptor' of type [org.springframework.cloud.client.loadbalancer.DeferringLoadBalancerInterceptor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [lbRestClientPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
[spring-app-virtual] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
[spring-app-virtual] [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
[spring-app-virtual] [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.26]
[spring-app-virtual] [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
[spring-app-virtual] [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1393 ms
[spring-app-virtual] [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
[spring-app-virtual] [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 6.5.2.Final
[spring-app-virtual] [           main] o.h.c.internal.RegionFactoryInitiator    : HHH000026: Second-level cache disabled
[spring-app-virtual] [           main] o.s.o.j.p.SpringPersistenceUnitInfo      : No LoadTimeWeaver setup: ignoring JPA class transformer
[spring-app-virtual] [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
[spring-app-virtual] [           main] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:testdb user=SA
[spring-app-virtual] [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
[spring-app-virtual] [           main] org.hibernate.orm.deprecation            : HHH90000025: H2Dialect does not need to be specified explicitly using 'hibernate.dialect' (remove the property setting and it will be selected by default)
[spring-app-virtual] [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
[spring-app-virtual] [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
[spring-app-virtual] [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
[spring-app-virtual] [           main] o.s.c.k.c.KubernetesNamespaceProvider    : Looking for service account namespace at: [/var/run/secrets/kubernetes.io/serviceaccount/namespace].
[spring-app-virtual] [           main] o.s.c.k.c.KubernetesNamespaceProvider    : Found service account namespace at: [/var/run/secrets/kubernetes.io/serviceaccount/namespace].
[spring-app-virtual] [           main] o.s.c.k.c.KubernetesNamespaceProvider    : Service account namespace value: /var/run/secrets/kubernetes.io/serviceaccount/namespace
[spring-app-virtual] [           main] bernetesDiscoveryClientAutoConfiguration : Will publish InstanceRegisteredEvent from blocking implementation
[spring-app-virtual] [           main] iscoveryClientHealthIndicatorInitializer : publishing InstanceRegisteredEvent
[spring-app-virtual] [           main] o.s.c.k.f.d.KubernetesCatalogWatch       : stateGenerator is of type: Fabric8EndpointsCatalogWatch
[spring-app-virtual] [           main] iguration$LoadBalancerCaffeineWarnLogger : Spring Cloud LoadBalancer is currently working with the default cache. While this cache implementation is useful for development and tests, it's recommended to use Caffeine cache in production.You can switch to using Caffeine cache, by adding it and org.springframework.cache.caffeine.CaffeineCacheManager to the classpath.
[spring-app-virtual] [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 17 endpoints beneath base path '/actuator'
[spring-app-virtual] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path '/'
[spring-app-virtual] [           main] gae.piaz.boot.virtual.Application        : Started Application in 5.525 seconds (process running for 5.715)
[spring-app-virtual] [           main] gae.piaz.boot.virtual.Application        : spring.application.name = spring-app-virtual
[spring-app-virtual] [           main] gae.piaz.boot.virtual.Application        : k8s.key1 = value1
[spring-app-virtual] [           main] gae.piaz.boot.virtual.Application        : k8s.key2 = value2

@ryanjbaxter
Copy link
Contributor

I would like to verify that a configmap linked to the application is available and has been loaded.

Can I ask why and what you are trying to accomplish by knowing this?

@c4rth
Copy link
Author

c4rth commented Aug 5, 2024

Sure.
I just would like to know when I start an application if a configmap is loaded, to validate that the deployments in k8s are ok.
Sometimes, the configmap definition is not right: name that doesn't match the spring app name, wrong namespace or not deployed.
It is simply to add a validation step.

@ryanjbaxter
Copy link
Contributor

One approach I can think of is to have a Bean which takes in all SourceDataEntriesProcessor or Fabric8ConfigMapPropertySource if you really want to by hyper-specific. You can look at the name of those PropertySources to determine whether one of them is the config map you are concerned about and if not throw an Exception. You could then use AbstractFailureAnalyze from Spring Boot to produce a FailureAnalysis object and provide a meaningful reason for the failure.

@c4rth
Copy link
Author

c4rth commented Aug 6, 2024

Thanks for this possible solution.

With spring.config.import: 'kubernetes:', I can find a CompositePropertySource named composite-configmap containing a Fabric8ConfigMapPropertySource containing all the properties of the configmap and if no configmap, the properties are empty.

With 'spring.cloud.bootstrap.enabled: true', no Fabric8ConfigMapPropertySource but a BootstrapPropertySource containing all the properties of the configmap and if no configmap, the properties are empty.

I prefer the 1st possibility, but the issue is if I add org.springframework.cloud:spring-cloud-starter-bootstrap or spring.cloud.bootstrap.enabled:, the app doesn't start.

@ryanjbaxter
Copy link
Contributor

You are going to have to provide more information than "the app doesn't start" for us to help

@c4rth
Copy link
Author

c4rth commented Aug 6, 2024

Indeed, sorry.

2024-08-06T16:16:50.748+01:00  WARN 1 --- [           main] [                                                 ] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'configMapPropertySourceLocator' defined in class path resource [org/springframework/cloud/kubernetes/fabric8/config/Fabric8BootstrapConfiguration.class]: Unsatisfied dependency expressed through method 'configMapPropertySourceLocator' parameter 0: No qualifying bean of type 'org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties' available: expected single matching bean but found 2: spring.cloud.kubernetes.config-org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties,configDataConfigMapConfigProperties
2024-08-06T16:16:50.749+01:00  INFO 1 --- [           main] [                                                 ] .s.b.a.l.ConditionEvaluationReportLogger : 

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2024-08-06T16:16:50.760+01:00 ERROR 1 --- [           main] [                                                 ] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method configMapPropertySourceLocator in org.springframework.cloud.kubernetes.fabric8.config.Fabric8BootstrapConfiguration required a single bean, but 2 were found:
	- spring.cloud.kubernetes.config-org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties: defined in unknown location
	- configDataConfigMapConfigProperties: a programmatically registered singleton

This may be due to missing parameter name information

Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

Ensure that your compiler is configured to use the '-parameters' flag.
You may need to update both your build tool settings as well as your IDE.
(See https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-6.x#parameter-name-retention)


2024-08-06T16:16:50.761+01:00 ERROR 1 --- [           main] [                                                 ] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'configMapPropertySourceLocator' defined in class path resource [org/springframework/cloud/kubernetes/fabric8/config/Fabric8BootstrapConfiguration.class]: Unsatisfied dependency expressed through method 'configMapPropertySourceLocator' parameter 0: No qualifying bean of type 'org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties' available: expected single matching bean but found 2: spring.cloud.kubernetes.config-org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties,configDataConfigMapConfigProperties
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:795) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:542) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:971) ~[spring-context-6.1.11.jar:6.1.11]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-context-6.1.11.jar:6.1.11]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.2.jar:3.3.2]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.2.jar:3.3.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.2.jar:3.3.2]
	at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:149) ~[spring-boot-3.3.2.jar:3.3.2]
	at org.springframework.cloud.bootstrap.BootstrapApplicationListener.bootstrapServiceContext(BootstrapApplicationListener.java:195) ~[spring-cloud-context-4.1.4.jar:4.1.4]
	at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:114) ~[spring-cloud-context-4.1.4.jar:4.1.4]
	at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:77) ~[spring-cloud-context-4.1.4.jar:4.1.4]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:185) ~[spring-context-6.1.11.jar:6.1.11]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:178) ~[spring-context-6.1.11.jar:6.1.11]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:156) ~[spring-context-6.1.11.jar:6.1.11]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:138) ~[spring-context-6.1.11.jar:6.1.11]
	at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136) ~[spring-boot-3.3.2.jar:3.3.2]
	at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:81) ~[spring-boot-3.3.2.jar:3.3.2]
	at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:64) ~[spring-boot-3.3.2.jar:3.3.2]
	at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118) ~[spring-boot-3.3.2.jar:3.3.2]
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112) ~[spring-boot-3.3.2.jar:3.3.2]
	at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:63) ~[spring-boot-3.3.2.jar:3.3.2]
	at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:370) ~[spring-boot-3.3.2.jar:3.3.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:330) ~[spring-boot-3.3.2.jar:3.3.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.2.jar:3.3.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.2.jar:3.3.2]
	at org.c4rth.virtual.Application.main(Application.java:21) ~[classes/:0.0.1-SNAPSHOT]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
	at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:91) ~[application/:na]
	at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:53) ~[application/:na]
	at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:58) ~[application/:na]
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties' available: expected single matching bean but found 2: spring.cloud.kubernetes.config-org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties,configDataConfigMapConfigProperties
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:218) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1420) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:904) ~[spring-beans-6.1.11.jar:6.1.11]
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:782) ~[spring-beans-6.1.11.jar:6.1.11]
	... 40 common frames omitted

@ryanjbaxter
Copy link
Contributor

Do you have any idea where this is coming from configDataConfigMapConfigProperties? Can you provide a sample?

@c4rth
Copy link
Author

c4rth commented Aug 24, 2024

Here is a sample repository https://github.com/c4rth/spring-k8s

The 'configDataConfigMapConfigProperties' is defined in method registerProperties of KubernetesConfigDataLocationResolver
For the other, I'm still looking.

@ryanjbaxter
Copy link
Contributor

OK looking at your sample gave me more clues.

Why are you specifying spring.config.import=kubernetes: and enabling Bootstrap? You are running into issues because we are trying to load configuration using two different approaches and this is not supported.

@c4rth
Copy link
Author

c4rth commented Aug 29, 2024

So spring.config.import=kubernetes: and Cloud Bootstrap are mutually exclusive.
OK, it's was not clear for me.
Maybe mentioning it in the documentation would be useful for others.
Thanks for your support and your patience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Status: Done
Development

No branches or pull requests

3 participants