spring-cloud-config-server - File System Backend searchLocation with placeholder - spring

The search locations can contain placeholders for {application},
{profile} and {label}
I am trying to segregate my properties into distinct directories like /app1/dev, /app2/dev, /app2/prod
I have set the searchLocations property in application.yml of my configuration server as given below.
spring:
application:
name: config-server
profiles:
active: native
cloud:
config:
server:
native:
#searchLocations: file:./config/{application},file:./config/{application}/{profile} # Trial 01
searchLocations: file:./config/,file:./config/{application},file:./config/{application}/{profile} # Trial 02
I have kept the properties inside directories like zuul/prod, zuul/test
BUT the config server is unable to serve the configurations.
For the request http://localhost:8082/zuul/prod it gives
{"name":"zuul","profiles":["prod"],"label":"master","propertySources":[]}
Kindly clarify how to achieve this segregation.
Environment : Spring Cloud Angel.SR2 & 3

Related

Profile based Spring Cloud Config Server client with optional local developer properties

My Goal:
Having the Spring Cloud Config Server import active and provide a way for developers to have an optional property file on their machine.
My Config Server is up and running using org.springframework.cloud:spring-cloud-config-server:3.1.3 and #EnableConfigServer on the main class. Http requests to the concrete endpoint yield the expected result. This server should provide important environment configurations for a developer for his/her local setup.
$ curl http://localhost:8888/test-application/dev
{"name":"test-application","profiles":["dev"],"label":null,"version":null,"state":null,"propertySources":[{"name":"classpath:/cfg/test-application/application-dev.yml","source":{"server.port":1111}},{"name":"classpath:/cfg/test-application/application.yml","source":{"server.port":8000}}]}
Where localhost:8888 is my Config Server and test-application ist the name of the client application (defined via spring.application.name). The provided dev is the currently active profile on the client (The dev profile indicates a locally running software, there is no dev environment).
Clients configuration:
application.yml
spring:
application:
name: test-application
config:
import:
- configserver:http://localhost:8888 # <- pull the configuration from the configserver
- optional:file:/absolute/path/to/the/project/root/ # <- if there are any additional configuration files, use them
The client uses the following dependencies:
org.springframework.boot:spring-boot-starter-web:2.7.0
org.springframework.cloud:spring-cloud-starter-bootstrap:3.1.3
org.springframework.cloud:spring-cloud-starter:3.1.3
org.springframework.cloud:spring-cloud-starter-config:3.1.3
As shown above, the "base" application.yml configured server.port=8000 where the profile specific is set to server.port=1111. When reading the documentation this behaviour is correct. But my local developer configuration contains server.port=2222. This was ignored.
Here comes the problem:
When starting the client application, i can see the following log statements:
Fetching config from server at : http://localhost:8888
Located environment: name=test-application, profiles=[default], label=null, version=null, state=null
Located property source: [BootstrapPropertySource {name='bootstrapProperties-configClient'}, BootstrapPropertySource {name='bootstrapProperties-classpath:/cfg/test-application/application-dev.yml'}, BootstrapPropertySource {name='bootstrapProperties-classpath:/cfg/test-application/application.yml'}]
The following 1 profile is active: "dev"
Tomcat initialized with port(s): 1111 (http)
Initializing Spring embedded WebApplicationContext
Tomcat started on port(s): 1111 (http) with context path ''
Started TestApplicationKt in 2.234 seconds (JVM running for 2.762)
The configuration evaluation result from spring was to choose port 1111 instead of the wanted 2222 within the application-dev.yml located in the project root (developer config).
Wrapped up:
Three config files:
config server application.yml (port: 8000)
config server application-dev.yml (port: 1111)
project root developer config application-dev.yml (port: 2222) <- I want this file to have precedence over the other two.
When running the debugger, i see these found property sources within the injected Environment bean. The wanted developer file is within this list and the property source content is correct (server.port=2222).
Does anyone have an idea how to solve this problem?
I have created a project that reproduces this exact behaviour. Link to GitHub.
Thanks in advance!
Is the dev profile active when application is running in dev environment or it's also active when running locally?
Ideally you should have 2 different profiles for dev and local and you can enable config server only when dev profile is active.
You can rename your local property file as application-local.yml and disable spring cloud config when profile local is active.
You can put below code in bootstrap.yml(create new file beside application.yml) and remove config server configurations from application.yml
---
spring:
application:
name: test-application
config:
activate:
on-profile: dev
import:
- configserver:http://localhost:8888 # <- pull the configuration from the configserver
- optional:file:/absolute/path/to/the/project/root/ # <- if there are any additional configuration files, use them
---
spring:
application:
name: test-application
config:
activate:
on-profile: local
cloud:
config:
enabled: false
EDIT: Actual fix
Thanks for sharing reproducible example.
All you need to do is remove local application-dev.yml location reference from client application.yml and add it to configServer application.yml as shown in belolow screenshots.
/client/src/main/resources/application.yml
And put it in configServer application.yml at the end of search-locations. Order matters so please make sure you put overriding location/s at the end.
/configServer/src/main/resources/application.yml
Build and start both the applications and you will see client application server started on port 2222

Invalid config server configuration

I am on learning stage of Spring Cloud & using spring version 2.4.3 and spring-cloud-version
2020.0.1 and I created two property file
application.yml
spring:
application:
name: cloud-server
server:
port: 8888
bootstrap.yml
spring:
cloud:
config:
server:
git:
uri: https://github.com/************/insurance-config-server
default-label: main
but still I got following error
***************************
APPLICATION FAILED TO START
***************************
Description:
Invalid config server configuration.
Action:
If you are using the git profile, you need to set a Git URI in your configuration. If you are using a native profile and have spring.cloud.config.server.bootstrap=true, you need to use a composite configuration.
How to solve this kind of error?
Did you have a bootstrap.yml file?
I had the same problem. My project did not have a bootstrap.yml, but I specified a dev activity file in the IDEA startup configuration, which caused the same error as you did. The error could not be found bootstrap.yml on startup. After deleting dev in IDEA startup configuration, it can start normally.
If you are following the example in the book you referenced then I will suggest you move this
spring:
cloud:
config:
server:
git:
uri: https://github.com/************/insurance-config-server
default-label: main
to application.yml
That is what I did and it worked for me

spring boot - application yml for each developer

In my work the fields in application.yml are dynamics and each developer have another (dynamic) configuration. So, we have the general yml section, that relevant for all of us (and have updates from time to time) and the “private profile”
Like this:
spring:
profiles: default
configuration:
...
...
spring:
profiles: development1
configuration: ...
spring:
profiles: development2
configuration: ...
We have “small” problems with this (mistakes, conflicts, etc.) and we’re look for solution.
I think about separate yml file for each developer, such as:
spring:
profiles: development1
configuration:
yml-file: app_dev1.yml
spring:
profiles: development2
configuration:
yml-file: app_dev2.yml
but didn’t find how to do this…
Will be glad to know if it can be done? (or you have another way to separate the yml between us).
We do not want to set an application yaml with annotation (git issues again..), something like Environment Variables...
Spring boot by default loads application.yaml but in addition if you run with --spring.profiles.active=dev1 it will load file application-dev1.yaml
So you could create yaml file per developer + have some "common" configuration in application.yaml
With such an approach you won't need lines like:
spring:
profiles: dev1
... in any of the yaml files

Yml config files "Inheritance" with Spring boot

I couldn't find a straight answer online.
Do Spring Boot's yml files "inherit" from each other? I mean if I have:
application.yml which has
server:
port: 80
host: foo
and application-profile1.yml which has only
server:
port: 90
So if I start my Spring Boot with profile1 as active profile, will I also have server.host property set to foo?
Yes, application.yml file has higher precedence over any application-{profile}.yml file. Properties from profile specific yml file will override values from the default application.yml file and properties that do not exist in profile specific yml file will be loaded from the default one. It applies to .properties files as well as to bootstrap.yml or bootstrap.properties.
Spring Boot documentation mentions it in 72.7 Change configuration depending on the environment paragraph:
In this example the default port is 9000, but if the Spring profile ‘development’ is active then the port is 9001, and if ‘production’ is active then it is 0.
The YAML documents are merged in the order they are encountered (so later values override earlier ones).
To do the same thing with properties files you can use application-${profile}.properties to specify profile-specific values.
Here is my solution.
Assume application.yml:
spring:
profiles: default-server-config
server:
port: 9801
servlet:
context-path: '/ctp'
If I want use default-server-config profile, and use port 8080 in my application-dev.yml
application-dev.yml:
spring:
profiles:
include:
- default-server-config
- dev-config
---
spring:
profiles: dev-config
server:
port: 8080
Then -Dspring.profiles.active=dev

Spring cloud config in local dev mode

Is it possible to control if the application requires spring-config-server based on profile.
I want to pick properties from resource/... in say local-dev profile and use cloud-config only with a profile where there would be a config-server running.
You can disable using config-server for a specific profile. Please try to define the properties in bootstrap.yml like below. Please note, we should configure these settings only in bootstrap.yml. Setting these properties in application.yml will not work. In this case, local profile will be running only with local profiles in /resources folder. In dev profile, properties from config-server will override properties from resources/ folder.
spring:
profiles: local
cloud:
config:
enabled: false
---
spring:
profiles: dev
cloud:
config:
uri: http://<your config server>

Resources