mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2026-05-04 22:26:11 +02:00
feat(coredns): add annotations for coredns groups (#5842)
Signed-off-by: Jan Jansen <jan.jansen@gdata.de>
This commit is contained in:
parent
413015ea76
commit
8851544c1c
@ -260,3 +260,78 @@ dnstools# dig @10.100.4.143 nginx.example.org +short
|
||||
10.0.2.15
|
||||
dnstools#
|
||||
```
|
||||
|
||||
## Specific service annotation options
|
||||
|
||||
### Groups
|
||||
|
||||
Groups can be used to group set of services together. The main use of this is to limit recursion,
|
||||
i.e. don't return all records, but only a subset. Let's say we have a configuration like this:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: a
|
||||
annotations:
|
||||
external-dns.alpha.kubernetes.io/hostname: a.domain.local
|
||||
external-dns.alpha.kubernetes.io/coredns-group: "g1"
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
...
|
||||
status:
|
||||
loadBalancer:
|
||||
ingress:
|
||||
- ip: 127.0.0.1
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: b
|
||||
annotations:
|
||||
external-dns.alpha.kubernetes.io/hostname: b.domain.local
|
||||
external-dns.alpha.kubernetes.io/coredns-group: "g1"
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
...
|
||||
status:
|
||||
loadBalancer:
|
||||
ingress:
|
||||
- ip: 127.0.0.2
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: c
|
||||
annotations:
|
||||
external-dns.alpha.kubernetes.io/hostname: c.subdom.domain.local
|
||||
external-dns.alpha.kubernetes.io/coredns-group: "g2"
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
...
|
||||
status:
|
||||
loadBalancer:
|
||||
ingress:
|
||||
- ip: 127.0.0.3
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: d
|
||||
annotations:
|
||||
external-dns.alpha.kubernetes.io/hostname: d.subdom.domain.local
|
||||
external-dns.alpha.kubernetes.io/coredns-group: "g2"
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
...
|
||||
status:
|
||||
loadBalancer:
|
||||
ingress:
|
||||
- ip: 127.0.0.4
|
||||
|
||||
```
|
||||
|
||||
And we want domain.local to return (127.0.0.1 and 127.0.0.2) and subdom.domain.local to return (127.0.0.3 and 127.0.0.4).
|
||||
For this the two domains, need to be in different groups. What those groups are does not matter,
|
||||
as long as a and b belong to the same group which is different from the group c and d belong to.
|
||||
If a service is found without a group it is always included.
|
||||
|
||||
@ -41,7 +41,8 @@ const (
|
||||
priority = 10 // default priority when nothing is set
|
||||
etcdTimeout = 5 * time.Second
|
||||
|
||||
randomPrefixLabel = "prefix"
|
||||
randomPrefixLabel = "prefix"
|
||||
providerSpecificGroup = "coredns/group"
|
||||
)
|
||||
|
||||
// coreDNSClient is an interface to work with CoreDNS service records in etcd
|
||||
@ -260,6 +261,9 @@ func (p coreDNSProvider) Records(_ context.Context) ([]*endpoint.Endpoint, error
|
||||
endpoint.TTL(service.TTL),
|
||||
service.Host,
|
||||
)
|
||||
if service.Group != "" {
|
||||
ep.WithProviderSpecific(providerSpecificGroup, service.Group)
|
||||
}
|
||||
log.Debugf("Creating new ep (%s) with new service host (%s)", ep, service.Host)
|
||||
}
|
||||
ep.Labels["originalText"] = service.Text
|
||||
@ -346,12 +350,17 @@ func (p coreDNSProvider) createServicesForEndpoint(dnsName string, ep *endpoint.
|
||||
prefix = fmt.Sprintf("%08x", rand.Int31())
|
||||
log.Infof("Generating new prefix: (%s)", prefix)
|
||||
}
|
||||
group := ""
|
||||
if prop, ok := ep.GetProviderSpecificProperty(providerSpecificGroup); ok {
|
||||
group = prop
|
||||
}
|
||||
service := Service{
|
||||
Host: target,
|
||||
Text: ep.Labels["originalText"],
|
||||
Key: p.etcdKeyFor(prefix + "." + dnsName),
|
||||
TargetStrip: strings.Count(prefix, ".") + 1,
|
||||
TTL: uint32(ep.RecordTTL),
|
||||
Group: group,
|
||||
}
|
||||
services = append(services, &service)
|
||||
ep.Labels[target] = prefix
|
||||
|
||||
@ -460,7 +460,7 @@ func validateServices(services map[string]Service, expectedServices map[string][
|
||||
}
|
||||
found := false
|
||||
for i, expectedServiceEntry := range expectedServiceEntries {
|
||||
if value.Host == expectedServiceEntry.Host && value.Text == expectedServiceEntry.Text {
|
||||
if value.Host == expectedServiceEntry.Host && value.Text == expectedServiceEntry.Text && value.Group == expectedServiceEntry.Group {
|
||||
expectedServiceEntries = append(expectedServiceEntries[:i], expectedServiceEntries[i+1:]...)
|
||||
found = true
|
||||
break
|
||||
@ -863,3 +863,48 @@ func TestCoreDNSProvider_updateTXTRecords_ClearsExtraText(t *testing.T) {
|
||||
assert.Equal(t, "txt-value", services[0].Text)
|
||||
assert.Empty(t, services[1].Text)
|
||||
}
|
||||
|
||||
func TestApplyChangesAWithGroupServiceTranslation(t *testing.T) {
|
||||
client := fakeETCDClient{
|
||||
map[string]Service{},
|
||||
}
|
||||
coredns := coreDNSProvider{
|
||||
client: client,
|
||||
coreDNSPrefix: defaultCoreDNSPrefix,
|
||||
}
|
||||
|
||||
changes1 := &plan.Changes{
|
||||
Create: []*endpoint.Endpoint{
|
||||
endpoint.NewEndpoint("domain1.local", endpoint.RecordTypeA, "5.5.5.5").WithProviderSpecific(providerSpecificGroup, "test1"),
|
||||
endpoint.NewEndpoint("domain2.local", endpoint.RecordTypeA, "5.5.5.6").WithProviderSpecific(providerSpecificGroup, "test1"),
|
||||
endpoint.NewEndpoint("domain3.local", endpoint.RecordTypeA, "5.5.5.7").WithProviderSpecific(providerSpecificGroup, "test2"),
|
||||
},
|
||||
}
|
||||
coredns.ApplyChanges(context.Background(), changes1)
|
||||
|
||||
expectedServices1 := map[string][]*Service{
|
||||
"/skydns/local/domain1": {{Host: "5.5.5.5", Group: "test1"}},
|
||||
"/skydns/local/domain2": {{Host: "5.5.5.6", Group: "test1"}},
|
||||
"/skydns/local/domain3": {{Host: "5.5.5.7", Group: "test2"}},
|
||||
}
|
||||
validateServices(client.services, expectedServices1, t, 1)
|
||||
}
|
||||
|
||||
func TestRecordsAWithGroupServiceTranslation(t *testing.T) {
|
||||
client := fakeETCDClient{
|
||||
map[string]Service{
|
||||
"/skydns/local/domain1": {Host: "5.5.5.5", Group: "test1"},
|
||||
},
|
||||
}
|
||||
coredns := coreDNSProvider{
|
||||
client: client,
|
||||
coreDNSPrefix: defaultCoreDNSPrefix,
|
||||
}
|
||||
endpoints, err := coredns.Records(context.Background())
|
||||
require.NoError(t, err)
|
||||
if prop, ok := endpoints[0].GetProviderSpecificProperty(providerSpecificGroup); !ok {
|
||||
t.Error("go no Group name")
|
||||
} else if prop != "test1" {
|
||||
t.Errorf("got unexpected Group name: %s != %s", prop, "test1")
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ const (
|
||||
CloudflareRecordCommentKey = AnnotationKeyPrefix + "cloudflare-record-comment"
|
||||
|
||||
AWSPrefix = AnnotationKeyPrefix + "aws-"
|
||||
CoreDNSPrefix = AnnotationKeyPrefix + "coredns-"
|
||||
SCWPrefix = AnnotationKeyPrefix + "scw-"
|
||||
WebhookPrefix = AnnotationKeyPrefix + "webhook-"
|
||||
CloudflarePrefix = AnnotationKeyPrefix + "cloudflare-"
|
||||
|
||||
@ -49,6 +49,11 @@ func ProviderSpecificAnnotations(annotations map[string]string) (endpoint.Provid
|
||||
Name: fmt.Sprintf("webhook/%s", attr),
|
||||
Value: v,
|
||||
})
|
||||
} else if attr, ok := strings.CutPrefix(k, CoreDNSPrefix); ok {
|
||||
providerSpecificAnnotations = append(providerSpecificAnnotations, endpoint.ProviderSpecificProperty{
|
||||
Name: fmt.Sprintf("coredns/%s", attr),
|
||||
Value: v,
|
||||
})
|
||||
} else if strings.HasPrefix(k, CloudflarePrefix) {
|
||||
if strings.Contains(k, CloudflareCustomHostnameKey) {
|
||||
providerSpecificAnnotations = append(providerSpecificAnnotations, endpoint.ProviderSpecificProperty{
|
||||
|
||||
@ -64,6 +64,16 @@ func TestProviderSpecificAnnotations(t *testing.T) {
|
||||
},
|
||||
setIdentifier: "",
|
||||
},
|
||||
{
|
||||
name: "CoreDNS annotation",
|
||||
annotations: map[string]string{
|
||||
"external-dns.alpha.kubernetes.io/coredns-group": "g1",
|
||||
},
|
||||
expected: endpoint.ProviderSpecific{
|
||||
{Name: "coredns/group", Value: "g1"},
|
||||
},
|
||||
setIdentifier: "",
|
||||
},
|
||||
{
|
||||
name: "Set identifier annotation",
|
||||
annotations: map[string]string{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user