mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-05 17:16:59 +02:00
Implement target annotation for more sources
This commit is contained in:
parent
859892fc72
commit
4a32aaec01
@ -5,21 +5,21 @@ ExternalDNS sources support a number of annotations on the Kubernetes resources
|
||||
The following table documents which sources support which annotations:
|
||||
|
||||
| Source | controller | hostname | internal-hostname | target | ttl | (provider-specific) |
|
||||
|--------------|------------|----------|-------------------|---------|-----|---------------------|
|
||||
| Ambassador | | | | | Yes | |
|
||||
|--------------|------------|----------|-------------------|---------|---------|---------------------|
|
||||
| Ambassador | | | | Yes | Yes | |
|
||||
| Connector | | | | | | |
|
||||
| Contour | Yes | Yes[^1] | | Yes | Yes | Yes |
|
||||
| CloudFoundry | | | | | | |
|
||||
| CRD | | | | | | |
|
||||
| F5 | | | | | Yes | |
|
||||
| F5 | | | | Yes | Yes | |
|
||||
| Gateway | Yes | Yes[^1] | | Yes[^4] | Yes | Yes |
|
||||
| Gloo | | | | | Yes | Yes |
|
||||
| Gloo | | | | Yes | Yes[^5] | Yes[^5] |
|
||||
| Ingress | Yes | Yes[^1] | | Yes | Yes | Yes |
|
||||
| Istio | Yes | Yes[^1] | | Yes | Yes | Yes |
|
||||
| Kong | | Yes | | | Yes | Yes |
|
||||
| Node | Yes | | | | Yes | |
|
||||
| Kong | | Yes | | Yes | Yes | Yes |
|
||||
| Node | Yes | | | Yes | Yes | |
|
||||
| OpenShift | Yes | Yes[^1] | | Yes | Yes | Yes |
|
||||
| Pod | | Yes | Yes | | | |
|
||||
| Pod | | Yes | Yes | Yes | | |
|
||||
| Service | Yes | Yes[^1] | Yes[^1][^2] | Yes[^3] | Yes | Yes |
|
||||
| Skipper | Yes | Yes[^1] | | Yes | Yes | Yes |
|
||||
| Traefik | | Yes | | Yes | Yes | Yes |
|
||||
@ -27,7 +27,8 @@ The following table documents which sources support which annotations:
|
||||
[^1]: Unless the `--ignore-hostname-annotation` flag is specified.
|
||||
[^2]: Only behaves differently than `hostname` for `Service`s of type `ClusterIP` or `LoadBalancer`.
|
||||
[^3]: Also supported on `Pods` referenced from a headless `Service`'s `Endpoints`.
|
||||
[^4]: The annotation should be on the `Gateway`
|
||||
[^4]: The annotation must be on the `Gateway`.
|
||||
[^5]: The annotation must be on the listener's `VirtualService`.
|
||||
|
||||
## external-dns.alpha.kubernetes.io/access
|
||||
|
||||
|
@ -133,11 +133,14 @@ func (sc *ambassadorHostSource) Endpoints(ctx context.Context) ([]*endpoint.Endp
|
||||
continue
|
||||
}
|
||||
|
||||
targets, err := sc.targetsFromAmbassadorLoadBalancer(ctx, service)
|
||||
targets := getTargetsFromTargetAnnotation(host.Annotations)
|
||||
if len(targets) == 0 {
|
||||
targets, err = sc.targetsFromAmbassadorLoadBalancer(ctx, service)
|
||||
if err != nil {
|
||||
log.Warningf("Could not find targets for service %s for Host %s: %v", service, fullname, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
hostEndpoints, err := sc.endpointsFromHost(ctx, host, targets)
|
||||
if err != nil {
|
||||
|
@ -152,37 +152,16 @@ func (vs *f5VirtualServerSource) endpointsFromVirtualServers(virtualServers []*f
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if virtualServer.Spec.VirtualServerAddress != "" {
|
||||
ep := &endpoint.Endpoint{
|
||||
Targets: endpoint.Targets{
|
||||
virtualServer.Spec.VirtualServerAddress,
|
||||
},
|
||||
RecordType: "A",
|
||||
DNSName: virtualServer.Spec.Host,
|
||||
Labels: endpoint.NewLabels(),
|
||||
RecordTTL: ttl,
|
||||
targets := getTargetsFromTargetAnnotation(virtualServer.Annotations)
|
||||
if len(targets) == 0 && virtualServer.Spec.VirtualServerAddress != "" {
|
||||
targets = append(targets, virtualServer.Spec.VirtualServerAddress)
|
||||
}
|
||||
if len(targets) == 0 && virtualServer.Status.VSAddress != "" {
|
||||
targets = append(targets, virtualServer.Status.VSAddress)
|
||||
}
|
||||
|
||||
vs.setResourceLabel(virtualServer, ep)
|
||||
endpoints = append(endpoints, ep)
|
||||
continue
|
||||
}
|
||||
|
||||
if virtualServer.Status.VSAddress != "" {
|
||||
ep := &endpoint.Endpoint{
|
||||
Targets: endpoint.Targets{
|
||||
virtualServer.Status.VSAddress,
|
||||
},
|
||||
RecordType: "A",
|
||||
DNSName: virtualServer.Spec.Host,
|
||||
Labels: endpoint.NewLabels(),
|
||||
RecordTTL: ttl,
|
||||
}
|
||||
|
||||
vs.setResourceLabel(virtualServer, ep)
|
||||
endpoints = append(endpoints, ep)
|
||||
continue
|
||||
}
|
||||
resource := fmt.Sprintf("f5-virtualserver/%s/%s", virtualServer.Namespace, virtualServer.Name)
|
||||
endpoints = append(endpoints, endpointsForHostname(virtualServer.Spec.Host, targets, ttl, nil, "", resource)...)
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
@ -234,7 +213,3 @@ func (vs *f5VirtualServerSource) filterByAnnotations(virtualServers []*f5.Virtua
|
||||
|
||||
return filteredList, nil
|
||||
}
|
||||
|
||||
func (vs *f5VirtualServerSource) setResourceLabel(virtualServer *f5.VirtualServer, ep *endpoint.Endpoint) {
|
||||
ep.Labels[endpoint.ResourceLabelKey] = fmt.Sprintf("f5-virtualserver/%s/%s", virtualServer.Namespace, virtualServer.Name)
|
||||
}
|
||||
|
@ -44,6 +44,41 @@ func TestF5VirtualServerEndpoints(t *testing.T) {
|
||||
virtualServer f5.VirtualServer
|
||||
expected []*endpoint.Endpoint
|
||||
}{
|
||||
{
|
||||
name: "F5 VirtualServer with target annotation",
|
||||
annotationFilter: "",
|
||||
virtualServer: f5.VirtualServer{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: f5VirtualServerGVR.GroupVersion().String(),
|
||||
Kind: "VirtualServer",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-vs",
|
||||
Namespace: defaultF5VirtualServerNamespace,
|
||||
Annotations: map[string]string{
|
||||
targetAnnotationKey: "192.168.1.150",
|
||||
},
|
||||
},
|
||||
Spec: f5.VirtualServerSpec{
|
||||
Host: "www.example.com",
|
||||
VirtualServerAddress: "192.168.1.100",
|
||||
},
|
||||
Status: f5.VirtualServerStatus{
|
||||
VSAddress: "192.168.1.200",
|
||||
},
|
||||
},
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "www.example.com",
|
||||
Targets: []string{"192.168.1.150"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
RecordTTL: 0,
|
||||
Labels: endpoint.Labels{
|
||||
"resource": "f5-virtualserver/virtualserver/test-vs",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "F5 VirtualServer with host and virtualServerAddress set",
|
||||
annotationFilter: "",
|
||||
@ -60,6 +95,9 @@ func TestF5VirtualServerEndpoints(t *testing.T) {
|
||||
Host: "www.example.com",
|
||||
VirtualServerAddress: "192.168.1.100",
|
||||
},
|
||||
Status: f5.VirtualServerStatus{
|
||||
VSAddress: "192.168.1.200",
|
||||
},
|
||||
},
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
|
@ -132,11 +132,16 @@ func (gs *glooSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, erro
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("Gloo: Find %s proxy", proxy.Metadata.Name)
|
||||
proxyTargets, err := gs.proxyTargets(ctx, proxy.Metadata.Name, ns)
|
||||
|
||||
proxyTargets := getTargetsFromTargetAnnotation(proxy.Metadata.Annotations)
|
||||
if len(proxyTargets) == 0 {
|
||||
proxyTargets, err = gs.proxyTargets(ctx, proxy.Metadata.Name, ns)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
log.Debugf("Gloo[%s]: Find %d target(s) (%+v)", proxy.Metadata.Name, len(proxyTargets), proxyTargets)
|
||||
|
||||
proxyEndpoints, err := gs.generateEndpointsFromProxy(ctx, &proxy, proxyTargets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -302,6 +302,96 @@ var proxyMetadataStaticSource = metav1.PartialObjectMetadata{
|
||||
},
|
||||
}
|
||||
|
||||
// Proxy with target annotation test
|
||||
var targetAnnotatedProxy = proxy{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: proxyGVR.GroupVersion().String(),
|
||||
Kind: "Proxy",
|
||||
},
|
||||
Metadata: metav1.ObjectMeta{
|
||||
Name: "target-ann",
|
||||
Namespace: defaultGlooNamespace,
|
||||
Annotations: map[string]string{
|
||||
"external-dns.alpha.kubernetes.io/target": "203.2.45.7",
|
||||
},
|
||||
},
|
||||
Spec: proxySpec{
|
||||
Listeners: []proxySpecListener{
|
||||
{
|
||||
HTTPListener: proxySpecHTTPListener{
|
||||
VirtualHosts: []proxyVirtualHost{
|
||||
{
|
||||
Domains: []string{"i.test"},
|
||||
Metadata: proxyVirtualHostMetadata{
|
||||
Source: []proxyVirtualHostMetadataSource{
|
||||
{
|
||||
Kind: "*v1.Unknown",
|
||||
Name: "my-unknown-svc",
|
||||
Namespace: "unknown",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Domains: []string{"j.test"},
|
||||
Metadata: proxyVirtualHostMetadata{
|
||||
Source: []proxyVirtualHostMetadataSource{
|
||||
{
|
||||
Kind: "*v1.VirtualService",
|
||||
Name: "my-annotated-svc",
|
||||
Namespace: "internal",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var targetAnnotatedProxySvc = corev1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: targetAnnotatedProxy.Metadata.Name,
|
||||
Namespace: targetAnnotatedProxy.Metadata.Namespace,
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Type: corev1.ServiceTypeLoadBalancer,
|
||||
},
|
||||
Status: corev1.ServiceStatus{
|
||||
LoadBalancer: corev1.LoadBalancerStatus{
|
||||
Ingress: []corev1.LoadBalancerIngress{
|
||||
{
|
||||
IP: "203.1.115.1",
|
||||
},
|
||||
{
|
||||
IP: "203.1.115.2",
|
||||
},
|
||||
{
|
||||
IP: "203.1.115.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var targetAnnotatedProxySource = metav1.PartialObjectMetadata{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: virtualServiceGVR.GroupVersion().String(),
|
||||
Kind: "VirtualService",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: targetAnnotatedProxy.Spec.Listeners[0].HTTPListener.VirtualHosts[1].Metadata.Source[0].Name,
|
||||
Namespace: targetAnnotatedProxy.Spec.Listeners[0].HTTPListener.VirtualHosts[1].Metadata.Source[0].Namespace,
|
||||
Annotations: map[string]string{
|
||||
"external-dns.alpha.kubernetes.io/ttl": "460",
|
||||
"external-dns.alpha.kubernetes.io/aws-geolocation-country-code": "IT",
|
||||
"external-dns.alpha.kubernetes.io/set-identifier": "identifier-annotated",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestGlooSource(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@ -318,10 +408,12 @@ func TestGlooSource(t *testing.T) {
|
||||
internalProxyUnstructured := unstructured.Unstructured{}
|
||||
externalProxyUnstructured := unstructured.Unstructured{}
|
||||
proxyMetadataStaticUnstructured := unstructured.Unstructured{}
|
||||
targetAnnotatedProxyUnstructured := unstructured.Unstructured{}
|
||||
|
||||
internalProxySourceUnstructured := unstructured.Unstructured{}
|
||||
externalProxySourceUnstructured := unstructured.Unstructured{}
|
||||
proxyMetadataStaticSourceUnstructured := unstructured.Unstructured{}
|
||||
targetAnnotatedProxySourceUnstructured := unstructured.Unstructured{}
|
||||
|
||||
internalProxyAsJSON, err := json.Marshal(internalProxy)
|
||||
assert.NoError(t, err)
|
||||
@ -332,6 +424,9 @@ func TestGlooSource(t *testing.T) {
|
||||
proxyMetadataStaticAsJSON, err := json.Marshal(proxyMetadataStatic)
|
||||
assert.NoError(t, err)
|
||||
|
||||
targetAnnotatedProxyAsJSON, err := json.Marshal(targetAnnotatedProxy)
|
||||
assert.NoError(t, err)
|
||||
|
||||
internalProxySvcAsJSON, err := json.Marshal(internalProxySource)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@ -341,13 +436,18 @@ func TestGlooSource(t *testing.T) {
|
||||
proxyMetadataStaticSvcAsJSON, err := json.Marshal(proxyMetadataStaticSource)
|
||||
assert.NoError(t, err)
|
||||
|
||||
targetAnnotatedProxySvcAsJSON, err := json.Marshal(targetAnnotatedProxySource)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, internalProxyUnstructured.UnmarshalJSON(internalProxyAsJSON))
|
||||
assert.NoError(t, externalProxyUnstructured.UnmarshalJSON(externalProxyAsJSON))
|
||||
assert.NoError(t, proxyMetadataStaticUnstructured.UnmarshalJSON(proxyMetadataStaticAsJSON))
|
||||
assert.NoError(t, targetAnnotatedProxyUnstructured.UnmarshalJSON(targetAnnotatedProxyAsJSON))
|
||||
|
||||
assert.NoError(t, internalProxySourceUnstructured.UnmarshalJSON(internalProxySvcAsJSON))
|
||||
assert.NoError(t, externalProxySourceUnstructured.UnmarshalJSON(externalProxySvcAsJSON))
|
||||
assert.NoError(t, proxyMetadataStaticSourceUnstructured.UnmarshalJSON(proxyMetadataStaticSvcAsJSON))
|
||||
assert.NoError(t, targetAnnotatedProxySourceUnstructured.UnmarshalJSON(targetAnnotatedProxySvcAsJSON))
|
||||
|
||||
// Create proxy resources
|
||||
_, err = fakeDynamicClient.Resource(proxyGVR).Namespace(defaultGlooNamespace).Create(context.Background(), &internalProxyUnstructured, metav1.CreateOptions{})
|
||||
@ -356,6 +456,8 @@ func TestGlooSource(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
_, err = fakeDynamicClient.Resource(proxyGVR).Namespace(defaultGlooNamespace).Create(context.Background(), &proxyMetadataStaticUnstructured, metav1.CreateOptions{})
|
||||
assert.NoError(t, err)
|
||||
_, err = fakeDynamicClient.Resource(proxyGVR).Namespace(defaultGlooNamespace).Create(context.Background(), &targetAnnotatedProxyUnstructured, metav1.CreateOptions{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create proxy source
|
||||
_, err = fakeDynamicClient.Resource(virtualServiceGVR).Namespace(internalProxySource.Namespace).Create(context.Background(), &internalProxySourceUnstructured, metav1.CreateOptions{})
|
||||
@ -364,6 +466,8 @@ func TestGlooSource(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
_, err = fakeDynamicClient.Resource(virtualServiceGVR).Namespace(proxyMetadataStaticSource.Namespace).Create(context.Background(), &proxyMetadataStaticSourceUnstructured, metav1.CreateOptions{})
|
||||
assert.NoError(t, err)
|
||||
_, err = fakeDynamicClient.Resource(virtualServiceGVR).Namespace(targetAnnotatedProxySource.Namespace).Create(context.Background(), &targetAnnotatedProxySourceUnstructured, metav1.CreateOptions{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create proxy service resources
|
||||
_, err = fakeKubernetesClient.CoreV1().Services(internalProxySvc.GetNamespace()).Create(context.Background(), &internalProxySvc, metav1.CreateOptions{})
|
||||
@ -372,10 +476,12 @@ func TestGlooSource(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
_, err = fakeKubernetesClient.CoreV1().Services(proxyMetadataStaticSvc.GetNamespace()).Create(context.Background(), &proxyMetadataStaticSvc, metav1.CreateOptions{})
|
||||
assert.NoError(t, err)
|
||||
_, err = fakeKubernetesClient.CoreV1().Services(targetAnnotatedProxySvc.GetNamespace()).Create(context.Background(), &targetAnnotatedProxySvc, metav1.CreateOptions{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
endpoints, err := source.Endpoints(context.Background())
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, endpoints, 8)
|
||||
assert.Len(t, endpoints, 10)
|
||||
assert.ElementsMatch(t, endpoints, []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "a.test",
|
||||
@ -459,5 +565,26 @@ func TestGlooSource(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DNSName: "i.test",
|
||||
Targets: []string{"203.2.45.7"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Labels: endpoint.Labels{},
|
||||
ProviderSpecific: endpoint.ProviderSpecific{},
|
||||
},
|
||||
{
|
||||
DNSName: "j.test",
|
||||
Targets: []string{"203.2.45.7"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
SetIdentifier: "identifier-annotated",
|
||||
RecordTTL: 460,
|
||||
Labels: endpoint.Labels{},
|
||||
ProviderSpecific: endpoint.ProviderSpecific{
|
||||
endpoint.ProviderSpecificProperty{
|
||||
Name: "aws/geolocation-country-code",
|
||||
Value: "IT",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -124,7 +124,8 @@ func (sc *kongTCPIngressSource) Endpoints(ctx context.Context) ([]*endpoint.Endp
|
||||
|
||||
var endpoints []*endpoint.Endpoint
|
||||
for _, tcpIngress := range tcpIngresses {
|
||||
var targets endpoint.Targets
|
||||
targets := getTargetsFromTargetAnnotation(tcpIngress.Annotations)
|
||||
if len(targets) == 0 {
|
||||
for _, lb := range tcpIngress.Status.LoadBalancer.Ingress {
|
||||
if lb.IP != "" {
|
||||
targets = append(targets, lb.IP)
|
||||
@ -133,6 +134,7 @@ func (sc *kongTCPIngressSource) Endpoints(ctx context.Context) ([]*endpoint.Endp
|
||||
targets = append(targets, lb.Hostname)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fullname := fmt.Sprintf("%s/%s", tcpIngress.Namespace, tcpIngress.Name)
|
||||
|
||||
|
@ -220,6 +220,65 @@ func TestKongTCPIngressEndpoints(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "TCPIngress with target annotation",
|
||||
tcpProxy: TCPIngress{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: kongGroupdVersionResource.GroupVersion().String(),
|
||||
Kind: "TCPIngress",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "tcp-ingress-sni",
|
||||
Namespace: defaultKongNamespace,
|
||||
Annotations: map[string]string{
|
||||
"kubernetes.io/ingress.class": "kong",
|
||||
"external-dns.alpha.kubernetes.io/target": "203.2.45.7",
|
||||
},
|
||||
},
|
||||
Spec: tcpIngressSpec{
|
||||
Rules: []tcpIngressRule{
|
||||
{
|
||||
Port: 30002,
|
||||
Host: "b.example.com",
|
||||
},
|
||||
{
|
||||
Port: 30003,
|
||||
Host: "c.example.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: tcpIngressStatus{
|
||||
LoadBalancer: corev1.LoadBalancerStatus{
|
||||
Ingress: []corev1.LoadBalancerIngress{
|
||||
{
|
||||
Hostname: "a123456769a314e71861a4303f06a3bd-1291189659.us-east-1.elb.amazonaws.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "b.example.com",
|
||||
Targets: []string{"203.2.45.7"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
RecordTTL: 0,
|
||||
Labels: endpoint.Labels{
|
||||
"resource": "tcpingress/kong/tcp-ingress-sni",
|
||||
},
|
||||
ProviderSpecific: endpoint.ProviderSpecific{},
|
||||
},
|
||||
{
|
||||
DNSName: "c.example.com",
|
||||
Targets: []string{"203.2.45.7"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Labels: endpoint.Labels{
|
||||
"resource": "tcpingress/kong/tcp-ingress-sni",
|
||||
},
|
||||
ProviderSpecific: endpoint.ProviderSpecific{},
|
||||
},
|
||||
},
|
||||
},
|
||||
} {
|
||||
ti := ti
|
||||
t.Run(ti.title, func(t *testing.T) {
|
||||
|
@ -130,10 +130,13 @@ func (ns *nodeSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, erro
|
||||
log.Debugf("not applying template for %s", node.Name)
|
||||
}
|
||||
|
||||
addrs, err := ns.nodeAddresses(node)
|
||||
addrs := getTargetsFromTargetAnnotation(node.Annotations)
|
||||
if len(addrs) == 0 {
|
||||
addrs, err = ns.nodeAddresses(node)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get node address from %s: %w", node.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
ep.Labels = endpoint.NewLabels()
|
||||
for _, addr := range addrs {
|
||||
|
@ -205,6 +205,17 @@ func testNodeSourceEndpoints(t *testing.T) {
|
||||
nodeAddresses: []v1.NodeAddress{},
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
title: "node with target annotation",
|
||||
nodeName: "node1.example.org",
|
||||
nodeAddresses: []v1.NodeAddress{{Type: v1.NodeExternalIP, Address: "1.2.3.4"}},
|
||||
annotations: map[string]string{
|
||||
"external-dns.alpha.kubernetes.io/target": "203.2.45.7",
|
||||
},
|
||||
expected: []*endpoint.Endpoint{
|
||||
{RecordType: "A", DNSName: "node1.example.org", Targets: endpoint.Targets{"203.2.45.7"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "annotated node without annotation filter returns endpoint",
|
||||
nodeName: "node1",
|
||||
|
@ -89,16 +89,25 @@ func (ps *podSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error
|
||||
continue
|
||||
}
|
||||
|
||||
targets := getTargetsFromTargetAnnotation(pod.Annotations)
|
||||
|
||||
if domainAnnotation, ok := pod.Annotations[internalHostnameAnnotationKey]; ok {
|
||||
domainList := splitHostnameAnnotation(domainAnnotation)
|
||||
for _, domain := range domainList {
|
||||
if len(targets) == 0 {
|
||||
addToEndpointMap(endpointMap, domain, suitableType(pod.Status.PodIP), pod.Status.PodIP)
|
||||
} else {
|
||||
for _, target := range targets {
|
||||
addToEndpointMap(endpointMap, domain, suitableType(target), target)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if domainAnnotation, ok := pod.Annotations[hostnameAnnotationKey]; ok {
|
||||
domainList := splitHostnameAnnotation(domainAnnotation)
|
||||
for _, domain := range domainList {
|
||||
if len(targets) == 0 {
|
||||
node, _ := ps.nodeInformer.Lister().Get(pod.Spec.NodeName)
|
||||
for _, address := range node.Status.Addresses {
|
||||
recordType := suitableType(address.Address)
|
||||
@ -107,6 +116,11 @@ func (ps *podSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error
|
||||
addToEndpointMap(endpointMap, domain, recordType, address.Address)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, target := range targets {
|
||||
addToEndpointMap(endpointMap, domain, suitableType(target), target)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,6 +316,78 @@ func TestPodSource(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"create records based on pod's target annotation",
|
||||
"",
|
||||
"",
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"208.1.2.1", "208.1.2.2"}, RecordType: endpoint.RecordTypeA},
|
||||
{DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"208.1.2.1", "208.1.2.2"}, RecordType: endpoint.RecordTypeA},
|
||||
},
|
||||
false,
|
||||
[]*corev1.Node{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-node1",
|
||||
},
|
||||
Status: corev1.NodeStatus{
|
||||
Addresses: []corev1.NodeAddress{
|
||||
{Type: corev1.NodeExternalIP, Address: "54.10.11.1"},
|
||||
{Type: corev1.NodeInternalIP, Address: "10.0.1.1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-node2",
|
||||
},
|
||||
Status: corev1.NodeStatus{
|
||||
Addresses: []corev1.NodeAddress{
|
||||
{Type: corev1.NodeExternalIP, Address: "54.10.11.2"},
|
||||
{Type: corev1.NodeInternalIP, Address: "10.0.1.2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[]*corev1.Pod{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-pod1",
|
||||
Namespace: "kube-system",
|
||||
Annotations: map[string]string{
|
||||
internalHostnameAnnotationKey: "internal.a.foo.example.org",
|
||||
hostnameAnnotationKey: "a.foo.example.org",
|
||||
targetAnnotationKey: "208.1.2.1",
|
||||
},
|
||||
},
|
||||
Spec: corev1.PodSpec{
|
||||
HostNetwork: true,
|
||||
NodeName: "my-node1",
|
||||
},
|
||||
Status: corev1.PodStatus{
|
||||
PodIP: "10.0.1.1",
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-pod2",
|
||||
Namespace: "kube-system",
|
||||
Annotations: map[string]string{
|
||||
internalHostnameAnnotationKey: "internal.a.foo.example.org",
|
||||
hostnameAnnotationKey: "a.foo.example.org",
|
||||
targetAnnotationKey: "208.1.2.2",
|
||||
},
|
||||
},
|
||||
Spec: corev1.PodSpec{
|
||||
HostNetwork: true,
|
||||
NodeName: "my-node2",
|
||||
},
|
||||
Status: corev1.PodStatus{
|
||||
PodIP: "10.0.1.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"create multiple records",
|
||||
"",
|
||||
|
Loading…
Reference in New Issue
Block a user