Skip to content

fix(source): filter provider-specific properties to configured provider#6220

Merged
k8s-ci-robot merged 13 commits intokubernetes-sigs:masterfrom
gofogo:fix-provider-specific-propery-handling
Mar 15, 2026
Merged

fix(source): filter provider-specific properties to configured provider#6220
k8s-ci-robot merged 13 commits intokubernetes-sigs:masterfrom
gofogo:fix-provider-specific-propery-handling

Conversation

@ivankatliarchuk
Copy link
Copy Markdown
Member

@ivankatliarchuk ivankatliarchuk commented Feb 24, 2026

What does it do ?

  • Add method on *Endpoint in endpoint/endpoint.go — to retains only properties whose name is prefixed with / (e.g. aws/evaluate-target-health when provider is aws), drops the rest, and sorts the result by name for deterministic output. This should reduce frictions when records created then recreated and etc
  • Wire the filter into postProcessor.Endpoints in source/wrappers/post_processor.go — called per endpoint when a provider is configured

As part of this pr, found Cloudflare special case that is architecturally fragile (it's going to be difficult to just fix the provider in this PR)

endpoint/endpoint.go hardcodes provider == "cloudflare" in a method on *Endpoint, which is the core domain model. This couples the domain layer to a specific provider's naming quirk. Worse: when provider is cloudflare, all properties are retained including aws/evaluate-target-health...

Follow-up PR

Motivation

When endpoints carry provider-specific properties from multiple providers (e.g., both aws/evaluate-target-health and coredns/group), all of them were passed downstream regardless of which provider was actually configured. This means a provider receives properties that belong to a different provider, which can cause unexpected behaviour or misconfiguration during record synchronisation.

Fixes #6217
Fixes #4951
Relates #4347
Relates #5947

More

  • Yes, this PR title follows Conventional Commits
  • Yes, I added unit tests
  • Yes, I updated end user documentation accordingly
┌──────────┬───────┐
│ Category │ Lines │
├──────────┼───────┤
│ Non-test │ +47   │
├──────────┼───────┤
│ Test     │ +309  │
├──────────┼───────┤
│ Docs     │ +21   │
├──────────┼───────┤
│ Ratio    │ 1:6.5 │
└──────────┴───────┘

Current
Screenshot 2026-02-24 at 09 22 43

With the fix -> the problem gone

Fixtures

go run main.go \
    --provider=aws \
    --registry=txt \
    --source=service \
    --interval=30s \
    --dry-run \
    --fqdn-template='{{ .Name }}.example.com' \
    --label-filter='app=my-app'

---
apiVersion: v1
kind: Service
metadata:
  name: test-headless
  labels:
    app: my-app
  annotations:
    external-dns.alpha.kubernetes.io/aws-evaluate-target-health: "true"
    external-dns.alpha.kubernetes.io/coredns-group: "my-group"
spec:
  clusterIP: None
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
      annotations:
        external-dns.alpha.kubernetes.io/aws-evaluate-target-health: "true"
        external-dns.alpha.kubernetes.io/coredns-group: "my-group"
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80

Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
@k8s-ci-robot k8s-ci-robot added the controller Issues or PRs related to the controller label Feb 24, 2026
@k8s-ci-robot k8s-ci-robot added source cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Feb 24, 2026
@coveralls
Copy link
Copy Markdown

coveralls commented Feb 24, 2026

Pull Request Test Coverage Report for Build 23116432762

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • 88 unchanged lines in 5 files lost coverage.
  • Overall coverage increased (+0.02%) to 79.692%

Files with Coverage Reduction New Missed Lines %
execute.go 1 59.82%
wrappers/post_processor.go 2 95.83%
wrappers/types.go 7 88.24%
endpoint.go 38 88.3%
store.go 40 49.71%
Totals Coverage Status
Change from base Build 23098157121: 0.02%
Covered Lines: 16627
Relevant Lines: 20864

💛 - Coveralls

Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
@ivankatliarchuk ivankatliarchuk marked this pull request as draft February 26, 2026 07:48
@k8s-ci-robot k8s-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Feb 26, 2026
@ivankatliarchuk ivankatliarchuk marked this pull request as ready for review February 26, 2026 20:31
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Feb 26, 2026
@k8s-ci-robot k8s-ci-robot requested a review from vflaux February 26, 2026 20:31
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
Copy link
Copy Markdown
Contributor

@vflaux vflaux left a comment

Choose a reason for hiding this comment

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

I don't think this will works with cloudflare. In endpoint.ProviderSpecificAnnotations(), other providers cut their annotation prefix (external-dns.alpha.kubernetes.io/provider-xxx) before adding a specific provider entry on the endpoint. Cloudflare keep it so the provider specifics are external-dns.alpha.kubernetes.io/cloudflare-xxx, not cloudflare-xxx. With this implementation those specifics will be filtered.
It could be tempting to simply change this and align with other providers, but we'd have to keep compatibility with DNSEndpoints that set those provider specifics.

@vflaux
Copy link
Copy Markdown
Contributor

vflaux commented Feb 27, 2026

Wouldn't it be better to let each provider handle its own filtering logic? Isn’t AdjustEndpoints() already meant for that?

@ivankatliarchuk
Copy link
Copy Markdown
Member Author

Btw, thank for flagging. Indeed, cloudflare is very different to other providers. I have a PR #6158 to start capturing end-2-end behaviour, it may help a bit soon.

Tested with fixtures

go run main.go \
    --provider=inmemory \
    --registry=txt \
    --source=service \
    --interval=30s \
    --dry-run \
    --fqdn-template='{{ .Name }}.example.com' \
    --label-filter='app=my-app' \
    --min-ttl=60s

---
apiVersion: v1
kind: Service
metadata:
  name: test-headless
  labels:
    app: my-app
  annotations:
    external-dns.alpha.kubernetes.io/aws-evaluate-target-health: "true"
    external-dns.alpha.kubernetes.io/coredns-group: "my-group"
    external-dns.alpha.kubernetes.io/cloudflare-custom-hostname: "true"
    external-dns.alpha.kubernetes.io/cloudflare-tags: "env:prod,team:my-team"
spec:
  clusterIP: None
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 80

Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Feb 27, 2026
@ivankatliarchuk
Copy link
Copy Markdown
Member Author

ivankatliarchuk commented Feb 27, 2026

I've added a bypass/exception for cloudflare. No plans solving cloudflare diff in this pr

Wouldn't it be better to let each provider handle its own filtering logic? Isn’t AdjustEndpoints() already meant for that?

All providers should be consistent where possible to reduce drift.

This is potential benefits of consistent providers

  • Fewer spurious updates: Consistent normalization prevents unnecessary changes when only representation differs (e.g., default values added vs omitted).
  • Predictable behavior: Users can rely on the same property handling across providers, reducing surprises.
  • Easier testing: Common patterns allow shared test utilities and clearer expectations.
  • Simplified maintenance: providers can follow established patterns; reviewers spend less time re-learning per-provider logic. Contributors understand one set of rules rather than per-provider quirks.

@ivankatliarchuk
Copy link
Copy Markdown
Member Author

ivankatliarchuk commented Feb 27, 2026

I've added test, that should fail, if someone is going to add a new provider with properties and support of other format.

At the moment, short syntax

  • coredns
  • aws
  • webhook
  • provider agnostic

Full syntax

  • cloudflare

@ivankatliarchuk
Copy link
Copy Markdown
Member Author

/test pull-external-dns-unit-test

ivankatliarchuk and others added 3 commits March 15, 2026 12:42
@ivankatliarchuk
Copy link
Copy Markdown
Member Author

Hi @vflaux when you around, pls have, let'f finish this review.

cfg.preferAlias = enabled
if enabled {
cfg.isConfigured = true
cfg.preferAlias = enabled
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.

No sure about this change. This option with enable=false will do nothing. And is that related to this PR?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah, will roll it back. Basically cfg.preferAlias is false be default, so the assigment only make sense when value is true

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

rolled back

ivankatliarchuk and others added 2 commits March 15, 2026 17:48
Co-authored-by: vflaux <38909103+vflaux@users.noreply.github.com>
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
@ivankatliarchuk ivankatliarchuk requested a review from vflaux March 15, 2026 18:24
@vflaux
Copy link
Copy Markdown
Contributor

vflaux commented Mar 15, 2026

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Mar 15, 2026
@ivankatliarchuk
Copy link
Copy Markdown
Member Author

/approve

@k8s-ci-robot
Copy link
Copy Markdown
Contributor

[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

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 15, 2026
@k8s-ci-robot k8s-ci-robot merged commit 45b4aa2 into kubernetes-sigs:master Mar 15, 2026
18 checks passed
@ivankatliarchuk ivankatliarchuk deleted the fix-provider-specific-propery-handling branch March 15, 2026 18:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. controller Issues or PRs related to the controller docs lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. source

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unnecessary repeat changes due to Provider-Specific properties handling Provider-specific annotations are passed unconditionally

4 participants