Skip to content
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

feat: configure arbitrary provider-specific properties via annotations #4875

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions docs/annotations/annotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The following table documents which sources support which annotations:
| Connector | | | | | | |
| Contour | Yes | Yes[^1] | | Yes | Yes | Yes |
| CloudFoundry | | | | | | |
| CRD | | | | | | |
| CRD | | Yes | | Yes | Yes | Yes |
| F5 | | | | Yes | Yes | |
| Gateway | Yes | Yes[^1] | | Yes[^4] | Yes | Yes |
| Gloo | | | | Yes | Yes[^5] | Yes[^5] |
Expand Down Expand Up @@ -101,7 +101,13 @@ It must be between 1 and 2,147,483,647 seconds.

## Provider-specific annotations

Some providers define their own annotations. Cloud-specific annotations have keys prefixed as follows:
Provider-specific annotations are prefixed by `external-dns.alpha.kubernetes.io/`
and the provider's name, for example `external-dns.alpha.kubernetes.io/aws-`.

Individual provider implementations should be examined to identify the additional
configuration offered via supported annotations.

Currently, supported Cloud-specific annotations include the following prefixes:

| Cloud | Annotation prefix |
|------------|------------------------------------------------|
Expand Down
21 changes: 7 additions & 14 deletions docs/sources/crd/dnsendpoint-aws-example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,10 @@ apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
metadata:
name: examplednsrecord
spec:
endpoints:
- dnsName: subdomain.foo.bar.com
providerSpecific:
- name: "aws/failover"
value: "PRIMARY"
- name: "aws/health-check-id"
value: "asdf1234-as12-as12-as12-asdf12345678"
- name: "aws/evaluate-target-health"
value: "true"
recordType: CNAME
setIdentifier: some-unique-id
targets:
- other-subdomain.foo.bar.com
annotations:
external-dns.alpha.kubernetes.io/hostname: "subdomain.foo.bar.com"
external-dns.alpha.kubernetes.io/target: "other-subdomain.foo.bar.com"
external-dns.alpha.kubernetes.io/set-identifier: "some-unique-id"
external-dns.alpha.kubernetes.io/aws-failover: "PRIMARY"
external-dns.alpha.kubernetes.io/aws-health-check-id: "asdf1234-as12-as12-as12-asdf12345678"
external-dns.alpha.kubernetes.io/aws-evaluate-target-health: "true"
16 changes: 5 additions & 11 deletions docs/sources/crd/dnsendpoint-example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,8 @@ apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
metadata:
name: examplednsrecord
spec:
endpoints:
- dnsName: foo.bar.com
recordTTL: 180
recordType: A
targets:
- 192.168.99.216
# Provider specific configurations are set like an annotation would on other sources
providerSpecific:
- name: external-dns.alpha.kubernetes.io/cloudflare-proxied
value: "true"
annotations:
external-dns.alpha.kubernetes.io/hostname: foo.bar.com
external-dns.alpha.kubernetes.io/target: 192.168.99.216
external-dns.alpha.kubernetes.io/ttl: "180"
external-dns.alpha.kubernetes.io/cloudflare-proxied: "true"
6 changes: 0 additions & 6 deletions docs/tutorials/webhook-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,6 @@ The default recommended port for the provider endpoints is `8888`, and should li

The default recommended port for the exposed endpoints is `8080`, and it should be bound to all interfaces (`0.0.0.0`)

## Custom Annotations

The Webhook provider supports custom annotations for DNS records. This feature allows users to define additional configuration options for DNS records managed by the Webhook provider. Custom annotations are defined using the annotation format `external-dns.alpha.kubernetes.io/webhook-<custom-annotation>`.

Custom annotations can be used to influence DNS record creation and updates. Providers implementing the Webhook API should document the custom annotations they support and how they affect DNS record management.

## Provider registry

To simplify the discovery of providers, we will accept pull requests that will add links to providers in this documentation.
Expand Down
20 changes: 10 additions & 10 deletions provider/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,19 @@ const (
route53PageSize int32 = 300
// providerSpecificAlias specifies whether a CNAME endpoint maps to an AWS ALIAS record.
providerSpecificAlias = "alias"
providerSpecificTargetHostedZone = "aws/target-hosted-zone"
providerSpecificTargetHostedZone = "aws-target-hosted-zone"
// providerSpecificEvaluateTargetHealth specifies whether an AWS ALIAS record
// has the EvaluateTargetHealth field set to true. Present iff the endpoint
// has a `providerSpecificAlias` value of `true`.
providerSpecificEvaluateTargetHealth = "aws/evaluate-target-health"
providerSpecificWeight = "aws/weight"
providerSpecificRegion = "aws/region"
providerSpecificFailover = "aws/failover"
providerSpecificGeolocationContinentCode = "aws/geolocation-continent-code"
providerSpecificGeolocationCountryCode = "aws/geolocation-country-code"
providerSpecificGeolocationSubdivisionCode = "aws/geolocation-subdivision-code"
providerSpecificMultiValueAnswer = "aws/multi-value-answer"
providerSpecificHealthCheckID = "aws/health-check-id"
providerSpecificEvaluateTargetHealth = "aws-evaluate-target-health"
providerSpecificWeight = "aws-weight"
providerSpecificRegion = "aws-region"
providerSpecificFailover = "aws-failover"
providerSpecificGeolocationContinentCode = "aws-geolocation-continent-code"
providerSpecificGeolocationCountryCode = "aws-geolocation-country-code"
providerSpecificGeolocationSubdivisionCode = "aws-geolocation-subdivision-code"
providerSpecificMultiValueAnswer = "aws-multi-value-answer"
providerSpecificHealthCheckID = "aws-health-check-id"
sameZoneAlias = "same-zone"
// Currently supported up to 10 health checks or hosted zones.
// https://docs.aws.amazon.com/Route53/latest/APIReference/API_ListTagsForResources.html#API_ListTagsForResources_RequestSyntax
Expand Down
17 changes: 10 additions & 7 deletions provider/cloudflare/cloudflare.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import (
"sigs.k8s.io/external-dns/endpoint"
"sigs.k8s.io/external-dns/plan"
"sigs.k8s.io/external-dns/provider"
"sigs.k8s.io/external-dns/source"
)

const (
Expand All @@ -44,6 +43,10 @@ const (
cloudFlareUpdate = "UPDATE"
// defaultCloudFlareRecordTTL 1 = automatic
defaultCloudFlareRecordTTL = 1

providerSpecificCustomHostnameKey = "cloudflare-custom-hostname"
// providerSpecificProxied specifies whether traffic will go through Cloudflare
providerSpecificProxied = "cloudflare-proxied"
)

// We have to use pointers to bools now, as the upstream cloudflare-go library requires them
Expand Down Expand Up @@ -499,7 +502,7 @@ func (p *CloudFlareProvider) AdjustEndpoints(endpoints []*endpoint.Endpoint) ([]
if proxied {
e.RecordTTL = 0
}
e.SetProviderSpecificProperty(source.CloudflareProxiedKey, strconv.FormatBool(proxied))
e.SetProviderSpecificProperty(providerSpecificProxied, strconv.FormatBool(proxied))

adjustedEndpoints = append(adjustedEndpoints, e)
}
Expand Down Expand Up @@ -647,10 +650,10 @@ func shouldBeProxied(endpoint *endpoint.Endpoint, proxiedByDefault bool) bool {
proxied := proxiedByDefault

for _, v := range endpoint.ProviderSpecific {
if v.Name == source.CloudflareProxiedKey {
if v.Name == providerSpecificProxied {
b, err := strconv.ParseBool(v.Value)
if err != nil {
log.Errorf("Failed to parse annotation [%s]: %v", source.CloudflareProxiedKey, err)
log.Errorf("Failed parsing value of %s: %v", providerSpecificProxied, err)
} else {
proxied = b
}
Expand All @@ -666,7 +669,7 @@ func shouldBeProxied(endpoint *endpoint.Endpoint, proxiedByDefault bool) bool {

func getEndpointCustomHostname(endpoint *endpoint.Endpoint) string {
for _, v := range endpoint.ProviderSpecific {
if v.Name == source.CloudflareCustomHostnameKey {
if v.Name == providerSpecificCustomHostnameKey {
return v.Value
}
}
Expand Down Expand Up @@ -721,9 +724,9 @@ func groupByNameAndTypeWithCustomHostnames(records []cloudflare.DNSRecord, chs [
if ep == nil {
continue
}
ep.WithProviderSpecific(source.CloudflareProxiedKey, strconv.FormatBool(proxied))
ep.WithProviderSpecific(providerSpecificProxied, strconv.FormatBool(proxied))
if customHostname, ok := customOriginServers[records[0].Name]; ok {
ep.WithProviderSpecific(source.CloudflareCustomHostnameKey, customHostname)
ep.WithProviderSpecific(providerSpecificCustomHostnameKey, customHostname)
}

endpoints = append(endpoints, ep)
Expand Down
32 changes: 16 additions & 16 deletions provider/cloudflare/cloudflare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ func TestCloudflareProxiedOverrideTrue(t *testing.T) {
Targets: endpoint.Targets{"127.0.0.1"},
ProviderSpecific: endpoint.ProviderSpecific{
endpoint.ProviderSpecificProperty{
Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied",
Name: providerSpecificProxied,
Value: "true",
},
},
Expand Down Expand Up @@ -555,7 +555,7 @@ func TestCloudflareProxiedOverrideFalse(t *testing.T) {
Targets: endpoint.Targets{"127.0.0.1"},
ProviderSpecific: endpoint.ProviderSpecific{
endpoint.ProviderSpecificProperty{
Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied",
Name: providerSpecificProxied,
Value: "false",
},
},
Expand Down Expand Up @@ -587,7 +587,7 @@ func TestCloudflareProxiedOverrideIllegal(t *testing.T) {
Targets: endpoint.Targets{"127.0.0.1"},
ProviderSpecific: endpoint.ProviderSpecific{
endpoint.ProviderSpecificProperty{
Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied",
Name: providerSpecificProxied,
Value: "asfasdfa",
},
},
Expand Down Expand Up @@ -638,7 +638,7 @@ func TestCloudflareSetProxied(t *testing.T) {
Targets: endpoint.Targets{"127.0.0.1"},
ProviderSpecific: endpoint.ProviderSpecific{
endpoint.ProviderSpecificProperty{
Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied",
Name: providerSpecificProxied,
Value: "true",
},
},
Expand Down Expand Up @@ -1008,7 +1008,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
Labels: endpoint.Labels{},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied",
Name: providerSpecificProxied,
Value: "false",
},
},
Expand Down Expand Up @@ -1042,7 +1042,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
Labels: endpoint.Labels{},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied",
Name: providerSpecificProxied,
Value: "false",
},
},
Expand Down Expand Up @@ -1090,7 +1090,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
Labels: endpoint.Labels{},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied",
Name: providerSpecificProxied,
Value: "false",
},
},
Expand All @@ -1103,7 +1103,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
Labels: endpoint.Labels{},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied",
Name: providerSpecificProxied,
Value: "false",
},
},
Expand Down Expand Up @@ -1144,7 +1144,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
Labels: endpoint.Labels{},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied",
Name: providerSpecificProxied,
Value: "false",
},
},
Expand All @@ -1157,7 +1157,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
Labels: endpoint.Labels{},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied",
Name: providerSpecificProxied,
Value: "false",
},
},
Expand Down Expand Up @@ -1198,7 +1198,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
Labels: endpoint.Labels{},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied",
Name: providerSpecificProxied,
Value: "false",
},
},
Expand Down Expand Up @@ -1338,7 +1338,7 @@ func TestCloudflareComplexUpdate(t *testing.T) {
Labels: endpoint.Labels{},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied",
Name: providerSpecificProxied,
Value: "true",
},
},
Expand Down Expand Up @@ -1423,7 +1423,7 @@ func TestCustomTTLWithEnabledProxyNotChanged(t *testing.T) {
Labels: endpoint.Labels{},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "external-dns.alpha.kubernetes.io/cloudflare-proxied",
Name: providerSpecificProxied,
Value: "true",
},
},
Expand Down Expand Up @@ -1653,7 +1653,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
Labels: endpoint.Labels{},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "external-dns.alpha.kubernetes.io/cloudflare-custom-hostname",
Name: providerSpecificCustomHostnameKey,
Value: "a.foo.fancybar.com",
},
},
Expand All @@ -1666,7 +1666,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
Labels: endpoint.Labels{},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "external-dns.alpha.kubernetes.io/cloudflare-custom-hostname",
Name: providerSpecificCustomHostnameKey,
Value: "txt.foo.fancybar.com",
},
},
Expand All @@ -1688,7 +1688,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
Labels: endpoint.Labels{},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "external-dns.alpha.kubernetes.io/cloudflare-custom-hostname",
Name: providerSpecificCustomHostnameKey,
Value: "a2.foo.fancybar.com",
},
},
Expand Down
2 changes: 1 addition & 1 deletion provider/ibmcloud/ibmcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ func shouldBeProxied(endpoint *endpoint.Endpoint, proxiedByDefault bool) bool {
if v.Name == proxyFilter {
b, err := strconv.ParseBool(v.Value)
if err != nil {
log.Errorf("Failed to parse annotation [%s]: %v", proxyFilter, err)
log.Errorf("Failed parsing value of %s: %v", proxyFilter, err)
} else {
proxied = b
}
Expand Down
14 changes: 7 additions & 7 deletions provider/ibmcloud/ibmcloud_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func newTestIBMCloudProvider(private bool) *IBMCloudProvider {
Targets: endpoint.Targets{"4.3.2.1"},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "ibmcloud-vpc",
Name: vpcFilter,
Value: "crn:v1:staging:public:is:us-south:a/0821fa9f9ebcc7b7c9a0d6e9bf9442a4::vpc:be33cdad-9a03-4bfa-82ca-eadb9f1de688",
},
},
Expand Down Expand Up @@ -223,7 +223,7 @@ func TestPublic_ApplyChanges(t *testing.T) {
Targets: endpoint.NewTargets("4.3.2.1"),
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "ibmcloud-proxied",
Name: proxyFilter,
Value: "false",
},
},
Expand All @@ -237,7 +237,7 @@ func TestPublic_ApplyChanges(t *testing.T) {
Targets: endpoint.NewTargets("1.2.3.4"),
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "ibmcloud-proxied",
Name: proxyFilter,
Value: "false",
},
},
Expand All @@ -251,7 +251,7 @@ func TestPublic_ApplyChanges(t *testing.T) {
Targets: endpoint.NewTargets("1.2.3.4", "5.6.7.8"),
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "ibmcloud-proxied",
Name: proxyFilter,
Value: "true",
},
},
Expand Down Expand Up @@ -284,7 +284,7 @@ func TestPrivate_ApplyChanges(t *testing.T) {
Targets: endpoint.NewTargets("4.3.2.1"),
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "ibmcloud-vpc",
Name: vpcFilter,
Value: "crn:v1:staging:public:is:us-south:a/0821fa9f9ebcc7b7c9a0d6e9bf9442a4::vpc:be33cdad-9a03-4bfa-82ca-eadb9f1de688",
},
},
Expand Down Expand Up @@ -352,7 +352,7 @@ func TestAdjustEndpoints(t *testing.T) {
Labels: endpoint.Labels{},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "ibmcloud-proxied",
Name: proxyFilter,
Value: "1",
},
},
Expand All @@ -364,7 +364,7 @@ func TestAdjustEndpoints(t *testing.T) {

assert.Equal(t, endpoint.TTL(0), ep[0].RecordTTL)
assert.Equal(t, "test.example.com", ep[0].DNSName)
proxied, _ := ep[0].GetProviderSpecificProperty("ibmcloud-proxied")
proxied, _ := ep[0].GetProviderSpecificProperty(proxyFilter)
assert.Equal(t, "true", proxied)
}

Expand Down
Loading
Loading