mirror of
				https://github.com/kubernetes-sigs/external-dns.git
				synced 2025-10-31 02:31:00 +01:00 
			
		
		
		
	* 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>
		
			
				
	
	
		
			1145 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			1145 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
| Copyright 2021 The Kubernetes Authors.
 | |
| 
 | |
| Licensed under the Apache License, Version 2.0 (the "License");
 | |
| you may not use this file except in compliance with the License.
 | |
| You may obtain a copy of the License at
 | |
| 
 | |
|     http://www.apache.org/licenses/LICENSE-2.0
 | |
| 
 | |
| Unless required by applicable law or agreed to in writing, software
 | |
| distributed under the License is distributed on an "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| See the License for the specific language governing permissions and
 | |
| limitations under the License.
 | |
| */
 | |
| 
 | |
| package source
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"math/rand"
 | |
| 	"testing"
 | |
| 
 | |
| 	log "github.com/sirupsen/logrus"
 | |
| 	"github.com/stretchr/testify/assert"
 | |
| 	"github.com/stretchr/testify/mock"
 | |
| 	"github.com/stretchr/testify/require"
 | |
| 	corev1 "k8s.io/api/core/v1"
 | |
| 	v1 "k8s.io/api/core/v1"
 | |
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | |
| 	corev1lister "k8s.io/client-go/listers/core/v1"
 | |
| 	"k8s.io/client-go/tools/cache"
 | |
| 
 | |
| 	"sigs.k8s.io/external-dns/endpoint"
 | |
| 	"sigs.k8s.io/external-dns/internal/testutils"
 | |
| 
 | |
| 	"k8s.io/client-go/kubernetes/fake"
 | |
| )
 | |
| 
 | |
| // testPodSource tests that various services generate the correct endpoints.
 | |
| func TestPodSource(t *testing.T) {
 | |
| 	t.Parallel()
 | |
| 
 | |
| 	for _, tc := range []struct {
 | |
| 		title                    string
 | |
| 		targetNamespace          string
 | |
| 		compatibility            string
 | |
| 		ignoreNonHostNetworkPods bool
 | |
| 		PodSourceDomain          string
 | |
| 		expected                 []*endpoint.Endpoint
 | |
| 		expectError              bool
 | |
| 		nodes                    []*corev1.Node
 | |
| 		pods                     []*corev1.Pod
 | |
| 	}{
 | |
| 		{
 | |
| 			"create IPv4 records based on pod's external and internal IPs",
 | |
| 			"",
 | |
| 			"",
 | |
| 			true,
 | |
| 			"",
 | |
| 			[]*endpoint.Endpoint{
 | |
| 				{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}, RecordType: endpoint.RecordTypeA},
 | |
| 				{DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}, RecordType: endpoint.RecordTypeA},
 | |
| 			},
 | |
| 			false,
 | |
| 			nodesFixturesIPv4(),
 | |
| 			[]*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",
 | |
| 						},
 | |
| 					},
 | |
| 					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",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "my-node2",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "10.0.1.2",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			"create IPv4 records based on pod's external and internal IPs using DNS Controller annotations",
 | |
| 			"",
 | |
| 			"kops-dns-controller",
 | |
| 			true,
 | |
| 			"",
 | |
| 			[]*endpoint.Endpoint{
 | |
| 				{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}, RecordType: endpoint.RecordTypeA},
 | |
| 				{DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}, RecordType: endpoint.RecordTypeA},
 | |
| 			},
 | |
| 			false,
 | |
| 			nodesFixturesIPv4(),
 | |
| 			[]*corev1.Pod{
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:      "my-pod1",
 | |
| 						Namespace: "kube-system",
 | |
| 						Annotations: map[string]string{
 | |
| 							kopsDNSControllerInternalHostnameAnnotationKey: "internal.a.foo.example.org",
 | |
| 							kopsDNSControllerHostnameAnnotationKey:         "a.foo.example.org",
 | |
| 						},
 | |
| 					},
 | |
| 					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{
 | |
| 							kopsDNSControllerInternalHostnameAnnotationKey: "internal.a.foo.example.org",
 | |
| 							kopsDNSControllerHostnameAnnotationKey:         "a.foo.example.org",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "my-node2",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "10.0.1.2",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			"create IPv6 records based on pod's external and internal IPs",
 | |
| 			"",
 | |
| 			"",
 | |
| 			true,
 | |
| 			"",
 | |
| 			[]*endpoint.Endpoint{
 | |
| 				{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
 | |
| 				{DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
 | |
| 			},
 | |
| 			false,
 | |
| 			nodesFixturesIPv6(),
 | |
| 			[]*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",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "my-node1",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "2001:DB8::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",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "my-node2",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "2001:DB8::2",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			"create IPv6 records based on pod's external and internal IPs using DNS Controller annotations",
 | |
| 			"",
 | |
| 			"kops-dns-controller",
 | |
| 			true,
 | |
| 			"",
 | |
| 			[]*endpoint.Endpoint{
 | |
| 				{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
 | |
| 				{DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
 | |
| 			},
 | |
| 			false,
 | |
| 			nodesFixturesIPv6(),
 | |
| 			[]*corev1.Pod{
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:      "my-pod1",
 | |
| 						Namespace: "kube-system",
 | |
| 						Annotations: map[string]string{
 | |
| 							kopsDNSControllerInternalHostnameAnnotationKey: "internal.a.foo.example.org",
 | |
| 							kopsDNSControllerHostnameAnnotationKey:         "a.foo.example.org",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "my-node1",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "2001:DB8::1",
 | |
| 					},
 | |
| 				},
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:      "my-pod2",
 | |
| 						Namespace: "kube-system",
 | |
| 						Annotations: map[string]string{
 | |
| 							kopsDNSControllerInternalHostnameAnnotationKey: "internal.a.foo.example.org",
 | |
| 							kopsDNSControllerHostnameAnnotationKey:         "a.foo.example.org",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "my-node2",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "2001:DB8::2",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			"create records based on pod's target annotation",
 | |
| 			"",
 | |
| 			"",
 | |
| 			true,
 | |
| 			"",
 | |
| 			[]*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,
 | |
| 			nodesFixturesIPv4(),
 | |
| 			[]*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",
 | |
| 			"",
 | |
| 			"",
 | |
| 			true,
 | |
| 			"",
 | |
| 			[]*endpoint.Endpoint{
 | |
| 				{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1"}, RecordType: endpoint.RecordTypeA, RecordTTL: endpoint.TTL(5400)},
 | |
| 				{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"2001:DB8::1"}, RecordType: endpoint.RecordTypeAAAA, RecordTTL: endpoint.TTL(5400)},
 | |
| 				{DNSName: "b.foo.example.org", Targets: endpoint.Targets{"54.10.11.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: "2001:DB8::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{
 | |
| 							hostnameAnnotationKey: "a.foo.example.org",
 | |
| 							ttlAnnotationKey:      "1h30m",
 | |
| 						},
 | |
| 					},
 | |
| 					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{
 | |
| 							hostnameAnnotationKey: "b.foo.example.org",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "my-node2",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "10.0.1.2",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			"pods with hostNetwore=false should be ignored",
 | |
| 			"",
 | |
| 			"",
 | |
| 			true,
 | |
| 			"",
 | |
| 			[]*endpoint.Endpoint{
 | |
| 				{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1"}, RecordType: endpoint.RecordTypeA, RecordTTL: endpoint.TTL(1)},
 | |
| 				{DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"10.0.1.1"}, RecordType: endpoint.RecordTypeA, RecordTTL: endpoint.TTL(1)},
 | |
| 			},
 | |
| 			false,
 | |
| 			nodesFixturesIPv4(),
 | |
| 			[]*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",
 | |
| 							ttlAnnotationKey:              "1s",
 | |
| 						},
 | |
| 					},
 | |
| 					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",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: false,
 | |
| 						NodeName:    "my-node2",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "100.0.1.2",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			"only watch a given namespace",
 | |
| 			"kube-system",
 | |
| 			"",
 | |
| 			true,
 | |
| 			"",
 | |
| 			[]*endpoint.Endpoint{
 | |
| 				{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1"}, RecordType: endpoint.RecordTypeA},
 | |
| 				{DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"10.0.1.1"}, RecordType: endpoint.RecordTypeA},
 | |
| 			},
 | |
| 			false,
 | |
| 			nodesFixturesIPv4(),
 | |
| 			[]*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",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "my-node1",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "10.0.1.1",
 | |
| 					},
 | |
| 				},
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:      "my-pod2",
 | |
| 						Namespace: "default",
 | |
| 						Annotations: map[string]string{
 | |
| 							internalHostnameAnnotationKey: "internal.a.foo.example.org",
 | |
| 							hostnameAnnotationKey:         "a.foo.example.org",
 | |
| 							ttlAnnotationKey:              "1s",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "my-node2",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "100.0.1.2",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			"split record for internal hostname annotation",
 | |
| 			"",
 | |
| 			"",
 | |
| 			true,
 | |
| 			"",
 | |
| 			[]*endpoint.Endpoint{
 | |
| 				{DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"10.0.1.1"}, RecordType: endpoint.RecordTypeA},
 | |
| 				{DNSName: "internal.b.foo.example.org", Targets: endpoint.Targets{"10.0.1.1"}, RecordType: endpoint.RecordTypeA},
 | |
| 			},
 | |
| 			false,
 | |
| 			[]*corev1.Node{
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name: "my-node1",
 | |
| 					},
 | |
| 					Status: corev1.NodeStatus{
 | |
| 						Addresses: []corev1.NodeAddress{
 | |
| 							{Type: corev1.NodeInternalIP, Address: "10.0.1.1"},
 | |
| 						},
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 			[]*corev1.Pod{
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:      "my-pod1",
 | |
| 						Namespace: "kube-system",
 | |
| 						Annotations: map[string]string{
 | |
| 							internalHostnameAnnotationKey: "internal.a.foo.example.org,internal.b.foo.example.org",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "my-node1",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "10.0.1.1",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			"create IPv4 records for non-host network pods",
 | |
| 			"",
 | |
| 			"",
 | |
| 			false,
 | |
| 			"example.org",
 | |
| 			[]*endpoint.Endpoint{
 | |
| 				{DNSName: "my-pod1.example.org", Targets: endpoint.Targets{"192.168.1.1"}, RecordType: endpoint.RecordTypeA, RecordTTL: endpoint.TTL(60)},
 | |
| 				{DNSName: "my-pod2.example.org", Targets: endpoint.Targets{"192.168.1.2"}, RecordType: endpoint.RecordTypeA},
 | |
| 			},
 | |
| 			false,
 | |
| 			nodesFixturesIPv4(),
 | |
| 			[]*corev1.Pod{
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:      "my-pod1",
 | |
| 						Namespace: "kube-system",
 | |
| 						Annotations: map[string]string{
 | |
| 							ttlAnnotationKey: "1m",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: false,
 | |
| 						NodeName:    "my-node1",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "192.168.1.1",
 | |
| 					},
 | |
| 				},
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:        "my-pod2",
 | |
| 						Namespace:   "kube-system",
 | |
| 						Annotations: map[string]string{},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: false,
 | |
| 						NodeName:    "my-node2",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "192.168.1.2",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			"create records based on pod's target annotation with pod source domain",
 | |
| 			"",
 | |
| 			"",
 | |
| 			true,
 | |
| 			"example.org",
 | |
| 			[]*endpoint.Endpoint{
 | |
| 				{DNSName: "my-pod1.example.org", Targets: endpoint.Targets{"208.1.2.1"}, RecordType: endpoint.RecordTypeA},
 | |
| 				{DNSName: "my-pod2.example.org", Targets: endpoint.Targets{"208.1.2.2"}, RecordType: endpoint.RecordTypeA},
 | |
| 				{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,
 | |
| 			nodesFixturesIPv4(),
 | |
| 			[]*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",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			"host network pod on a missing node",
 | |
| 			"",
 | |
| 			"",
 | |
| 			true,
 | |
| 			"",
 | |
| 			[]*endpoint.Endpoint{},
 | |
| 			false,
 | |
| 			nodesFixturesIPv4(),
 | |
| 			[]*corev1.Pod{
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:      "my-pod1",
 | |
| 						Namespace: "kube-system",
 | |
| 						Annotations: map[string]string{
 | |
| 							hostnameAnnotationKey: "a.foo.example.org",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "missing-node",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "10.0.1.1",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	} {
 | |
| 		t.Run(tc.title, func(t *testing.T) {
 | |
| 			kubernetes := fake.NewClientset()
 | |
| 			ctx := t.Context()
 | |
| 
 | |
| 			// Create the nodes
 | |
| 			for _, node := range tc.nodes {
 | |
| 				if _, err := kubernetes.CoreV1().Nodes().Create(ctx, node, metav1.CreateOptions{}); err != nil {
 | |
| 					t.Fatal(err)
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			// Create the pods
 | |
| 			for _, pod := range tc.pods {
 | |
| 				pods := kubernetes.CoreV1().Pods(pod.Namespace)
 | |
| 
 | |
| 				if _, err := pods.Create(ctx, pod, metav1.CreateOptions{}); err != nil {
 | |
| 					t.Fatal(err)
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			client, err := NewPodSource(ctx, kubernetes, tc.targetNamespace, tc.compatibility, tc.ignoreNonHostNetworkPods, tc.PodSourceDomain, "", false, "", nil)
 | |
| 			require.NoError(t, err)
 | |
| 
 | |
| 			endpoints, err := client.Endpoints(ctx)
 | |
| 			if tc.expectError {
 | |
| 				require.Error(t, err)
 | |
| 			} else {
 | |
| 				require.NoError(t, err)
 | |
| 			}
 | |
| 
 | |
| 			// Validate returned endpoints against desired endpoints.
 | |
| 			validateEndpoints(t, endpoints, tc.expected)
 | |
| 
 | |
| 			for _, ep := range endpoints {
 | |
| 				// TODO: source should always set the resource label key. currently not supported by the pod source.
 | |
| 				require.Empty(t, ep.Labels, "Labels should not be empty for endpoint %s", ep.DNSName)
 | |
| 				require.NotContains(t, ep.Labels, endpoint.ResourceLabelKey)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestPodSourceLogs(t *testing.T) {
 | |
| 	t.Parallel()
 | |
| 	// Generate unique pod names to avoid log conflicts across parallel tests.
 | |
| 	// Since logs are globally shared, using the same pod names could cause
 | |
| 	// false positives in unexpectedDebugLogs assertions.
 | |
| 	suffix := fmt.Sprintf("%d", rand.Intn(100000))
 | |
| 	for _, tc := range []struct {
 | |
| 		title                    string
 | |
| 		ignoreNonHostNetworkPods bool
 | |
| 		pods                     []*corev1.Pod
 | |
| 		nodes                    []*corev1.Node
 | |
| 		expectedDebugLogs        []string
 | |
| 		unexpectedDebugLogs      []string
 | |
| 	}{
 | |
| 		{
 | |
| 			"pods with hostNetwore=false should be skipped logging",
 | |
| 			true,
 | |
| 			[]*corev1.Pod{
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:      fmt.Sprintf("my-pod1-%s", suffix),
 | |
| 						Namespace: "kube-system",
 | |
| 						Annotations: map[string]string{
 | |
| 							internalHostnameAnnotationKey: "internal.a.foo.example.org",
 | |
| 							hostnameAnnotationKey:         "a.foo.example.org",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: false,
 | |
| 						NodeName:    "my-node1",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "100.0.1.1",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 			nodesFixturesIPv4(),
 | |
| 			[]string{fmt.Sprintf("skipping pod my-pod1-%s. hostNetwork=false", suffix)},
 | |
| 			nil,
 | |
| 		},
 | |
| 		{
 | |
| 			"host network pod on a missing node",
 | |
| 			true,
 | |
| 			[]*corev1.Pod{
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:      fmt.Sprintf("missing-node-pod-%s", suffix),
 | |
| 						Namespace: "kube-system",
 | |
| 						Annotations: map[string]string{
 | |
| 							hostnameAnnotationKey: "a.foo.example.org",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "missing-node",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "10.0.1.1",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 			nodesFixturesIPv4(),
 | |
| 			[]string{
 | |
| 				fmt.Sprintf(`Get node[missing-node] of pod[missing-node-pod-%s] error: node "missing-node" not found; ignoring`, suffix),
 | |
| 			},
 | |
| 			nil,
 | |
| 		},
 | |
| 		{
 | |
| 			"mixed valid and hostNetwork=false pods with missing node",
 | |
| 			true,
 | |
| 			[]*corev1.Pod{
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:      fmt.Sprintf("valid-pod-%s", suffix),
 | |
| 						Namespace: "kube-system",
 | |
| 						Annotations: map[string]string{
 | |
| 							hostnameAnnotationKey: "valid.foo.example.org",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "my-node1",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "10.0.1.1",
 | |
| 					},
 | |
| 				},
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:      fmt.Sprintf("non-hostnet-pod-%s", suffix),
 | |
| 						Namespace: "kube-system",
 | |
| 						Annotations: map[string]string{
 | |
| 							hostnameAnnotationKey: "nonhost.foo.example.org",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: false,
 | |
| 						NodeName:    "my-node2",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "100.0.1.2",
 | |
| 					},
 | |
| 				},
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:      fmt.Sprintf("missing-node-pod-%s", suffix),
 | |
| 						Namespace: "kube-system",
 | |
| 						Annotations: map[string]string{
 | |
| 							hostnameAnnotationKey: "missing.foo.example.org",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "missing-node",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "10.0.1.3",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 			nodesFixturesIPv4(),
 | |
| 			[]string{
 | |
| 				fmt.Sprintf("skipping pod non-hostnet-pod-%s. hostNetwork=false", suffix),
 | |
| 				fmt.Sprintf(`Get node[missing-node] of pod[missing-node-pod-%s] error: node "missing-node" not found; ignoring`, suffix),
 | |
| 			},
 | |
| 			[]string{
 | |
| 				fmt.Sprintf("skipping pod valid-pod-%s. hostNetwork=false", suffix),
 | |
| 				fmt.Sprintf(`Get node[my-node1] of pod[valid-pod-%s] error: node "my-node1" not found; ignoring`, suffix),
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			"valid pods with hostNetwork=true should not generate logs",
 | |
| 			true,
 | |
| 			[]*corev1.Pod{
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:      fmt.Sprintf("valid-pod-%s", suffix),
 | |
| 						Namespace: "kube-system",
 | |
| 						Annotations: map[string]string{
 | |
| 							hostnameAnnotationKey: "valid.foo.example.org",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: true,
 | |
| 						NodeName:    "my-node1",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "10.0.1.1",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 			nodesFixturesIPv4(),
 | |
| 			nil,
 | |
| 			[]string{
 | |
| 				fmt.Sprintf("skipping pod valid-pod-%s. hostNetwork=false", suffix),
 | |
| 				fmt.Sprintf(`Get node[my-node1] of pod[valid-pod-%s] error: node "my-node1" not found; ignoring`, suffix),
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			"when ignoreNonHostNetworkPods=false, no skip logs should be generated",
 | |
| 			false,
 | |
| 			[]*corev1.Pod{
 | |
| 				{
 | |
| 					ObjectMeta: metav1.ObjectMeta{
 | |
| 						Name:      fmt.Sprintf("my-pod1-%s", suffix),
 | |
| 						Namespace: "kube-system",
 | |
| 						Annotations: map[string]string{
 | |
| 							internalHostnameAnnotationKey: "internal.a.foo.example.org",
 | |
| 							hostnameAnnotationKey:         "a.foo.example.org",
 | |
| 						},
 | |
| 					},
 | |
| 					Spec: corev1.PodSpec{
 | |
| 						HostNetwork: false,
 | |
| 						NodeName:    "my-node1",
 | |
| 					},
 | |
| 					Status: corev1.PodStatus{
 | |
| 						PodIP: "10.0.1.1",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 			nodesFixturesIPv4(),
 | |
| 			nil,
 | |
| 			[]string{
 | |
| 				fmt.Sprintf("skipping pod my-pod1-%s. hostNetwork=false", suffix),
 | |
| 			},
 | |
| 		},
 | |
| 	} {
 | |
| 		t.Run(tc.title, func(t *testing.T) {
 | |
| 			kubernetes := fake.NewClientset()
 | |
| 			ctx := context.Background()
 | |
| 			// Create the nodes
 | |
| 			for _, node := range tc.nodes {
 | |
| 				if _, err := kubernetes.CoreV1().Nodes().Create(ctx, node, metav1.CreateOptions{}); err != nil {
 | |
| 					t.Fatal(err)
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			// Create the pods
 | |
| 			for _, pod := range tc.pods {
 | |
| 				pods := kubernetes.CoreV1().Pods(pod.Namespace)
 | |
| 
 | |
| 				if _, err := pods.Create(ctx, pod, metav1.CreateOptions{}); err != nil {
 | |
| 					t.Fatal(err)
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			client, err := NewPodSource(ctx, kubernetes, "", "", tc.ignoreNonHostNetworkPods, "", "", false, "", nil)
 | |
| 			require.NoError(t, err)
 | |
| 
 | |
| 			hook := testutils.LogsUnderTestWithLogLevel(log.DebugLevel, t)
 | |
| 
 | |
| 			_, err = client.Endpoints(ctx)
 | |
| 			require.NoError(t, err)
 | |
| 
 | |
| 			// Check if all expected logs are present in actual logs.
 | |
| 			// We don't do an exact match because logs are globally shared,
 | |
| 			// making precise comparisons difficult
 | |
| 			for _, expectedLog := range tc.expectedDebugLogs {
 | |
| 				testutils.TestHelperLogContains(expectedLog, hook, t)
 | |
| 			}
 | |
| 
 | |
| 			// Check that no unexpected logs are present.
 | |
| 			// This ensures that logs are not generated inappropriately.
 | |
| 			for _, unexpectedLog := range tc.unexpectedDebugLogs {
 | |
| 				testutils.TestHelperLogNotContains(unexpectedLog, hook, t)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestPodSource_AddEventHandler(t *testing.T) {
 | |
| 	fakeInformer := new(fakePodInformer)
 | |
| 	inf := testInformer{}
 | |
| 	fakeInformer.On("Informer").Return(&inf)
 | |
| 
 | |
| 	pSource := &podSource{
 | |
| 		podInformer: fakeInformer,
 | |
| 	}
 | |
| 
 | |
| 	handlerCalled := false
 | |
| 	handler := func() { handlerCalled = true }
 | |
| 
 | |
| 	pSource.AddEventHandler(t.Context(), handler)
 | |
| 
 | |
| 	fakeInformer.AssertNumberOfCalls(t, "Informer", 1)
 | |
| 	assert.False(t, handlerCalled)
 | |
| 	assert.Equal(t, 1, inf.times)
 | |
| }
 | |
| 
 | |
| type fakePodInformer struct {
 | |
| 	mock.Mock
 | |
| 	informer cache.SharedIndexInformer
 | |
| }
 | |
| 
 | |
| func (f *fakePodInformer) Informer() cache.SharedIndexInformer {
 | |
| 	args := f.Called()
 | |
| 	return args.Get(0).(cache.SharedIndexInformer)
 | |
| }
 | |
| 
 | |
| func (f *fakePodInformer) Lister() corev1lister.PodLister {
 | |
| 	return corev1lister.NewPodLister(f.Informer().GetIndexer())
 | |
| }
 | |
| 
 | |
| func nodesFixturesIPv6() []*corev1.Node {
 | |
| 	return []*corev1.Node{
 | |
| 		{
 | |
| 			ObjectMeta: metav1.ObjectMeta{
 | |
| 				Name: "my-node1",
 | |
| 			},
 | |
| 			Status: corev1.NodeStatus{
 | |
| 				Addresses: []corev1.NodeAddress{
 | |
| 					{Type: corev1.NodeInternalIP, Address: "2001:DB8::1"},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			ObjectMeta: metav1.ObjectMeta{
 | |
| 				Name: "my-node2",
 | |
| 			},
 | |
| 			Status: corev1.NodeStatus{
 | |
| 				Addresses: []corev1.NodeAddress{
 | |
| 					{Type: corev1.NodeInternalIP, Address: "2001:DB8::2"},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func nodesFixturesIPv4() []*corev1.Node {
 | |
| 	return []*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"},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestPodTransformerInPodSource(t *testing.T) {
 | |
| 	t.Run("transformer set", func(t *testing.T) {
 | |
| 		ctx := t.Context()
 | |
| 		fakeClient := fake.NewClientset()
 | |
| 
 | |
| 		pod := &v1.Pod{
 | |
| 			Spec: v1.PodSpec{
 | |
| 				Containers: []v1.Container{{
 | |
| 					Name: "test",
 | |
| 				}},
 | |
| 				Hostname:    "test-hostname",
 | |
| 				NodeName:    "test-node",
 | |
| 				HostNetwork: true,
 | |
| 			},
 | |
| 			ObjectMeta: metav1.ObjectMeta{
 | |
| 				Namespace: "test-ns",
 | |
| 				Name:      "test-name",
 | |
| 				Labels: map[string]string{
 | |
| 					"label1": "value1",
 | |
| 					"label2": "value2",
 | |
| 					"label3": "value3",
 | |
| 				},
 | |
| 				Annotations: map[string]string{
 | |
| 					"user-annotation": "value",
 | |
| 					"external-dns.alpha.kubernetes.io/hostname": "test-hostname",
 | |
| 					"external-dns.alpha.kubernetes.io/random":   "value",
 | |
| 					"other/annotation":                          "value",
 | |
| 				},
 | |
| 				UID: "someuid",
 | |
| 			},
 | |
| 			Status: v1.PodStatus{
 | |
| 				PodIP:  "127.0.0.1",
 | |
| 				HostIP: "127.0.0.2",
 | |
| 				Conditions: []v1.PodCondition{{
 | |
| 					Type:   v1.PodReady,
 | |
| 					Status: v1.ConditionTrue,
 | |
| 				}, {
 | |
| 					Type:   v1.ContainersReady,
 | |
| 					Status: v1.ConditionFalse,
 | |
| 				}},
 | |
| 			},
 | |
| 		}
 | |
| 
 | |
| 		_, err := fakeClient.CoreV1().Pods(pod.Namespace).Create(context.Background(), pod, metav1.CreateOptions{})
 | |
| 		require.NoError(t, err)
 | |
| 
 | |
| 		// Should not error when creating the source
 | |
| 		src, err := NewPodSource(ctx, fakeClient, "", "", false, "", "", false, "", nil)
 | |
| 		require.NoError(t, err)
 | |
| 		ps, ok := src.(*podSource)
 | |
| 		require.True(t, ok)
 | |
| 
 | |
| 		retrieved, err := ps.podInformer.Lister().Pods("test-ns").Get("test-name")
 | |
| 		require.NoError(t, err)
 | |
| 
 | |
| 		// Metadata
 | |
| 		assert.Equal(t, "test-name", retrieved.Name)
 | |
| 		assert.Equal(t, "test-ns", retrieved.Namespace)
 | |
| 		assert.Empty(t, retrieved.UID)
 | |
| 		assert.Empty(t, retrieved.Labels)
 | |
| 		// Filtered
 | |
| 		assert.Equal(t, map[string]string{
 | |
| 			"user-annotation": "value",
 | |
| 			"external-dns.alpha.kubernetes.io/hostname": "test-hostname",
 | |
| 			"external-dns.alpha.kubernetes.io/random":   "value",
 | |
| 			"other/annotation":                          "value",
 | |
| 		}, retrieved.Annotations)
 | |
| 
 | |
| 		// Spec
 | |
| 		assert.Empty(t, retrieved.Spec.Containers)
 | |
| 		assert.Empty(t, retrieved.Spec.Hostname)
 | |
| 		assert.Equal(t, "test-node", retrieved.Spec.NodeName)
 | |
| 		assert.True(t, retrieved.Spec.HostNetwork)
 | |
| 
 | |
| 		// Status
 | |
| 		assert.Empty(t, retrieved.Status.ContainerStatuses)
 | |
| 		assert.Empty(t, retrieved.Status.InitContainerStatuses)
 | |
| 		assert.Empty(t, retrieved.Status.HostIP)
 | |
| 		assert.Equal(t, "127.0.0.1", retrieved.Status.PodIP)
 | |
| 		assert.Empty(t, retrieved.Status.Conditions)
 | |
| 	})
 | |
| 
 | |
| 	t.Run("transformer is not used when fqdnTemplate is set", func(t *testing.T) {
 | |
| 		ctx := t.Context()
 | |
| 		fakeClient := fake.NewClientset()
 | |
| 
 | |
| 		pod := &v1.Pod{
 | |
| 			Spec: v1.PodSpec{
 | |
| 				Containers: []v1.Container{{
 | |
| 					Name: "test",
 | |
| 				}},
 | |
| 				Hostname:    "test-hostname",
 | |
| 				NodeName:    "test-node",
 | |
| 				HostNetwork: true,
 | |
| 			},
 | |
| 			ObjectMeta: metav1.ObjectMeta{
 | |
| 				Namespace: "test-ns",
 | |
| 				Name:      "test-name",
 | |
| 				Labels: map[string]string{
 | |
| 					"label1": "value1",
 | |
| 					"label2": "value2",
 | |
| 					"label3": "value3",
 | |
| 				},
 | |
| 				Annotations: map[string]string{
 | |
| 					"user-annotation": "value",
 | |
| 					"external-dns.alpha.kubernetes.io/hostname": "test-hostname",
 | |
| 					"external-dns.alpha.kubernetes.io/random":   "value",
 | |
| 					"other/annotation":                          "value",
 | |
| 				},
 | |
| 				UID: "someuid",
 | |
| 			},
 | |
| 			Status: v1.PodStatus{
 | |
| 				PodIP:  "127.0.0.1",
 | |
| 				HostIP: "127.0.0.2",
 | |
| 				Conditions: []v1.PodCondition{{
 | |
| 					Type:   v1.PodReady,
 | |
| 					Status: v1.ConditionTrue,
 | |
| 				}, {
 | |
| 					Type:   v1.ContainersReady,
 | |
| 					Status: v1.ConditionFalse,
 | |
| 				}},
 | |
| 			},
 | |
| 		}
 | |
| 
 | |
| 		_, err := fakeClient.CoreV1().Pods(pod.Namespace).Create(context.Background(), pod, metav1.CreateOptions{})
 | |
| 		require.NoError(t, err)
 | |
| 
 | |
| 		// Should not error when creating the source
 | |
| 		src, err := NewPodSource(ctx, fakeClient, "", "", false, "", "template", false, "", nil)
 | |
| 		require.NoError(t, err)
 | |
| 		ps, ok := src.(*podSource)
 | |
| 		require.True(t, ok)
 | |
| 
 | |
| 		retrieved, err := ps.podInformer.Lister().Pods("test-ns").Get("test-name")
 | |
| 		require.NoError(t, err)
 | |
| 
 | |
| 		// Metadata
 | |
| 		assert.Equal(t, "test-name", retrieved.Name)
 | |
| 		assert.Equal(t, "test-ns", retrieved.Namespace)
 | |
| 		assert.NotEmpty(t, retrieved.UID)
 | |
| 		assert.NotEmpty(t, retrieved.Labels)
 | |
| 	})
 | |
| }
 |