-
Notifications
You must be signed in to change notification settings - Fork 3.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
Allow empty separator in relabel config #6425
Conversation
Thanks for taking this up. |
I ran with I think I need to look deeper into how this is handled in Prometheus codebase. From my experience label-related changes are very bug-prone. Don't want to reinvent the wheel and create a bunch of subtle bugs... |
8eeb779
to
d366d68
Compare
@@ -1497,7 +1497,8 @@ type RelabelConfig struct { | |||
SourceLabels []LabelName `json:"sourceLabels,omitempty"` | |||
|
|||
// Separator is the string between concatenated SourceLabels. | |||
Separator string `json:"separator,omitempty"` | |||
//+kubebuilder:default=";" | |||
Separator string `json:"separator"` |
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.
The "issue" with adding a default value is that the API response will change to return separator: ";"
if the field isn't set and it may disrupt some clients (reconcilers for instance).
Another option would be to change the field type to be a string pointer:
- if the pointer is nil, don't set the
separator
field in the generated Prometheus config (and let Prometheus use its own default). - if not nil, pass the value as-is.
The risk with this option is for users that have separator: ""
in their YAML manifests today as it will change the behavior for them.
Separator string `json:"separator"` | |
Separator *string `json:"separator"` |
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 I agree this is a breaking change. But since this change is on par with Prometheus's behavior, I think it's worth doing.
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 thought of your suggested approach too. Will try this. I think it is less risky than the current (default ;
approach) because there might be less users setting separator: ""
than users not setting it at all.
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.
Agreed, I don't think that separator: ""
is widely used in the wild, especially knowing that as of today, it's the same as not setting it. If we follow that path, we's till need to mark it as a CHANGE in the changelog for safety.
@slashpai @simonpasquier All tests are passed now. Do you think we need to add tests for |
I would extend |
pkg/prometheus/resource_selector.go
Outdated
!(rc.Separator == "" || | ||
rc.Separator == relabel.DefaultRelabelConfig.Separator) || | ||
!(rc.Separator == nil || | ||
rc.Separator == &relabel.DefaultRelabelConfig.Separator) || |
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.
The addresses will always be different. Yes, it will be the same if at some point rc.Separator = (default value in rhs) in some languages but not in go, see this. I think it might be better to dereference rc.Separator instead of getting the address of the default value.
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.
Thanks. I know what you mean. I was just too focused on the nil separator, since that's the breaking change. Will fix this in next commit.
pkg/prometheus/resource_selector.go
Outdated
!(rc.Separator == "" || | ||
rc.Separator == relabel.DefaultRelabelConfig.Separator) || | ||
!(rc.Separator == nil || | ||
rc.Separator == &relabel.DefaultRelabelConfig.Separator) || |
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.
Same here. Check this playground out.
test/e2e/prometheus_test.go
Outdated
@@ -4657,7 +4659,7 @@ func testRelabelConfigCRDValidation(t *testing.T) { | |||
relabelConfigs: []*monitoringv1.RelabelConfig{ | |||
{ | |||
SourceLabels: []monitoringv1.LabelName{"__address__"}, | |||
Separator: ",", | |||
Separator: &sep1, |
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.
(nit) you can use ptr.To 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.
Agree, using pointer package from k8s would be better.
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'll fix this nit tomorrow when I have more time.
test/e2e/prometheus_test.go
Outdated
@@ -4668,7 +4670,7 @@ func testRelabelConfigCRDValidation(t *testing.T) { | |||
scenario: "empty-separator", | |||
relabelConfigs: []*monitoringv1.RelabelConfig{ | |||
{ | |||
Separator: "", | |||
Separator: &sep2, |
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.
Same 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.
- sourceLabels: [label1, label2] | ||
separator: "" | ||
action: replace | ||
targetLabel: custom_label |
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.
It took me forever to understand why such a simple change (changing separator to pointer), would change so much a golden file, e.g. source labels, action, etc.
That was until I realized that this file is not really a golden file by definition, but an input! We should change the suffix of this file to something else, e.g. .input
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.
👍 btw the config format is wrong since it expects Prometheus snake-case format.
@@ -392,7 +392,7 @@ func TestValidateRelabelConfig(t *testing.T) { | |||
relabelConfig: monitoringv1.RelabelConfig{ | |||
SourceLabels: []monitoringv1.LabelName{"__tmp_port"}, | |||
TargetLabel: "__port1", | |||
Separator: relabel.DefaultRelabelConfig.Separator, | |||
Separator: &relabel.DefaultRelabelConfig.Separator, |
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.
(nit)
Separator: &relabel.DefaultRelabelConfig.Separator, | |
Separator: ptr.To(relabel.DefaultRelabelConfig.Separator), |
You might want to squash these commits into one (or a few) once you are done with all the changes. You might already be on it, just a reminder! |
I've never done this in any of my merged PRs here. Is there any reason to do that in this PR? |
It's not really a necessity per se, but having one point in the final commit tree which tells you what exactly this commit did, than to have 10 or so commits that took to achieve it would be more desirable. |
For example, "fix e2e failure" is meaningful within the context of this PR. But once merged to main, it would become rather ambiguous. |
Yes many commits may not be meaningful out of PR. But no matter how many commits are in the PR, in the end there's only one merged commit right? Like this: 128acfc Of course if that's really necessary I'll do it. But I have seen many merged PRs with several commits, even from maintainers. So currently I don't see any values of doing it here. If I miss something else then please specify. |
IMHO for best practices its good to squash commits with meaningful message. Incase not doing GitHub has option squash and merge but we would still need to update comments while doing that. |
Yes, please help me squash when you merge. The first commit message has everything you need to know about the PR. I always follow your format here. Personally, I prefer to keep PR commits history as they are. In case I do several approaches in one PR, that PR merged, then I need to revert the PR and come back to a previous approach, commits history can help me find back that approach in my PR. |
separator: "" | ||
action: replace | ||
targetLabel: custom-label |
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.
- sourceLabels: [label-a, label-b] | |
separator: "" | |
action: replace | |
targetLabel: custom-label | |
- source_labels: [label-a, label-b] | |
separator: "" | |
action: replace | |
target_label: custom-label |
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.
Thanks. Fixed it. Any ideas why the test still passed with the operator's format? 🤔
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 thought the input file followed the operator's format. And the output (expected) file followed Prometheus's format. But from your suggestion, it means both follow Prometheus's format?
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.
correct, it's because the test is about additionalScrapeConfigs which hold native Prometheus configs.
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.
Hmm, then do you think this test can verify our fix? I thought we needed a test regarding the operator's format? 🤔 Like, before the operator's format didn't support ""
but now it does?
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.
The operator appends the additional config that is specified by name (I think?) in the final generated config. In this, we process the input config (user defined) and generate a final config. I think what you're trying to test is that the generated config which contains the appended additional config still contains the "empty" value in field instead of omitting it entirely.
d65d126
to
5f107bc
Compare
Allow empty separator in relabel config. This is corresponding to Prometheus' relabel config. Fixes prometheus-operator#5003
CI didn't run so I squashed commits to reactivate it. It still hasn't run though... Will wait then. |
@simonpasquier Is it good to merge? |
Description
Fixes #5003
Currently we don't allow empty separator in relabel config. If users specify an empty separator, it will be turned into the default
;
from Prometheus side. Since Prometheus makes use of empty separator, Prometheus operator should do that too.Type of change
What type of changes does your code introduce to the Prometheus operator? Put an
x
in the box that apply.CHANGE
(fix or feature that would cause existing functionality to not work as expected)FEATURE
(non-breaking change which adds functionality)BUGFIX
(non-breaking change which fixes an issue)ENHANCEMENT
(non-breaking change which improves existing functionality)NONE
(if none of the other choices apply. Example, tooling, build system, CI, docs, etc.)Verification
No tests broken. New tests passed.
Changelog entry
Allow empty seperator in relabel config
Question
Is this considered a breaking change?