Skip to content

feat: add generic PTR record support for all providers#6232

Open
clwluvw wants to merge 12 commits intokubernetes-sigs:masterfrom
clwluvw:generic-ptr-provider
Open

feat: add generic PTR record support for all providers#6232
clwluvw wants to merge 12 commits intokubernetes-sigs:masterfrom
clwluvw:generic-ptr-provider

Conversation

@clwluvw
Copy link

@clwluvw clwluvw commented Feb 27, 2026

What does it do ?

Introduces a provider-agnostic PTR record mechanism that wraps any provider as a decorator. A new --create-ptr flag accepts three modes: "off" (default), "always" (PTR for all A/AAAA records), and "annotation" (PTR only when the
source resource is annotated with external-dns.alpha.kubernetes.io/create-ptr).
The RFC2136 provider's built-in PTR logic is removed in favor of this generic approach, and the old --rfc2136-create-ptr flag is preserved for backward compatibility.

Motivation

PTR record creation was previously hardcoded into the RFC2136 provider only. Any other provider managing reverse DNS zones (e.g. PowerDNS) had no way to create PTR records automatically. This change makes PTR support available to all providers.

More

  • Yes, this PR title follows Conventional Commits
  • Yes, I added unit tests
  • Yes, I updated end user documentation accordingly

Add a provider-agnostic PTR record management layer that automatically
creates and deletes PTR records for A and AAAA endpoints.

Signed-off-by: Seena Fallah <[email protected]>
Add PTR to the supportedRecords list in the AffixNameMapper so the TXT
registry can correctly map between PTR records and their ownership TXT
records (e.g. ptr-2.49.168.192.in-addr.arpa -> 2.49.168.192.in-addr.arpa).

Without this, extractRecordTypeDefaultPosition cannot recognize the 'ptr-'
prefix, causing the TXT registry to skip owner label attachment for PTR
records. This prevents PTR record updates and deletions.

Signed-off-by: Seena Fallah <[email protected]>
- Add PTR to trailingTypes so EnsureTrailingDot is applied to PTR targets
  before sending to the PowerDNS API (required format: 'host.example.com.')
- Implement GetDomainFilter() on PDNSProvider so the generic PTRProvider
  wrapper can access the configured domain filter to skip A/AAAA records
  outside the managed domain set

Signed-off-by: Seena Fallah <[email protected]>
Remove the provider-specific PTR implementation (createPTR field,
AddReverseRecord, RemoveReverseRecord, GenerateReverseRecord) and all
PTR handling from ApplyChanges.

PTR management is now handled generically by the PTRProvider wrapper
via AdjustEndpoints.

Signed-off-by: Seena Fallah <[email protected]>
Add a new --create-ptr flag that enables automatic PTR record management
for any provider. When enabled, buildProvider wraps the provider with
PTRProvider and automatically adds PTR to ManagedDNSRecordTypes.

The existing --rfc2136-create-ptr flag is deprecated in favor of the
new provider-agnostic flag but remains functional for backward
compatibility.

Signed-off-by: Seena Fallah <[email protected]>
Pass --local to ko when building images locally (IMG_PUSH=false) so
images are loaded into the local Docker daemon instead of requiring
a registry.

Signed-off-by: Seena Fallah <[email protected]>
The annotation mode allows fine-grained per-resource control over PTR
creation.

Backward compatibility: --rfc2136-create-ptr still maps to "always" mode.

Signed-off-by: Seena Fallah <[email protected]>
@k8s-ci-robot k8s-ci-robot added the apis Issues or PRs related to API change label Feb 27, 2026
@k8s-ci-robot k8s-ci-robot added controller Issues or PRs related to the controller docs provider Issues or PRs related to a provider labels Feb 27, 2026
@k8s-ci-robot
Copy link
Contributor

Welcome @clwluvw!

It looks like this is your first PR to kubernetes-sigs/external-dns 🎉. Please refer to our pull request process documentation to help your PR have a smooth ride to approval.

You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. Here is the bot commands documentation.

You can also check if kubernetes-sigs/external-dns has its own contribution guidelines.

You may want to refer to our testing guide if you run into trouble with your tests not passing.

If you are having difficulty getting your pull request seen, please follow the recommended escalation practices. Also, for tips and tricks in the contribution process you may want to read the Kubernetes contributor cheat sheet. We want to make sure your contribution gets all the attention it needs!

Thank you, and welcome to Kubernetes. 😃

@k8s-ci-robot k8s-ci-robot added registry Issues or PRs related to a registry source needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Feb 27, 2026
@k8s-ci-robot
Copy link
Contributor

Hi @clwluvw. Thanks for your PR.

I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Tip

We noticed you've done this a few times! Consider joining the org to skip this step and gain /lgtm and other bot rights. We recommend asking approvers on your previous PRs to sponsor you.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Feb 27, 2026
@k8s-ci-robot k8s-ci-robot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Feb 27, 2026
Copy link
Member

@ivankatliarchuk ivankatliarchuk left a comment

Choose a reason for hiding this comment

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

The main challenge is - to test at least in 3-4 different providers.

provider/ptr.go Outdated
@@ -0,0 +1,204 @@
/*
Copyright 2025 The Kubernetes Authors.
Copy link
Member

Choose a reason for hiding this comment

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

Year is not right.
Could you move it to blueprints folder this logic?

Copy link
Member

Choose a reason for hiding this comment

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

I'm not yet sure, could be even in endpoint package. Hard to say what the correct location is at the moment

Copy link
Author

Choose a reason for hiding this comment

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

We can't move it to blueprint, PTRProvider wraps provider.Provider and we will endup in circular dependency. Do you want me to put it under its own provider pkg?

Copy link
Member

Choose a reason for hiding this comment

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

’d say this is a very unusual approach from a coding perspective. If this was AI-generated(we not against it, but worth to mention that), it would be worth spending more time understanding the existing codebase first and consider few design options.

Custom functions for things like reverseaddr, comments that are longer than the code itself, a high degree of coupling, and the introduction of a provider wrapper. Honestly, this approach is very unusual.

Layers and designs explained here https://github.com/kubernetes-sigs/external-dns/tree/master/docs/contributing

@ivankatliarchuk
Copy link
Member

/ok-to-test

@k8s-ci-robot k8s-ci-robot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Feb 27, 2026
Policy: "sync",
Provider: "",
ProviderCacheTime: 0,
CreatePTR: "off",
Copy link
Member

Choose a reason for hiding this comment

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

true|false

Copy link
Author

Choose a reason for hiding this comment

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

@ivankatliarchuk - the option can take always, annotation, and off as explained in the PR to act differently. it doesn't operate only on two modes.

Copy link
Member

Choose a reason for hiding this comment

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

You are breaking project contract. Not sure. Will w8 for other reviewers then

Copy link
Author

Choose a reason for hiding this comment

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

@ivankatliarchuk - I have changed to to boolean. my only concern was to have a control so not always create ptr records as you might want to not have ptr for certain domains and so on. so with what you described in the project contract, now annotation will control it if it is false and will always create ptr records if the flag is there. please check my last commit.

Copy link
Member

Choose a reason for hiding this comment

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

If there is an annotation on a resource - it should be applied. If the user have a controll over annotation value - it could simply remove the annotation.

So if we have flag --no-create-ptr, the external dns will not create PTR record, unless the resource has specific annotation. If we have --create-ptr with annotation set to false -> ptr record will not be created.

This is very new approach for a project to controll target type over annotation. It will take a while for sure.

Copy link
Author

Choose a reason for hiding this comment

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

It will take a while for sure.

you mean you agree with the approach or hold a different opinion? :)

Copy link
Member

Choose a reason for hiding this comment

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

I’m not particularly strong on adding new features - I tend to focus more on redesign and standardisation. It might make sense to introduce a new annotation, but right now there’s a lack of design behind it.

For example, why not consider a more generic name like target-type, which could support multiple values in the future (e.g. PTR, NAPTR, etc.)?

Also, it’s much easier to review and reason about changes when they’re submitted as small, isolated PRs. Otherwise, it becomes difficult to assess the risk and potential impact across millions of deployments.

How I would do it myself

  • PR rename flag, and move it out of the rfc provider
  • PR to add filter
  • PR to propose new annotation. For example use cases are not clear

^ all this chagnes will require testing, and end-2-end testing evidences, this is on top of unit tests coverage

Copy link
Author

Choose a reason for hiding this comment

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

Also, it’s much easier to review and reason about changes when they’re submitted as small, isolated PRs.

i tried to do that via commits, but fine also to do it via PR if it still makes sense.

^ all this chagnes will require testing, and end-2-end testing evidences, this is on top of unit tests coverage

Right, i also discovered some via testing in real with powerdns which i couldn't find them with unit testing. i thought the project already have a concept to mock other APIs. but if not we need to come with a concept for that otherwise it would be hard to say "i test it and it worked :D"

but right now there’s a lack of design behind it.

Agreed, the current implementation was my original thought about how to tackle it. i submited to get some initial feedback around it. thanks for that. but would be intresting to hear your ideas. I'm basically open to any implementation as my original concern was about PTR records, but i can see how it can be more generic.

provider/ptr.go Outdated
@@ -0,0 +1,204 @@
/*
Copyright 2025 The Kubernetes Authors.
Copy link
Member

Choose a reason for hiding this comment

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

I'm not yet sure, could be even in endpoint package. Hard to say what the correct location is at the moment

provider.BaseProvider
client PDNSAPIProvider
client PDNSAPIProvider
domainFilter *endpoint.DomainFilter
Copy link
Member

Choose a reason for hiding this comment

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

Move this endpoint.DomainFilter support to separate PR please

Copy link
Author

Choose a reason for hiding this comment

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

Opened #6234


If the annotation is not present, use the domains from both the spec and annotations.

## external-dns.alpha.kubernetes.io/create-ptr
Copy link
Member

Choose a reason for hiding this comment

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

What are the other options, aka annotations names?

Copy link
Author

Choose a reason for hiding this comment

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

In the last commit, true will opt-in and false will opt-out.

Copy link
Member

Choose a reason for hiding this comment

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

I mean the annotation name. We are using nouns. But create-ptr starts with a verb (create-), breaking the convention. The closest parallel is alias — you set alias: "true" to create an alias record. We don't call it create-alias. This is why I was asking, which other annotation names you have considered?

The --create-ptr CLI flag name most likley makes sense as a boolean flag, but the annotation doesn't need the create- prefix.

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from ivankatliarchuk. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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

Add --create-ptr boolean flag (default: false) that enables automatic
PTR record creation for all providers. The create-ptr annotation
overrides the flag per resource, following the project's configuration
precedence contract.

Signed-off-by: Seena Fallah <[email protected]>
@clwluvw clwluvw force-pushed the generic-ptr-provider branch from e40e932 to cb9687a Compare February 27, 2026 20:15
@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Feb 27, 2026
Copy link
Member

@ivankatliarchuk ivankatliarchuk left a comment

Choose a reason for hiding this comment

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

worth to review where DNSEndpoint supports PTR as well

@clwluvw
Copy link
Author

clwluvw commented Mar 6, 2026

worth to review where DNSEndpoint supports PTR as well

AFAIU, we can use:

apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
spec:
  endpoints:
  - dnsName: 2.49.168.192.in-addr.arpa
    recordType: PTR
    targets:
    - web.example.com

also we can do something like:

apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
metadata:
  name: web
spec:
  endpoints:
  - dnsName: web.example.com
    recordType: A
    targets:
    - 192.168.49.2
    providerSpecific:
    - name: record-type
      value: ptr

@ivankatliarchuk
Copy link
Member

worth to review where DNSEndpoint supports PTR as well

AFAIU, we can use:

apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
spec:
  endpoints:
  - dnsName: 2.49.168.192.in-addr.arpa
    recordType: PTR
    targets:
    - web.example.com

also we can do something like:

apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
metadata:
  name: web
spec:
  endpoints:
  - dnsName: web.example.com
    recordType: A
    targets:
    - 192.168.49.2
    providerSpecific:
    - name: record-type
      value: ptr

Yeah, this is where we need other maintainers, but not sure whey someone is free. This case

apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
spec:
  endpoints:
  - dnsName: 2.49.168.192.in-addr.arpa
    recordType: PTR

^ 100% we should support if we do not support, dedicated PR is required, as it is what DNSEndpoint is for.

In regards below example, second opinion is needed.

 providerSpecific:
   - name: record-type
      value: ptr

@clwluvw
Copy link
Author

clwluvw commented Mar 6, 2026

@ivankatliarchuk - thanks let me know if something is still needed from my side. After #6234 is merged I can rebase and do another test like e2e.sh there to test these scenarios on powerdns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

apis Issues or PRs related to API change cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. controller Issues or PRs related to the controller docs ok-to-test Indicates a non-member PR verified by an org member that is safe to test. provider Issues or PRs related to a provider registry Issues or PRs related to a registry 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.

3 participants