fix(annotations): initialize annotation keys at declaration time#6159
Conversation
f8f7a35 to
180aa05
Compare
180aa05 to
cb74032
Compare
Pull Request Test Coverage Report for Build 21551962450Warning: This coverage report may be inaccurate.This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.
Details
💛 - Coveralls |
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
cb74032 to
ba74177
Compare
source/annotations/annotations.go
Outdated
| func SetAnnotationPrefix(prefix string) { | ||
| prefix = strings.TrimSpace(prefix) | ||
| if prefix == "" || !strings.HasSuffix(prefix, "/") { | ||
| return | ||
| } |
There was a problem hiding this comment.
Shoudn't this return an error instead of silently ignoring the value.
Maybe add a proper validation? validation.IsDNS1123Subdomain() is what validate annotation prefixes I think.
There was a problem hiding this comment.
This is not a DNS subdomain, this is a kubernetes annotation prefix current default external-dns.alpha.kubernetes.io/. Basically any annotation prefix could be used
There was a problem hiding this comment.
The method could return an error, but I'd rather to keep it as is for now. I'm not actually a big fan of this functionality. In past we had always all annotations defaulted and prefixed with "external-dns.alpha.kubernetes.io/". This is a runtime hack for split brain functionality.
Why I think is better to keep as is(aka without error return)
- default behaviour is here
- this method require a proper validation for annotations prefixes(could be added in the future)
I'd rather remove this checks `prefix == "" || !strings.HasSuffix(prefix, "/"), wdyt?
Returnign error could be added in follow up. I'm still looking for options to completely remove this method
There was a problem hiding this comment.
This checks a mainly for tests. Runtime validation is here pkg/apis/externaldns/validation/validation.go
There was a problem hiding this comment.
Basically any annotation prefix could be used
There is a validation on the prefix. With a_/b the api-server returns:
Invalid value: "a_/b": prefix part a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')
However, external-dns only reads the annotations, so validation isn’t required anyway. If an invalid prefix is set, it simply won’t match any annotation.
I'd rather remove this checks `prefix == "" || !strings.HasSuffix(prefix, "/"), wdyt?
This can probably be removed.
There was a problem hiding this comment.
Basically any annotation prefix could be used
There is a validation on the prefix. With
a_/bthe api-server returns:Invalid value: "a_/b": prefix part a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')However, external-dns only reads the annotations, so validation isn’t required anyway. If an invalid prefix is set, it simply won’t match any annotation.
I'd rather remove this checks `prefix == "" || !strings.HasSuffix(prefix, "/"), wdyt?
This can probably be removed.
The behavour is sligthly different. If incorrect annotation is set for split brain functionality -> one could end up wihtout records. But not a big deal at the moment. This split brain feature is complex and risky
There was a problem hiding this comment.
But this is an issue of brain split feature itself - too complex
| } | ||
| AnnotationKeyPrefix = prefix | ||
|
|
||
| // Cloudflare annotations |
There was a problem hiding this comment.
We may use a function for this:
func setAnnotationKeyPrefix(prefix string, key *string) {
suffix,_ := strings.CutPrefix(DefaultAnnotationPrefix, *key)
*key = prefix + suffix
}setAnnotationKeyPrefix(prefix, &CloudflareProxiedKey)This would avoid potential typos.
There was a problem hiding this comment.
This will create more issues with initial problem. CloudflareProxiedKey is not a suffix, CloudflareProxiedKey must be defaulted always to external-dns.alpha.kubernetes.io/cloudflare-key. This is what I'm trying to fix.
At the moment, in all tests annotation.CloudflareProxiedKey is just cloudlare-key without annotation prefix, when it was beforeexternal-dns.alpha.kubernetes.io/cloudflare-key. So now in pretty much every test we need
annotations.SetAnnotationPrefix("external-dns.alpha.kubernetes.io/")
I may missing something in your suggestion, or there is misunderstanding what the issue curretly is.
Currently without this fix, every test file that touches annotations needs workarounds, and test order becomes fragile. And now tests need to know about runtime behaviour......
There was a problem hiding this comment.
What I understand is that you define default values for the annotation keys and when SetAnnotationPrefix() is called it changes the values with a new prefix.
My suggestion is to use a function that replace the prefix on all annotations like this:
// SetAnnotationPrefix sets a custom annotation prefix and rebuilds all annotation keys.
// This must be called before any sources are initialized.
// The prefix must end with '/'.
func SetAnnotationPrefix(prefix string) {
prefix = strings.TrimSpace(prefix)
if prefix == "" || !strings.HasSuffix(prefix, "/") {
return
}
replaceAnnotationPrefix(
AnnotationKeyPrefix,
prefix,
// Cloudflare annotations
&CloudflareProxiedKey,
&CloudflareCustomHostnameKey,
&CloudflareRegionKey,
&CloudflareRecordCommentKey,
&CloudflareTagsKey,
// Provider prefixes
&AWSPrefix,
&CoreDNSPrefix,
&SCWPrefix,
&WebhookPrefix,
&CloudflarePrefix,
// Core annotations
&TtlKey,
&SetIdentifierKey,
&AliasKey,
&TargetKey,
&ControllerKey,
&HostnameKey,
&AccessKey,
&EndpointsTypeKey,
&Ingress,
&IngressHostnameSourceKey,
&InternalHostnameKey,
&GatewayHostnameSourceKey,
)
AnnotationKeyPrefix = prefix
}
func replaceAnnotationPrefix(currentPrefix, newPrefix string, keys ...*string) {
for _, key := range keys {
suffix, found := strings.CutPrefix(*key, currentPrefix)
if !found {
panic(fmt.Sprintf("annotation key %q does not have default prefix %s ", *key, currentPrefix))
}
*key = newPrefix + suffix
}
}There’s no need to duplicate the annotation suffixes, which eliminates any risk of typos.
wdyt?
There was a problem hiding this comment.
I understand but do not agree with this proposal. Please have a look, I'm rolling back a change that does break how things should be.
If you think we should add this function in function, open a pull request lets discuss.
This public function is a hack. It changes the behaviour of annotations at runtime that cause and brake normal flow for tests. It should not exist. This is my view. I'm just trying to get the code to work as before.
There was a problem hiding this comment.
I don't understand why there is a spelling problem, when I'm clearly solving different problem.
Could you explain why to extend the scope of the initial pull request?
There was a problem hiding this comment.
My view I described in title
- anything that could remove that public function -- make sense to folloup
- anything to extend the current function is just building more tech debt on top of the current hack
There was a problem hiding this comment.
I'm rolling back a change that does break how things should be.
I missed that it was a rollback of a previous PR, my mistake.
There was a problem hiding this comment.
Thanks. Feel free to submit a new PR with your proposal. On my side, I'm trying to undersant how to remove this fucntions ;-0
|
/lgtm |
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
|
Hi @vflaux. I removed #6159 (comment) |
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
|
/lgtm |
|
/approve |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: ivankatliarchuk The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
* master: fix(annotations): initialize annotation keys at declaration time (kubernetes-sigs#6159) chore(linter): unused params and functions linter (kubernetes-sigs#6142) docs(fqdn): use correct arguments order in FQDN Templating custom functions (kubernetes-sigs#6144)
…_total * master: chore(deps): bump mkdocs-git-revision-date-localized-plugin (kubernetes-sigs#6161) fix(annotations): initialize annotation keys at declaration time (kubernetes-sigs#6159) chore(linter): unused params and functions linter (kubernetes-sigs#6142) docs(fqdn): use correct arguments order in FQDN Templating custom functions (kubernetes-sigs#6144) chore(cloudflare): improve tests (kubernetes-sigs#6150) refactor(kubeclient): consolidate duplicate code (kubernetes-sigs#6076) remove call to get latest kubectl (kubernetes-sigs#6148) refactor(aws): extract and restructure alias-handling logic to enable safe upcoming fixes (kubernetes-sigs#6021) feat(pihole): deprecate v5 API support (kubernetes-sigs#6123) chore(cloudflare): move custom hostnames logic to dedicated files (kubernetes-sigs#6114) chore(provider): zone cache provider interface (kubernetes-sigs#6120)
* master: chore(deps): bump mkdocs-git-revision-date-localized-plugin (kubernetes-sigs#6161) fix(annotations): initialize annotation keys at declaration time (kubernetes-sigs#6159) chore(linter): unused params and functions linter (kubernetes-sigs#6142) docs(fqdn): use correct arguments order in FQDN Templating custom functions (kubernetes-sigs#6144) chore(cloudflare): improve tests (kubernetes-sigs#6150)
What does it do ?
Rollback changes that was added here #5889
Without this fix, every test file that touches annotations needs workarounds, and test order becomes fragile. And now tests need to know about runtime behaviour......
Curretnly, annotation keys are uninitialized strings that did required
init()or explicitSetAnnotationPrefix()calls to populate. This caused issues where tests needed boilerplate likeTestMainjust to ensure defaults were set.This is still a band-aid though. The root issue is global mutable state. A cleaner long-term solution would be passing prefix configuration through context or making annotation keys instance-based rather than package-level globals.
SetAnnotationPrefix. As empty strings creates undocumented issues.Some other PR, curerrently in review
Motivation
SetAnnotationPrefixis called at runtime fromcontroller/execute.goto configure custom prefixes. However, the current implementation skips updates when the prefix equalsthe default (DefaultAnnotationPrefix == prefix), which prevents:
It was added here #5889
More