-
Notifications
You must be signed in to change notification settings - Fork 1.8k
[chore][RFC] - Configuration Merging revamped #13256
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
[chore][RFC] - Configuration Merging revamped #13256
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #13256 +/- ##
==========================================
- Coverage 91.62% 91.38% -0.25%
==========================================
Files 522 646 +124
Lines 29208 42606 +13398
==========================================
+ Hits 26763 38937 +12174
- Misses 1926 2844 +918
- Partials 519 825 +306 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
douglascamata
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good stuff, @VihasMakwana. I like this. I left comments but they are non-blockers to me.
| - In this example, we will merge the list of extensions and receivers from pipeline, excluding lists in the rest of the config. | ||
| - `otelcol --config main.yaml --config ext.yaml?merge_paths=service::extensions --config rec.yaml?merge_paths=service::**::receivers` | ||
| - In this example, we will merge all list of extensions from `ext.yml` and list of receivers from `rec.yaml`, excluding lists in the rest of the config. | ||
| 2. `merge_mode`: One of `prepend` or `append`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably need more options. For example, if I want to add a receiver in a merging config while it may be already defined in the base config. Also, we need the default replace behavior. What about the following list:
append: append entries to the listappend_unique: append only unique entries to the listprepend: insert entries in front of the listprepend_unique: insert only unique entries in front of the list
replace(default): overwrite the list
keep: keep the original list
Also, I would call the options list_merge_mode and list_merge_paths to make it clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dmitryax I see. I'll update the RFC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you touch a good point there with the _unique modifiers, @dmitryax. Shouldn't both append and prepend always ensure lists containing only "basic types" (strings, ints, etc) do not have duplicated values? I don't know about any scenario in the Collector involving lists of basic types where duplicated values wouldn't be a problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For service components, duplicates will cause error.
I'm not sure about other places though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For service components, duplicates will cause error.
Right. For example, I have a list of receivers in a basic config file which I don't control. Then, I want to add another receiver and override it in case it's already defined in the basic config. In that case --config=extra_receiver.yaml?merge_mode=append&merge_paths=service::**::receivers would cause a failure if the basic config already has my receiver. I need append_unique instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can start with a small number of options, in any case we can discuss that in the implementation phase
| 1. `merge_paths`: A comma-separated list of glob patterns which will be used while config merging | ||
| - This setting will control the paths user wants to merge from the given config. | ||
| - Example: | ||
| - `otelcol --config main.yaml --config extra.yaml?merge_paths=service::extensions,service::**::receivers` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think using the query params is fine. However, we need to keep in mind that some confmap providers use the same pattern to pass extra information. With this approach, they won't be able to use these keys which is probably fine.
If anyone else have any other ideas, please share.
cc @open-telemetry/collector-approvers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, we can extract the parameters here
opentelemetry-collector/confmap/resolver.go
Line 176 in 6aa2b81
| for _, uri := range mr.uris { |
Then we can remove our parameters from URI and let resolver do its job:
u, _ := url.Parse("otel.yaml?key=val&merge_mode=append")
q := u.Query()
q.Del("merge_mode")
u.RawQuery = q.Encode()
// uri will now be otel.yaml?key=val&key2=val2There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We discussed this in this RFC and came up with a few issues with query parameters that we'll want to consider before going that route.
@dmitryax I believe you, @mx-psi, and I had an offline conversation at KubeCon and tacitly agreed we should go the route of configuring these inside a config file (this option in the RFC). Do you still think we should go this route? I think we should probably at least explore it before deciding on an approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@evan-bradley @dmitryax approach 1 does not deal with params, does this resolve your concerns here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't mind calling out the "Configuring Confmap Providers" RFC just to make it clear there are other options we can explore, but if approach 1 is our preference, I'm good with what's here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's fair
|
I haven't had time to look into this proposal in detail but one thing I would like to see explored is whether we can use YAML custom tags https://yaml.org/spec/1.2.2/#tags to specify this in the YAML itself per-array |
|
@mx-psi Thanks for sharing your thoughts! I'll surely go the documentation and see if they can be integrated. I'm all in if we can get it work through just yaml. |
|
@mx-psi I had a brief look at yaml tags and their support in golang. Here are my thoughts:
var node Node
err := yaml.Unmarshal(data, &node)
// recursively go through the node and its children to find the nodes with tags and store their path.
Here are some initial pros and cons that come to mind:
Let me know your thoughts! |
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description Promotes @VihasMakwana as triager. @VihasMakwana is a contrib triager and has been doing excellent work in core, including pushing for RFCs and features such as #13256, #13224 and #11775. Thank you for your work @VihasMakwana ! cc @open-telemetry/collector-approvers
|
This PR was marked stale due to lack of activity. It will be closed in 14 days. |
92e1e76 to
dc77505
Compare
|
|
||
| ## Proposed approaches: | ||
|
|
||
| ### Approach 1 (Recommended): Use yaml tags |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I discussed this over Slack with Vihas but mentioning it here: it would be good to make sure that our officially released Helm charts and operator do not break these YAML tags (they shouldn't but I think it's a good check to do before deciding)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've reached out on #otel-helm on CNCF slack for more eyes on this. I'll run some tests on this and keep you updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mx-psi Unfortunately, YAML tags are not preserved in helm chart. I think this is due to the fact that our helm chart deals with yaml to dict conversion internally and tags are lost in this process.
The same applies to the operator. The operator marshals the config into a struct and internally, it is map[string]interface{}. Hence, the tags are lost in the conversion.
That being said, do users need this feature in helm/operator? Our helm chart internally deals with all the merging and appending to the lists, when necessary.
For operator, users deploy a single configuration like following:
kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: simplest
spec:
config:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
exporters:
debug: {}
service:
pipelines:
traces:
receivers: [otlp]
exporters: [debug]
EOFThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^^ @mx-psi
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From 2025-09-10 Collector SIG meeting it seems like this should not be a concern but let's wait a bit more for the Operator SIG to answe
Co-authored-by: Pablo Baeyens <[email protected]>
|
if you guys are around, please take a look at this RFC. I've documented both the approaches. Here's a PoC for yaml tags: #13551 |
|
@mx-psi if you're around, can you please take a look? |
mx-psi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, let's wait to see what the Operator SIG says but I think the suggested approach works and would be my preferred alternative
|
@dmitryax @evan-bradley could you take another look so we can know if there are any outstanding discussions to be had before going forward with this? |
evan-bradley
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good to me, thanks @VihasMakwana.
|
Hi @VihasMakwana, great work, fantastic stuff! 💪 Do you think the points raised in this issue might also be worth evaluating for inclusion in this RFC (or perhaps in a follow-up)? The use case is a bit different, but there seems to be real value for users in merging configurations dynamically from multiple files within a directory. |
Co-authored-by: Evan Bradley <[email protected]>
Co-authored-by: Evan Bradley <[email protected]>
Co-authored-by: Hélia Barroso <[email protected]> Co-authored-by: Evan Bradley <[email protected]>
|
@paulojmdias I like that enhancement! It can definitely be a follow-up in my opinion. |
Awesome, let's see what other people think about it. I'm also open to help with it 🙌 |
|
This was discussed in the last Operator SIG meeting with no major concerns. I think we can merge this on or after Wednesday unless we hear any objections |
|
Speaking on behalf of the operator SIG, we're unlikely to use this feature, so no objections from our side. |
cb24802
|
Lovely so see this merged, @VihasMakwana. Congrats and thank you! Do you have an implementation plan in mind? Are there are issues or PRs that I can follow to know when work starts to move forward so that I help out and/or know when it's ready to be used? |
|
@douglascamata Hello!
You can keep an eye on #13551. It's still in draft and I need to clean things up. I'll find some time this week/next one and mark it for review. |
Description
This RFC is a follow-up of #12097. The first PR introduced the feature gate to merge the components' lists and left out the options to configure the merging behaviour.
This RFC proposes an approach to extend the current behaviour by enabling merging of specified config parts and support different modes.
Link to tracking issue
Relates:
Thanks to @mx-psi @dmitryax and @evan-bradley for their feedback on the first PR!!