spring-cloud-config
spring-cloud-config copied to clipboard
S3 Support - Sharing Configuration With All Applications
Hello,
I was reading the documentation section Sharing Configuration With All Applications, and there is no support for the S3 backend. Are you aware is there is a technical limitation to add such support? or if that would be something worth doing?
I was looking at the code in the AwsS3EnvironmentRepository, and with my limited knowledge of the project, I was thinking it could "just" be looking for the application*
files as well to see if there was a shared properties already defined.
I know it is not specified that it would work, but I believe it should. Have you tried it?
Yes I tried, it does not work.
For reference regarding the test. We have our local development environment running with the configuration service using the git back-end, but our cloud dev/test/stage/prod environments runs with the S3 back-end. The git repository is configured to push to S3 on every commit to default branch. I added a file application.yml
test: bar-01
I already had a file for my-service-configuration.yml
admin:
endpoints:
enabled: true
Now on my local (using git back-end) instance, when I query the config-service for this configuration http://localhost:8888/my-service-configuration.yml
I get
admin:
endpoints:
enabled: true
test: bar-01
In the cloud instance (using S3 back-end) of the config service, if I query the same http://ecs-lb-internal.local:8888/my-service-configuration.yml
, I get
admin:
endpoints:
enabled: true
Can you provide a complete, minimal, verifiable sample that reproduces the problem? It should be available as a GitHub (or similar) project or attached to this issue as a zip file.
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Hello, I don't specially want to provide you with a S3 bucket for you to develop. Could you share with me a S3 bucket and some credential to access it. It is very straight forward to setup an example using nothing else than the default setup explain in there: https://docs.spring.io/spring-cloud-config/docs/current/reference/html/#_aws_s3_backend. Once you provide me an access to a S3 bucket, I can start up a config server in Heroku to show case the issue.
If it is too complicated for you, then I will try to have a look, but I might need a bit more than 7 days, could you please keep the issue open a bit longer to give me some time to setup everything? Do you think it would be a nice feature to have? I could help develop it.
I guess we need to figure out whether this is a feature enhancement or a bug, that is what I am trying to get at with the sample. I can try and reproduce it, but if you know this feature is not yet implemented and you want to contribute code to support it, we always welcome contributions.
From what I've looked in the code in https://github.com/spring-cloud/spring-cloud-config/blob/main/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepository.java, it does not look implemented, I would like to see if I can port some of the logic from the FileSystem BE to the S3 BE, (via a shared component). If by any chance you know where is the shareable configuration implemented in the FS BE, it would help. But it is also possible that the S3 API might not allow to do all you can do with a FS, so if I see an obvious blocker, I'll document it here.
Every EnvironmentRepository
implemention will implement a findOne
method. This method is passed an application
String. If the application variable does not equal application
, ie its a specific application name, then we add it as a comma separated value, see
https://github.com/spring-cloud/spring-cloud-config/blob/main/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java#L222
Hello, @sp4ce
Once you provide me an access to a S3 bucket, I can start up a config server in Heroku to show case the issue.
As far as I understood you need access to some S3 bucket. If it's so then it's not necessary to rent one on Amazon. You can just use minio. Startup a container locally or using test container.
I am also having same issue shared configurations across all microservices doesn't work for S3 implementation. If we look at AwsS3EnvironmentRepository
and another implementation where it works ex : AwsSecretsManagerEnvironmentRepository
we can see the clear difference between implementation logic how it identifies the resource to use.
In S3 implementation it doesn't load the default config configured via spring.cloud.config.server.default-application-name
if it has an application name passed to AwsS3EnvironmentRepository.findOne()
method. It should do a check and see if it's not same as default name then it should load the default configuration file. Same logic should be applied in conjunction with the profile name for the variable spring.cloud.config.server.default-profile
.
If I have a client service name as service-one
and client profile set as dev1
with server having default app name as application
and default profile name as default
then it should load all these files from S3 service-one-dev1.yml
, application-dev1.yml
, service-one-default.yml
, application-default.yml
, service-one.yml
, application.yml
in that order of-course with the hierarchy and order like it's for other implementation like file based etc. Currently spring with S3 will resolve ONLY service-one-dev1.yml
it doesn't even load service-one-default.yml
and service-one.yml
let apart files like application-dev1.yml
, application-default.yml
and application.yml
files.
Logic should be same like other implementations(like Secret manager, Native etc) it was overlooked I guess. Code fix seems to be simple. It's virtually impossible to write same logic without doing complete copy paste of the code as most of the methods are private with almost nothing being extensible.
Is it possible to get some traction on this, looking at history of this issue I am wondering the such an active community this has not been picked up and addressed yet. Is there any issue or challenge that I don't forsee that could be a blocking for this.
@AjitDas can you try Spring Cloud 2022.0.2-SNAPSHOT? This issue was recently closed which seems related https://github.com/spring-cloud/spring-cloud-config/issues/1611
thanks @ryanjbaxter for the info. I looked at the code change and it probably solves one part of the problem where it can read profile specific as well as without profile file for a given microservice name. However it still doesn't address spring.cloud.config.server.default-application-name
and spring.cloud.config.server.default-profile
keys to read the configuration shared across multiple micro services. Is there any specific branch I can verify the code to see if it has details what I am looking for. Thanks once again
@AjitDas the changes should be in the main branch if you want to try it out
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
This issue still exists as I mentioned it doesn't handle identifying resources via spring.cloud.config.server.default-application-name
and spring.cloud.config.server.default-profile
properties when specified application name and profile are passed.
Looking at below code AwsS3EnvironmentRepository.java
it initialize the application
and profiles
variables without including the default values configured via config properties. This means if specifiedApplication
and specifiedProfiles
variables are passed in method arguments then it will not consider default application or profile that means common properties across multiple microservice will not be used. Can the implementation logic be something similar as AwsSecretManagerEnvironmentRepository
?
final String application = !StringUtils.hasText(specifiedApplication)
? serverProperties.getDefaultApplicationName() : specifiedApplication;
final String profiles = !StringUtils.hasText(specifiedProfiles) ? serverProperties.getDefaultProfile()
: specifiedProfiles;
final String label = !StringUtils.hasText(specifiedLabel) ? serverProperties.getDefaultLabel() : specifiedLabel;
String[] profileArray = parseProfiles(profiles); // can we add default to this array if it's not present already ?
String[] apps = new String[] { application }; // can we add default to this array if it's not present already ?
if (application != null) {
apps = StringUtils.commaDelimitedListToStringArray(application.replace(" ", ""));
}
@AjitDas thats makes sense, would you be interested in submitting a PR with then changes?