Skip to content

fix-2148: reload issue#2164

Merged
ryanjbaxter merged 8 commits intospring-cloud:3.3.xfrom
wind57:fix-issue-2148-reload
Mar 5, 2026
Merged

fix-2148: reload issue#2164
ryanjbaxter merged 8 commits intospring-cloud:3.3.xfrom
wind57:fix-issue-2148-reload

Conversation

@wind57
Copy link
Copy Markdown
Contributor

@wind57 wind57 commented Mar 3, 2026

No description provided.

* limitations under the License.
*/

package org.springframework.cloud.kubernetes.commons.config;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the actual fix is made from two parts. this is part 1.

introduce a new abstraction ConfigMapPropertySource ( we already have this one for secrets ).

Every property source that is derived from configmap will extend this one; and also every type that is derived from a secret will extend the SecretsPropertySource ( again, which we already have )


import org.springframework.cloud.bootstrap.config.BootstrapPropertySource;
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
import org.springframework.cloud.kubernetes.commons.config.ConfigMapPropertySource;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is part 2 of the fix and this is what I am doing:

in the reload method, we always receive a certain type ( I mean the argument for existingSourcesType ). It's either Fabric8SecretsPropertySource.class / KubernetesClientSecretsPropertySource.class or Fabric8ConfigMapPropertySource.class / KubernetesClientConfigMapPropertySource.class.

Let's suppose we got the Fabric8ConfigMapPropertySource.class here as the type ( exactly as in the bug OP opened ). We would have taken two property sources as such:

  • an instance of Fabric8ConfigMapPropertySource
  • an instance of MountSecretPropertySource

though, the change that triggered this was caused by a config map change, so secrets ( and you pointed out to me in the bug details Ryan ) makes little sense.


As such, I introduced that extra abstraction : ConfigMapPropertySource and now can do :

else if (source instanceof MountConfigMapPropertySource mountConfigMapPropertySource
					&& ConfigMapPropertySource.class.isAssignableFrom(sourceClass)) {
				// we know that the type is correct here
				managedSources.add((S) mountConfigMapPropertySource);
			}
			else if (source instanceof MountSecretPropertySource mountSecretPropertySource
					&& SecretsPropertySource.class.isAssignableFrom(sourceClass)) {
				// we know that the type is correct here
				managedSources.add((S) mountSecretPropertySource);
			}

so that the MountSecretPropertySource is not taken.

@wind57 wind57 marked this pull request as ready for review March 3, 2026 20:27
@wind57
Copy link
Copy Markdown
Contributor Author

wind57 commented Mar 3, 2026

@ryanjbaxter this is ready, I've tested it against the bug issue that was opened

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses a config reload issue (fix-2148) by introducing a common ConfigMapPropertySource base type and adjusting how ConfigReloadUtil.findPropertySources(...) selects mount-based property sources during reload comparisons.

Changes:

  • Added ConfigMapPropertySource as a shared base class for configmap-backed PropertySources.
  • Updated MountConfigMapPropertySource and SourceDataEntriesProcessor to extend ConfigMapPropertySource.
  • Tightened ConfigReloadUtil.findPropertySources(...) matching rules and expanded unit tests around mount/configmap/secret selection behavior.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
spring-cloud-kubernetes-commons/src/test/java/.../ConfigReloadUtilTests.java Updates/extends tests for findPropertySources behavior with mount/configmap/secret sources.
spring-cloud-kubernetes-commons/src/main/java/.../reload/ConfigReloadUtil.java Adds conditional matching for mount sources based on configmap/secret type hierarchies.
spring-cloud-kubernetes-commons/src/main/java/.../config/SourceDataEntriesProcessor.java Switches to extending the new ConfigMapPropertySource.
spring-cloud-kubernetes-commons/src/main/java/.../config/MountConfigMapPropertySource.java Switches to extending the new ConfigMapPropertySource.
spring-cloud-kubernetes-commons/src/main/java/.../config/ConfigMapPropertySource.java Introduces the new shared base class for configmap property sources.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 113 to 121
else if (source instanceof MountConfigMapPropertySource mountConfigMapPropertySource
&& ConfigMapPropertySource.class.isAssignableFrom(sourceClass)) {
// we know that the type is correct here
managedSources.add((S) mountConfigMapPropertySource);
}
else if (source instanceof MountSecretPropertySource mountSecretPropertySource) {
else if (source instanceof MountSecretPropertySource mountSecretPropertySource
&& SecretsPropertySource.class.isAssignableFrom(sourceClass)) {
// we know that the type is correct here
managedSources.add((S) mountSecretPropertySource);
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findPropertySources(Class<S> ...) can now add MountConfigMapPropertySource / MountSecretPropertySource even when sourceClass is a more specific subtype (e.g. Fabric8ConfigMapPropertySource). That violates the method’s generic contract (returning a List<S> that may contain elements not assignable to S) and can trigger ClassCastException in callers that use List<Fabric8ConfigMapPropertySource> (there are such call sites in tests). Consider either: (1) changing reload call sites to pass ConfigMapPropertySource.class / SecretsPropertySource.class so plain sourceClass.isInstance works and you can remove these unsafe branches, or (2) changing the method signature/return type to not claim List<S> when it can return other implementations.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copilot here is correct. I never took a closer look here, but there is a minor issue. The thing is, this works because we only put elements in that list ( and it works due to type erasure ), but otherwise the pattern is pretty broken here.

I am looking how to properly fix it.

@wind57
Copy link
Copy Markdown
Contributor Author

wind57 commented Mar 4, 2026

@ryanjbaxter can you re-trigger copilot here please? I will explain what I am fixing and how after I review his review

@ryanjbaxter ryanjbaxter requested a review from Copilot March 4, 2026 21:19
Signed-off-by: wind57 <[email protected]>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

wind57 added 2 commits March 5, 2026 08:55
Signed-off-by: wind57 <[email protected]>
Signed-off-by: wind57 <[email protected]>

@BeforeAll
static void beforeAll() {
wireMockServer = new WireMockServer(options().dynamicPort());
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these tests here are exactly as in the bug description

@Deprecated(forRemoval = false)
@SuppressWarnings("unchecked")
public static <S extends PropertySource<?>> List<S> findPropertySources(Class<S> sourceClass,
public static <S extends MapPropertySource> List<MapPropertySource> findPropertySources(Class<S> sourceClass,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed the method generics type a little. It was a bug, really. It was a classic "heap pollution" where we could put entries in this List and after that it was completely useless: you could not instantiate it properly and when taking elements out, it would throw a ClassCastException.

We were only comparing size of it all the time, that is why it did not fail until now. Still, I think its worth to change it properly.

return new Fabric8ConfigMapPropertySource(context);
}

public static Fabric8SecretsPropertySource secretPropertySource(KubernetesClient kubernetesClient) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to change the visibility of Fabric8SecretsPropertySource and also ConfigReloadUtil::findPropertySources is not public in main, so I need to create this indirection to be able to access them

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you just add a comment to the class explaining its existance?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done. I have a PR that also merges 3.3.x into main, I'll wait until 3.3.x passes, then merge it, then will tag you when the PR is ready. It's just that there are deletions there and it would be easier for me to do it and take that burned off you

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks I was just looking at the merge and it is terrible LOL

Signed-off-by: wind57 <[email protected]>
@wind57
Copy link
Copy Markdown
Contributor Author

wind57 commented Mar 5, 2026

@ryanjbaxter fixed all copilot comments, its good to look at. thank you

Signed-off-by: wind57 <[email protected]>
@ryanjbaxter ryanjbaxter merged commit f8671c1 into spring-cloud:3.3.x Mar 5, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ConfigMap reloading not starting due to "PropertySources does not match the ones loaded from Kubernetes"

4 participants