-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Reduce verbosity of kubernetes extension config with inheritance or more opinionated defaulting #34025
Comments
You added a link to a Zulip discussion, please make sure the description of the issue is comprehensive and doesn't require accessing Zulip This message is automatically generated by a bot. |
@radcortez is there anything in Smallrye Config we could leverage here? |
We don't have any notion of namespace inheritance in config like described here. Mappings do support a Base mapping to share properties between multiple ConfigRoots (currrently, each specialization has its own root). That would required to rewrite the current Roots. An easier approach could be to use the fallbacks: https://smallrye.io/smallrye-config/3.3.0/extensions/fallback/#use-smallrye-config-in-a-java-application For instance, we can write a fallback function to replace |
Subscribing @edeandrea too :) The fallback option sounds ideal, @radcortez. |
Thank you @holly-cummins for looping me in. I'm not sure fallbacks would help here, unless I'm not understanding how they work. These particular properties are read at build time (not runtime) by various extensions at different points in time during the build process (during the maven package phase). Different extensions are looking at various namespaces. Maybe using an example would help clarify if this indeed could be a viable solution? quarkus.kubernetes.part-of=fights-service
quarkus.kubernetes.env.configmaps=${quarkus.application.name}-config
quarkus.kubernetes.env.secrets=${quarkus.application.name}-config-creds
quarkus.kubernetes.labels.app=${quarkus.application.name}
quarkus.kubernetes.labels.application=${quarkus.kubernetes.part-of}
quarkus.kubernetes.labels.system=quarkus-super-heroes
quarkus.openshift.part-of=${quarkus.kubernetes.part-of}
quarkus.openshift.env.configmaps=${quarkus.kubernetes.env.configmaps}
quarkus.openshift.env.secrets=${quarkus.kubernetes.env.secrets}
quarkus.openshift.labels.app=${quarkus.kubernetes.labels.app}
quarkus.openshift.labels.application=${quarkus.kubernetes.labels.application}
quarkus.openshift.labels.system=${quarkus.kubernetes.labels.system} How would the fallback option work when the |
A Fallback is just a function or mapping rule that allows Config to lookup the value in another property if the original property didn't get a value. We use this in a number of scenarios. For instance you can use both In this case, you are doing something similar with property expansion. We can set a simple fallback rule like quarkus.kubernetes.labels.app=my-app
quarkus.kubernetes.labels.app=my-app
quarkus.openshift.labels.application=another-app
In a way, the fallback mechanism allows you to implement some sort of inheritance. You can add multiple fallback rules like:
Not sure if I got the question, but fallback is done at the property name level in the current Config instance, by rewriting the property name with the fallback rule and performing another lookup (or multiple ones if fallback rules are chained). What targets a fallback is not finding the value on the original property name lookup. I believe that the fallback mechanism should help here, but maybe there is some logic that I'm not aware on how you deal with the different targets. |
Looking at the docs you sent it looks like I would need to create a My question is - does this work for configuration properties which are read at build time? And then if so, for the super-heroes, since there are 5 apps, we'd have to have 5 copies of this class and config scattered throughout the source tree? |
Correct.
What you want to do here is to provide the fallback rules at the extension level, so you only have one copy, and the interceptor is applied to all phases. If I understood correctly, the "inheritance" rules do not change per application, so they can be added at the extension level. |
I don't quite understand what you mean here. Does that mean create my own extension and then somehow share it somehow amongst all the other applications? |
No, it's to add this feature directly into our kubernetes extension. |
Let me know what is the desired behaviour with each system specialization and I'll handle the rest :) |
I like the idea of the fallback configuration option whose general rule is:
However, my main concern is that is a breaking change that is not very transparent to users. Users having configured only the Kubernetes manifests will suddenly see that this configuration is also used for the OpenShift manifests. Though, we might add a big note in the migration guide. An alternative to the fallback configuration option is to use the same concept as in data sources or rest-clients, the multitenant configuration. We could add a base configuration at the root level ( I still prefer the idea of the fallback approach, but the multitenant solution embraces the same concept as in data sources or rest-clients and it would not be a breaking change. |
@Sgitario that's a good point about breaking changes ... although I suspect it might be a rare case. It would have to be:
At first I thought that would be quite rare, but I guess (taking OpenShift in particular) the scenario might be something like "Vanilla Kubernetes is a bag of bits so I need to manually configure lots of stuff, but OpenShift is more secure out-of-the-box so I get sensible config 'for free'." The
So for me, I'd vote for |
And also, the user would need to learn about this new property which is not ideal either.
Yes, I think that as long as we properly document this breaking change in the migration guide, it should be good. |
Currently, because you need to configure everything, if you only have kubernetes configured, it means you only used kubernetes as a target. If you are using both kubernetes and openshift, it means you are already required to configure the openshift properties (which in this case they wouldn't fallback to kubernetes). If you are adding a new target, then you get the fallbacks. We certainly need to document it, but at first glance, I don't think it is a big breaking change, but I may be missing something, since I'm not an experienced user of the kubernetes extension. |
What about a simple flag that the user can set to say whether or not they want the fallback? By default it would be off, so it would be backwards compatible. |
Wouldn't it be simpler for them to just provide the properties if they didn't want the fallback? They'd have to that anyway if they opted to not have the fallback. The one exception is properties where a user would choose to set it for kubernetes and not for openshift, and I'm not sure we have a good example of what those properties might be. It feels a bit hypothetical so far. Every knob we provide adds complexity for users, so I think we need to be very sure a knob is needed before introducing it. |
Correct. If we really want to make things super clear, we can add a log stating that property |
Some updates about this issue and possible solutions:
@radcortez did I do something wrong to implement the fallback option? |
What is not working exactly? Remember, Fallback only kicks in when a property in the original name cannot find a value. So what you are saying is that if we cannot find a value in |
I think this is what I did (unless you spot the opposite from the changes of the commit). When I said it's not working, it's because I provide a |
Description
I've just been writing some config for the kubernetes extension, for an app in the superheroes sample.
I was surprised how much of it there was. See, for example, https://github.com/quarkusio/quarkus-super-heroes/blob/1049a71741404c98e5a122e9fc9e7181516d2ce3/rest-fights/src/main/resources/application.properties#L76. Part of the issue is that the sample has config for knative, openshift, minikube, and kubernetes. From reading the documentation, there doesn't seem to be any inheritance between the namespaces, so if I configure a property for kubernetes, I then have to replicate all the config for openshift, even though openshift is a specialisation of kubernetes.
I also wonder whether some of the properties being configured could be defaulted?
See also discussion in https://quarkusio.zulipchat.com/#narrow/stream/187030-users/topic/DRYer.20config.20for.20kubernetes.20extension/near/364657444.
Implementation ideas
No response
The text was updated successfully, but these errors were encountered: