Support Git-style searchPaths with wildcards in AWS S3 buckets (#2812)#2958
Support Git-style searchPaths with wildcards in AWS S3 buckets (#2812)#2958tomy8964 wants to merge 10 commits into
Conversation
…g-cloud#2812) Fixes spring-cloud#2812 - ListObjectsV2 + AntPathMatcher based matching for *, **, ?, dot-wildcard - auto-ext lookup order (.properties → .json → .yml/.yaml) - directory scan, deduplication, prefix extraction - only active when searchPaths non-empty Signed-off-by: Geonwook Ham <tomy8964@naver.com> Signed-off-by: ham <tomy8964@naver.com>
Signed-off-by: Geonwook Ham <tomy8964@naver.com>
|
Hi @ryanjbaxter! |
There was a problem hiding this comment.
Pull request overview
This PR extends the AWS S3 environment repository to support Git-style searchPaths (placeholders + wildcard matching), enabling S3-backed config layouts to match existing Git-backed repository conventions.
Changes:
- Add
searchPathsconfiguration to the AWS S3 backend and wire it through the factory. - Implement placeholder expansion and wildcard-based S3 key discovery (including directory scans) with deduplication.
- Add an extensive JUnit 5 test suite covering placeholder/wildcard resolution scenarios.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 10 comments.
| File | Description |
|---|---|
spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepository.java |
Adds searchPaths support, wildcard matching via AntPathMatcher, S3 list/head probing, and key→property source wrapping. |
spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryFactory.java |
Passes searchPaths from properties into the repository constructor. |
spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentProperties.java |
Introduces searchPaths as a bindable configuration property. |
spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryTests.java |
Adds coverage for placeholder/wildcard behavior, ordering, and special cases. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Fixes spring-cloud#2812 Rework AwsS3EnvironmentRepository path resolution and profile handling. Reverse the app list before checking/appending the default application and only append the default when it is missing. Simplify property-source iteration and invoke negated-profile property source logic only when searchPaths is empty to avoid duplicate sources. Normalize search path patterns by resolving null label/profile vars, collapsing duplicate slashes and trimming leading '/', and optimize extension probing so existing extensions aren't re-probed. Signed-off-by: Geonwook Ham <tomy8964@naver.com>
ad8fc5a to
daa088a
Compare
Fixes spring-cloud#2812 In AwsS3EnvironmentRepositoryTests, avoid mutating a shared 'server' instance by creating a new ConfigServerProperties (serverWithDefaultLabel) and setting its defaultLabel before constructing AwsS3EnvironmentRepository. This prevents side-effects on shared test state and ensures the repository gets the intended default label for the test. Signed-off-by: Geonwook Ham <tomy8964@naver.com>
|
Hi @ryanjbaxter! I have successfully addressed all the feedback from the Copilot review:
The checks are passing, and it's ready for your review. Could you please take another look when you have some time? Thank you! |
The for loop header and the first statement are on the same line (for (...) {String resolvedLabel = ...), which is likely to fail formatting checks (and is hard to read). Split the loop body onto its own lines.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Geonwook Ham <tomy8964@naver.com>
Fixes spring-cloud#2812 Generalize getS3ConfigFileWithSearchPaths by adding a Function keyWrapper to handle different key-wrapping strategies (profile-specific and negated-profile cases). Implement wrapKeyWithNegatedConfigFiles to support YAML documents with negated spring.config.activate.on-profile expressions and wire it into property source discovery. Clean up formatting, streamline S3 client calls, and simplify create/wrapper methods. Also remove explicit setOrder in AwsS3EnvironmentRepositoryFactory (return repository directly) and update tests for minor formatting/usage changes. Signed-off-by: Geonwook Ham <tomy8964@naver.com>
|
Hi @ryanjbaxter! I have successfully addressed the second round of feedback from the Copilot review:
The checks are passing again, and the codebase is now much cleaner and more reusable. Could you please take another look when you have some time? Thank you! |
ryanjbaxter
left a comment
There was a problem hiding this comment.
Could you also add documentation?
…dant callReadImmediately flags Signed-off-by: Geonwook Ham <tomy8964@naver.com>
Signed-off-by: Geonwook Ham <tomy8964@naver.com>
|
Hi @ryanjbaxter! Summary of Changes
|
| private Optional<S3ConfigFile> createConfigFileFromKey(String key, String application, String profile, | ||
| String label) { | ||
| String ext = key.substring(key.lastIndexOf('.') + 1); | ||
| if ("properties".equalsIgnoreCase(ext)) { |
There was a problem hiding this comment.
The return for these 3 conditions looks identical to me
| return this.order; | ||
| } | ||
|
|
||
| public void setOrder(int order) { |
There was a problem hiding this comment.
We cannot remove public methods
| putFiles("v1/foo/foo.json", jsonContent); | ||
|
|
||
| Environment env = repo.findOne("foo", "", "v1"); | ||
| assertThat(env.getPropertySources()).hasSize(2); |
There was a problem hiding this comment.
What about validating the 2nd property source
| private String extractPrefix(String pattern) { | ||
| int idx = pattern.indexOf('*'); | ||
| int q = pattern.indexOf('?'); | ||
| if (q != -1 && (idx == -1 || q < idx)) { |
There was a problem hiding this comment.
I think there is a bug here if the pattern begins with *.
If q == -1 and idx == 0 (wildcard at the very start), the else if is never entered because the outer if was false (q == -1), so idx stays 0 and the method falls through to the lastIndexOf logic rather than returning ""
Summary
Add full Git-style
searchPathssupport (placeholders + wildcards) to the AWS S3 backend so that users can migrate existing Git-based configurations without renaming toapplication.*..*), single (?) and double (**) wildcard matching.properties → .json → .yml → .yamlwhen expanding literals or.*patternsThis issue (#2812)
resolves #2812
Changes
Core Logic
Extended
getS3ConfigFileWithSearchPaths(...)to treat{application}and{profile}placeholders identically to the Git backendAdded support for:
.*): expands against supported extensions in priority order?)**)/Ensured seenKeys set to avoid duplicate property sources
Tests
Added new JUnit 5 tests in
AwsS3EnvironmentRepositoryTeststo cover all scenarios:searchPaths_placeholderOnly_shouldResolveExactFilesearchPaths_wildcardOnly_shouldResolveAllPropertiessearchPaths_placeholderAndWildcard_shouldResolveMatchingKeyssearchPaths_orderMatters_forPropertySourceOrdersearchPath_extensionPreserved(dynamic tests for each extension)searchPaths_applicationAsDirectory_shouldStillHonorSearchPathsmultiDocumentYaml_withSearchPaths_shouldNotSplitDocumentsgetLocations_returnsCorrectsearchPaths_deduplication_shouldOnlyAddOncesearchPaths_singleCharacterWildcard_shouldMatchExactlyOneCharsearchPaths_withEmptyLabel_shouldUseDefaultLabelsearchPaths_multipleLabels_shouldApplyForEachLabelInReverseOrdersearchPaths_literalNotFound_shouldReturnEmpty…plus the additional edge cases for literal-stop, dot-wildcard priority, and nested directory patterns.
Example Usage
Additional Notes
Backward Compatibility
This update does not break any existing AWS S3 config setups. The default lookup behavior is unchanged if no placeholders or wildcards are used in
searchPaths.Migration
Existing users migrating from Git-backed config servers can now use their current
searchPaths(including wildcards and placeholders) on S3 with no renaming or convention change required.Documentation
Documentation and usage examples for the enhanced
searchPathswill be updated in the relevant documentation files after the merge.If there are specific locations that require documentation updates, please let me know—I will be happy to update them.
Performance and Cost
Using wildcards (such as
*or**) in searchPaths may result in additional AWS S3 API calls (e.g., ListObjects), especially for large buckets or deeply nested directory patterns.This could lead to increased latency and higher AWS costs.
Users should consider the structure and size of their buckets when designing searchPaths and monitor AWS S3 usage accordingly.