* feat(annotations): add custom annotation prefix support for split horizon DNS
Add --annotation-prefix flag to allow customizing the annotation prefix
used by external-dns. This enables split horizon DNS scenarios where
multiple instances process different sets of annotations from the same
Kubernetes resources.
Changes:
- Add AnnotationPrefix field to Config with validation
- Convert annotation constants to variables that can be reconfigured
- Add SetAnnotationPrefix() function to rebuild annotation keys
- Integrate annotation prefix setting in controller startup
- Update Helm chart with annotationPrefix value
- Add comprehensive split horizon DNS documentation
- Update FAQ with annotation prefix examples
This maintains full backward compatibility - the default prefix remains
"external-dns.alpha.kubernetes.io/".
Co-Authored-By: Claude <noreply@anthropic.com>
* docs(advanced): fix markdown formatting in split-horizon guide
Add blank lines before code blocks to improve markdown rendering
and comply with markdownlint rules.
Co-Authored-By: Claude <noreply@anthropic.com>
* docs(advanced): fix markdown formatting in split-horizon guide
Co-Authored-By: Claude <noreply@anthropic.com>
* docs(charts): regenerate Helm chart documentation
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add AnnotationPrefix field to test configs
Add missing AnnotationPrefix field to minimalConfig and overriddenConfig
test configurations to match the new default value set in NewConfig().
Co-Authored-By: Claude <noreply@anthropic.com>
* test(charts): update error pattern in json-schema test
Update expected error message pattern to match current Helm validation
output format.
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(annotations): remove init() for explicit initialization
- Remove init() function from annotations package
- Add explicit SetAnnotationPrefix() call in controller/execute.go
- Remove annotation key aliases from source/source.go
- Replace all alias usages with annotations.* references (348 changes in 28 files)
- Add TestMain to existing test files (service_test.go, cloudflare_test.go)
This change makes annotation initialization explicit and predictable,
avoiding hidden global state initialization at import time.
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: update changelog and mkdocs to include annotationPrefix and split horizon DNS
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* docs(split-horizon): fix linting
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* refactor(annotations): replace hardcoded annotation prefix with constant
Replace all hardcoded "external-dns.alpha.kubernetes.io/" strings
with annotations.DefaultAnnotationPrefix constant to establish
a single source of truth.
Changes:
- Add DefaultAnnotationPrefix constant in source/annotations/annotations.go
- Replace hardcoded string in controller/execute.go with constant reference
- Replace hardcoded strings in pkg/apis/externaldns/types.go (2 occurrences)
- Add helm unit tests for annotationPrefix value
This eliminates string duplication and makes future changes easier.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Signed-off-by: Aleksei Sviridkin <f@lex.la>
Co-authored-by: Claude <noreply@anthropic.com>
* chore(source/service): serviceTypeFilter edge case tests
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
* chore(source/service): serviceTypeFilter edge case tests
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
---------
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
* feat: reduce cyclomatic complexity of service_test
* style: indention added
* style: tab
* refactor: address PR feedback, improve tests, and reduce complexity
* fix(service): address PR feedback and fix linting
* Revert "fix(service): address PR feedback and fix linting"
This reverts commit 4cba488dc741ee1d946b105da952c09893c289c4.
* refactor: address all PR feedback - improve method naming, add test coverage, fix parameter ordering
* refactor: address latest PR feedback - convert to method, use testutils, add test coverage
* test: add coverage for pod hostname scenario
Addresses 4th to last PR comment about missing test coverage for
the case where pod.Spec.Hostname is set, which creates additional
headless domains (pod-specific hostname + base hostname)
* style: remove extra line
Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com>
* style: remove extra line
Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com>
---------
Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com>
* feat: use transformers in pod informers to reduce memory footprint
Add a transformer to the pods informer of the pod and service sources.
Refs: #5595
Signed-off-by: Valerian Roche <valerian.roche@datadoghq.com>
* Do not use transformer when fqdnTemplate is set
* Update source/pod_test.go
Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com>
---------
Signed-off-by: Valerian Roche <valerian.roche@datadoghq.com>
Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com>
* fix(source/service): disable pod and endpointSlicesInformer when not required
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
* fix(source/service): disable pod and endpointSlicesInformer when not required
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
* fix(source/service): disable pod and endpointSlices informers when they are not needed
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
* fix(source/service): disable pod and endpointSlices informers when they are not needed
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
---------
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
* fix(source/service): disable node informer when service type filter is activated
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
fix(source/service): disable node informer when service type filter is activated
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
fix(source/service): disable node informer when service type filter is activated
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
fix(source/service): disable node informer when service type filter is activated
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
* fix(source/service): disable node informer when service type filter is activated
Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com>
* fix(source/service): disable node informer when service type filter is activated
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
---------
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com>
* chore(source/service): restructure code with filters are testable
* chore(source/service): restructure code with filters are testable
Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com>
* chore(source/service): restructure code with filters are testable
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
---------
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com>
If external-dns.alpha.kubernetes.io/target annotation is present on a
pod, it's value will be used as the target for the headless service.
If annotation external-dns.alpha.kubernetes.io/access=public is present,
NodeExternalIP of the node running the pod is used as the target for the
headless service.
Currently the `--label-filter` flag can only be used to filter CRDs
which match the label selector passed through that flag. This change
extends the functionality to the Ingress, Service and Openshift Route
type objects. When the flag is not specified the default value is
`labels.Everything()` which is an empty string, the same as before.
Annotation based filter is inefficient because the filtering has to be
done in the controller instead of the API server like with label
filtering.