Search code examples
spring-cloud-config

spring cloud config multiple profiles


I want to setup multiple profiles for my spring_cloud_config_server.

Here is my yml file:

server:
  port: "2000"

spring:
  profiles:
    active: native
  application:
    name: config-server
  cloud:
    config:
      server:
        native:
          search-locations: file:///opt/app/configuration

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8260/eureka

logging:
  level:
    org:
      springframework: INFO
---
spring:
  profiles: docker
  application:
    name: config-server
  cloud:
    config:
      server:
        native:
          search-locations: file:/opt/app/configuration

server:
  port: "2000"

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8260/eureka

logging:
  level:
    org:
      springframework: INFO

When I run the app using the "native" profile using the following command

java -jar app.jar

or

java -jar -Dspring.profiles.active=native app.jar

The app running good. When I run the app using the "docker" profile using the following command

java -jar -Dspring.profiles.active=docker app.jar

The app exits with Exception:

ERROR o.s.b.w.e.tomcat.TomcatStarter - Error starting Tomcat context. Exception: org.springframework.beans.factory.BeanCreationException. Message: Error creating bean with name 'servletEndpointRegistrar' defined in class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/web/ServletEndpointManagementContextConfiguration$WebMvcServletEndpointManagementContextConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.actuate.endpoint.web.ServletEndpointRegistrar]: Factory method 'servletEndpointRegistrar' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'healthEndpoint' defined in class path resource [org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.actuate.health.HealthEndpoint]: Factory method 'healthEndpoint' threw exception; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'configServerHealthIndicator' defined in class path resource [org/springframework/cloud/config/server/config/EnvironmentRepositoryConfiguration.class]: Unsatisfied dependency expressed through method 'configServerHealthIndicator' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.cloud.config.server.config.CompositeConfiguration': Unsatisfied dependency expressed through method 'setEnvironmentRepos' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultEnvironmentRepository' defined in class path resource [org/springframework/cloud/config/server/config/DefaultRepositoryConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: You need to configure a uri for the git repository.

The root cause is:

Exception: You need to configure a uri for the git repository.

Is my yml file correct for the two profiles? Did I miss anything to make it work for both profiles?


Solution

  • Default behavior of Spring Cloud Config Server is logic for git profile. So it is trying to find property spring.cloud.config.server.git.uri which you don't have.

    To fix you issue you need to have native profile enabled for both cases. Native configuration starts working only when 'native' profile is active:

    public class EnvironmentRepositoryConfiguration { 
    ......
    @Configuration
    @ConditionalOnMissingBean(EnvironmentRepository.class)
    @Profile("native")
    class NativeRepositoryConfiguration {
    
      @Bean
      public NativeEnvironmentRepository 
         nativeEnvironmentRepository(NativeEnvironmentRepositoryFactory factory,
            NativeEnvironmentProperties environmentProperties) {
        return factory.build(environmentProperties);
      }
    }
    ......
    

    see more here: https://github.com/spring-cloud/spring-cloud-config/blob/master/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EnvironmentRepositoryConfiguration.java#L215

    Since Spring Boot supports multiple profiles in your particular case I would recommend to use "including" additional profiles feature of Spring Boot. See: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html#boot-features-adding-active-profiles

    Basically your application.yml configuration will look like this:

    spring.profiles: some-profile-1
    spring.profiles.include:
      - native
    # specific configuration for 'some-profile-1'
    
    ---
    
    spring.profiles: some-profile-2
    spring.profiles.include:
      - native
    # specific configuration for 'some-profile-2'
    

    And you will just enable active profile by passing -Dspring.profiles.active=some-profile-1 (or 2)