diff --git a/source/service.go b/source/service.go index 28cb1b9cd..2cc5013df 100644 --- a/source/service.go +++ b/source/service.go @@ -171,6 +171,7 @@ func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname stri return endpoints } + targetsByHeadlessDomain := make(map[string][]string) for _, v := range pods.Items { headlessDomain := hostname if v.Spec.Hostname != "" { @@ -181,11 +182,7 @@ func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname stri log.Debugf("Generating matching endpoint %s with HostIP %s", headlessDomain, v.Status.HostIP) // To reduce traffice on the DNS API only add record for running Pods. Good Idea? if v.Status.Phase == v1.PodRunning { - if ttl.IsConfigured() { - endpoints = append(endpoints, endpoint.NewEndpointWithTTL(headlessDomain, endpoint.RecordTypeA, ttl, v.Status.HostIP)) - } else { - endpoints = append(endpoints, endpoint.NewEndpoint(headlessDomain, endpoint.RecordTypeA, v.Status.HostIP)) - } + targetsByHeadlessDomain[headlessDomain] = append(targetsByHeadlessDomain[headlessDomain], v.Status.HostIP) } else { log.Debugf("Pod %s is not in running phase", v.Spec.Hostname) } @@ -193,11 +190,7 @@ func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname stri log.Debugf("Generating matching endpoint %s with PodIP %s", headlessDomain, v.Status.PodIP) // To reduce traffice on the DNS API only add record for running Pods. Good Idea? if v.Status.Phase == v1.PodRunning { - if ttl.IsConfigured() { - endpoints = append(endpoints, endpoint.NewEndpointWithTTL(headlessDomain, endpoint.RecordTypeA, ttl, v.Status.PodIP)) - } else { - endpoints = append(endpoints, endpoint.NewEndpoint(headlessDomain, endpoint.RecordTypeA, v.Status.PodIP)) - } + targetsByHeadlessDomain[headlessDomain] = append(targetsByHeadlessDomain[headlessDomain], v.Status.PodIP) } else { log.Debugf("Pod %s is not in running phase", v.Spec.Hostname) } @@ -205,6 +198,20 @@ func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname stri } + headlessDomains := []string{} + for headlessDomain := range targetsByHeadlessDomain { + headlessDomains = append(headlessDomains, headlessDomain) + } + sort.Strings(headlessDomains) + for _, headlessDomain := range headlessDomains { + targets := targetsByHeadlessDomain[headlessDomain] + if ttl.IsConfigured() { + endpoints = append(endpoints, endpoint.NewEndpointWithTTL(headlessDomain, endpoint.RecordTypeA, ttl, targets...)) + } else { + endpoints = append(endpoints, endpoint.NewEndpoint(headlessDomain, endpoint.RecordTypeA, targets...)) + } + } + return endpoints } diff --git a/source/service_test.go b/source/service_test.go index edc4666ab..01fef8b93 100644 --- a/source/service_test.go +++ b/source/service_test.go @@ -1321,7 +1321,7 @@ func TestHeadlessServices(t *testing.T) { labels map[string]string annotations map[string]string clusterIP string - podIP string + podIPs []string selector map[string]string lbs []string podnames []string @@ -1343,7 +1343,7 @@ func TestHeadlessServices(t *testing.T) { hostnameAnnotationKey: "service.example.org", }, v1.ClusterIPNone, - "1.1.1.1", + []string{"1.1.1.1", "1.1.1.2"}, map[string]string{ "component": "foo", }, @@ -1353,7 +1353,7 @@ func TestHeadlessServices(t *testing.T) { []v1.PodPhase{v1.PodRunning, v1.PodRunning}, []*endpoint.Endpoint{ {DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, - {DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, + {DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}}, }, false, }, @@ -1371,7 +1371,7 @@ func TestHeadlessServices(t *testing.T) { ttlAnnotationKey: "1", }, v1.ClusterIPNone, - "1.1.1.1", + []string{"1.1.1.1", "1.1.1.2"}, map[string]string{ "component": "foo", }, @@ -1381,7 +1381,7 @@ func TestHeadlessServices(t *testing.T) { []v1.PodPhase{v1.PodRunning, v1.PodRunning}, []*endpoint.Endpoint{ {DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}, RecordTTL: endpoint.TTL(1)}, - {DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}, RecordTTL: endpoint.TTL(1)}, + {DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}, RecordTTL: endpoint.TTL(1)}, }, false, }, @@ -1398,7 +1398,7 @@ func TestHeadlessServices(t *testing.T) { hostnameAnnotationKey: "service.example.org", }, v1.ClusterIPNone, - "1.1.1.1", + []string{"1.1.1.1", "1.1.1.2"}, map[string]string{ "component": "foo", }, @@ -1424,7 +1424,7 @@ func TestHeadlessServices(t *testing.T) { hostnameAnnotationKey: "service.example.org", }, v1.ClusterIPNone, - "1.1.1.1", + []string{"1.1.1.1", "1.1.1.2"}, map[string]string{ "component": "foo", }, @@ -1433,8 +1433,7 @@ func TestHeadlessServices(t *testing.T) { []string{"", ""}, []v1.PodPhase{v1.PodRunning, v1.PodRunning}, []*endpoint.Endpoint{ - {DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, - {DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, + {DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1", "1.1.1.2"}}, }, false, }, @@ -1473,7 +1472,7 @@ func TestHeadlessServices(t *testing.T) { Annotations: tc.annotations, }, Status: v1.PodStatus{ - PodIP: tc.podIP, + PodIP: tc.podIPs[i], Phase: tc.phases[i], }, } @@ -1522,7 +1521,7 @@ func TestHeadlessServicesHostIP(t *testing.T) { labels map[string]string annotations map[string]string clusterIP string - hostIP string + hostIPs []string selector map[string]string lbs []string podnames []string @@ -1544,7 +1543,7 @@ func TestHeadlessServicesHostIP(t *testing.T) { hostnameAnnotationKey: "service.example.org", }, v1.ClusterIPNone, - "1.1.1.1", + []string{"1.1.1.1", "1.1.1.2"}, map[string]string{ "component": "foo", }, @@ -1554,7 +1553,7 @@ func TestHeadlessServicesHostIP(t *testing.T) { []v1.PodPhase{v1.PodRunning, v1.PodRunning}, []*endpoint.Endpoint{ {DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, - {DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, + {DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}}, }, false, }, @@ -1572,7 +1571,7 @@ func TestHeadlessServicesHostIP(t *testing.T) { ttlAnnotationKey: "1", }, v1.ClusterIPNone, - "1.1.1.1", + []string{"1.1.1.1", "1.1.1.2"}, map[string]string{ "component": "foo", }, @@ -1582,7 +1581,7 @@ func TestHeadlessServicesHostIP(t *testing.T) { []v1.PodPhase{v1.PodRunning, v1.PodRunning}, []*endpoint.Endpoint{ {DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}, RecordTTL: endpoint.TTL(1)}, - {DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}, RecordTTL: endpoint.TTL(1)}, + {DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}, RecordTTL: endpoint.TTL(1)}, }, false, }, @@ -1599,7 +1598,7 @@ func TestHeadlessServicesHostIP(t *testing.T) { hostnameAnnotationKey: "service.example.org", }, v1.ClusterIPNone, - "1.1.1.1", + []string{"1.1.1.1", "1.1.1.2"}, map[string]string{ "component": "foo", }, @@ -1625,7 +1624,7 @@ func TestHeadlessServicesHostIP(t *testing.T) { hostnameAnnotationKey: "service.example.org", }, v1.ClusterIPNone, - "1.1.1.1", + []string{"1.1.1.1", "1.1.1.2"}, map[string]string{ "component": "foo", }, @@ -1634,8 +1633,7 @@ func TestHeadlessServicesHostIP(t *testing.T) { []string{"", ""}, []v1.PodPhase{v1.PodRunning, v1.PodRunning}, []*endpoint.Endpoint{ - {DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, - {DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1"}}, + {DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1", "1.1.1.2"}}, }, false, }, @@ -1674,7 +1672,7 @@ func TestHeadlessServicesHostIP(t *testing.T) { Annotations: tc.annotations, }, Status: v1.PodStatus{ - HostIP: tc.hostIP, + HostIP: tc.hostIPs[i], Phase: tc.phases[i], }, }