diff --git a/docs/sources/service.md b/docs/sources/service.md index 9a1871c7b1..c112408d09 100644 --- a/docs/sources/service.md +++ b/docs/sources/service.md @@ -106,5 +106,6 @@ as one of the values. ### ExternalName -Creates a target with the value of the Service's `externalName` field. +1. If the Service has one or more `spec.externalIPs`, uses the values in that field. +2. Otherwise, creates a target with the value of the Service's `externalName` field. diff --git a/source/service.go b/source/service.go index db7247902a..df9b3a8869 100644 --- a/source/service.go +++ b/source/service.go @@ -555,6 +555,9 @@ func extractServiceIps(svc *v1.Service) endpoint.Targets { } func extractServiceExternalName(svc *v1.Service) endpoint.Targets { + if len(svc.Spec.ExternalIPs) > 0 { + return svc.Spec.ExternalIPs + } return endpoint.Targets{svc.Spec.ExternalName} } diff --git a/source/service_test.go b/source/service_test.go index 13c029d593..18c49a21fe 100644 --- a/source/service_test.go +++ b/source/service_test.go @@ -3545,6 +3545,7 @@ func TestExternalServices(t *testing.T) { labels map[string]string annotations map[string]string externalName string + externalIPs []string expected []*endpoint.Endpoint expectError bool }{ @@ -3562,6 +3563,7 @@ func TestExternalServices(t *testing.T) { hostnameAnnotationKey: "service.example.org", }, "111.111.111.111", + []string{}, []*endpoint.Endpoint{ {DNSName: "service.example.org", Targets: endpoint.Targets{"111.111.111.111"}, RecordType: endpoint.RecordTypeA}, }, @@ -3581,6 +3583,7 @@ func TestExternalServices(t *testing.T) { hostnameAnnotationKey: "service.example.org", }, "2001:db8::111", + []string{}, []*endpoint.Endpoint{ {DNSName: "service.example.org", Targets: endpoint.Targets{"2001:db8::111"}, RecordType: endpoint.RecordTypeAAAA}, }, @@ -3600,11 +3603,53 @@ func TestExternalServices(t *testing.T) { hostnameAnnotationKey: "service.example.org", }, "remote.example.com", + []string{}, []*endpoint.Endpoint{ {DNSName: "service.example.org", Targets: endpoint.Targets{"remote.example.com"}, RecordType: endpoint.RecordTypeCNAME}, }, false, }, + { + "annotated ExternalName service with externalIPs returns a single endpoint with multiple targets", + "", + "testing", + "foo", + v1.ServiceTypeExternalName, + "", + "", + false, + map[string]string{"component": "foo"}, + map[string]string{ + hostnameAnnotationKey: "service.example.org", + }, + "service.example.org", + []string{"10.2.3.4", "11.2.3.4"}, + []*endpoint.Endpoint{ + {DNSName: "service.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"10.2.3.4", "11.2.3.4"}}, + }, + false, + }, + { + "annotated ExternalName service with externalIPs of dualstack addresses returns 2 endpoints with multiple targets", + "", + "testing", + "foo", + v1.ServiceTypeExternalName, + "", + "", + false, + map[string]string{"component": "foo"}, + map[string]string{ + hostnameAnnotationKey: "service.example.org", + }, + "service.example.org", + []string{"10.2.3.4", "11.2.3.4", "2001:db8::1", "2001:db8::2"}, + []*endpoint.Endpoint{ + {DNSName: "service.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"10.2.3.4", "11.2.3.4"}}, + {DNSName: "service.example.org", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:db8::1", "2001:db8::2"}}, + }, + false, + }, } { tc := tc t.Run(tc.title, func(t *testing.T) { @@ -3617,6 +3662,7 @@ func TestExternalServices(t *testing.T) { Spec: v1.ServiceSpec{ Type: tc.svcType, ExternalName: tc.externalName, + ExternalIPs: tc.externalIPs, }, ObjectMeta: metav1.ObjectMeta{ Namespace: tc.svcNamespace,