Skip to content

Wildcard locations for configs causes files to be parsed multiple times on k8s #23160

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

Closed
leonard84 opened this issue Sep 1, 2020 · 11 comments
Closed
Assignees
Labels
type: bug A general bug
Milestone

Comments

@leonard84
Copy link
Contributor

With the release of 2.3 there where some changes to how config files were loaded. The new wildcard support causes files to be loaded multiple times if they are in mounted k8s configmaps. The reason is an implementation detail of k8s that uses double symlink indirection.

A mounted config map produces a layout like this:

/srv/config/.
/srv/config/..
/srv/config/..data -> ..2020_09_01_10_07_26.375746684
/srv/config/application-override.yml -> ..data/application-override.yml
/srv/config/..2020_09_01_10_07_26.375746684
/srv/config/..2020_09_01_10_07_26.375746684/application-override.yml

Spring will happily parse every file that it can find:

OriginTrackedMapCollectionPropertySource {name='applicationConfig: [config/2020_08_31_14_34_22.027190996/application-override.yml]'}
OriginTrackedMapCollectionPropertySource {name='applicationConfig: [config/data/application-override.yml]'}
OriginTrackedMapCollectionPropertySource {name='applicationConfig: [file:./config/application-override.yml]'}

This can cause weird errors, depending on the application.
Also note that for some reason the files in subdirs don't have the file: scheme.
I'd suggest to not parse files and directories starting with a .

Spring Boot version 2.3.1

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Sep 1, 2020
@philwebb philwebb added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Sep 1, 2020
@philwebb philwebb added this to the 2.3.x milestone Sep 1, 2020
@scottfrederick scottfrederick self-assigned this Oct 20, 2020
@scottfrederick
Copy link
Contributor

scottfrederick commented Oct 21, 2020

When a wildcard directory is configured as a search location, the code will only search one directory level deep to find property files. So just setting one additional search location with a wildcard won't cause the reported issue.

The scenario described can be reproduced by setting two additional search locations. Assuming /srv is the current working directory in this example, setting spring.config.additional-location=file:./config/application-override.yml,file:./config/*/application-override.yml gives the results shown. In this case the property source named file:./config/application-override.yml is loaded by the first location (without the wildcard), and the other two property sources are loaded by the second location (with the wildcard).

Also note that for some reason the files in subdirs don't have the file: scheme.

Property sources loaded by a location with a wildcard don't have the file: prefix in the name, so this observation is also consistent with the scenario above.

@leonard84 Can you confirm that your example has multiple additional search locations configured?

Setting two additional locations like this is a valid use-case, because it is reasonable for someone to set up a configuration with with configmaps mounted at multiple locations like /srv/config/application-override.yml, /srv/config/mysql/application-override.yml, /srv/config/redis/application-override.yml. Ignoring paths that have an element that starts with . does appear to be the best way to make this work as expected.

@leonard84
Copy link
Contributor Author

@scottfrederick we didn't configure any special parameters. Our working directory is /srv so /srv/config/ is one of the default scan locations.

@MinaFayez9
Copy link

MinaFayez9 commented Nov 9, 2020

This fix is causing running Sprint Boot on eclipse tomcat servers, not to pick up the configurations file, as eclipse deploys the application on a path containing "."
for example "D:\workspaces\eclipse.metadata.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps"
Can this fix be controlled by another system configuration for instance ?

@snicoll
Copy link
Member

snicoll commented Nov 9, 2020

Thank you @mena149f. We're aware of the problem and that's fixed in the upcoming 2.3.6.RELEASE, see #23983

@bo0ts
Copy link

bo0ts commented Nov 11, 2020

@snicoll Please consider 62aa1b7#commitcomment-44079277 This is not a fix.

@wilkinsona
Copy link
Member

@bo0ts Sorry, I don't understand why only ignoring .. is not a fix. Our goal is to avoid ignoring hidden files that start with a single . while continuing to ignore files that start with ... As far as we know, there's no reason not to ignore ..-prefixed files. It sounds like you have a reason but I don't understand your comment on the commit.

If you would like us to reconsider, please comment on #23983 and provide a complete and minimal sample that demonstrates the problem.

@bo0ts
Copy link

bo0ts commented Nov 11, 2020

@wilkinsona We are using fully qualified paths to set our config locations, e.g. -Dspring.config.location=classpath:/,classpath:/config/,file:./,file:./config/,/config/config1/..2020_10_27_21_10_29.547134956/application.properties,/config/config2/..2020_10_27_21_10_30.275048764/secret.properties,/config/config3/..2020_10_27_21_10_29.797568129/application.properties. (We collect those files with find . -type f ...)

This change breaks loading our configs and #23983 does nothing to alleviate this. I don't think skipping explicitly defined absolute paths to config files is the intention.

@leonard84
Copy link
Contributor Author

@bo0ts may I ask why you list those files explicitly instead of just listing the folders to be searched?
K8s uses the double symlink indirection so that it can atomically switch the content of the config map.
If you now directly reference the source file and not the symlink, then you are basically breaking this construct.
IMHO this is an antipattern in the context of kubernetes.

@scottfrederick
Copy link
Contributor

scottfrederick commented Nov 12, 2020

K8s uses the double symlink indirection so that it can atomically switch the content of the config map.

I wondered about this also. IIUC, the folders with names like ..2020_10_27_21_10_29.547134956 are intended to be temporary directories, which can be replaced with a different directory when the contents of the configmap changes. The symlink gets renamed to refer to the new temp folder when this happens. It does seem like using the temp folder names is an anti-pattern.

@bo0ts
Copy link

bo0ts commented Nov 12, 2020

@leonard84 @scottfrederick You are certainly right and we should at least specify the symlinks. However we explicitly decided against specifying the directories because we did not want to rely on yet another implicit mechanism for loading settings and because the behavior is different between Spring Boot 1.5 and 2 (which we both have to support with this script).

@leonard84
Copy link
Contributor Author

@bo0ts you can then simply use the non hidden symlinks, like k8s intended. You script might need to be a little fancier than a simple find . -type f, but then it would adhere to k8s standards.

Untested: find . -not -path '*/\.*' -name '*.properties' or find . -not -path '*/\.*' -type l -ls

At the end you want to have this:

/config/config1/application.properties,/config/config2/secret.properties,/config/config3/application.properties

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

8 participants