Skip to content

Commit

Permalink
feat: use ClusterIP with internal-hostname annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
btoonk committed Feb 14, 2020
1 parent b8d018f commit b1544ac
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 9 deletions.
27 changes: 18 additions & 9 deletions source/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func (sc *serviceSource) Endpoints() ([]*endpoint.Endpoint, error) {
continue
}

svcEndpoints := sc.endpoints(svc)
svcEndpoints := append(sc.endpoints(svc, false), sc.endpoints(svc, true)...)

// process legacy annotations if no endpoints were returned and compatibility mode is enabled.
if len(svcEndpoints) == 0 && sc.compatibility != "" {
Expand All @@ -178,7 +178,7 @@ func (sc *serviceSource) Endpoints() ([]*endpoint.Endpoint, error) {

// apply template if none of the above is found
if (sc.combineFQDNAnnotation || len(svcEndpoints) == 0) && sc.fqdnTemplate != nil {
sEndpoints, err := sc.endpointsFromTemplate(svc)
sEndpoints, err := sc.endpointsFromTemplate(svc, false)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -271,7 +271,7 @@ func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname stri
return endpoints
}

func (sc *serviceSource) endpointsFromTemplate(svc *v1.Service) ([]*endpoint.Endpoint, error) {
func (sc *serviceSource) endpointsFromTemplate(svc *v1.Service, useClusterIP bool) ([]*endpoint.Endpoint, error) {
var endpoints []*endpoint.Endpoint

// Process the whole template string
Expand All @@ -284,21 +284,26 @@ func (sc *serviceSource) endpointsFromTemplate(svc *v1.Service) ([]*endpoint.End
providerSpecific, setIdentifier := getProviderSpecificAnnotations(svc.Annotations)
hostnameList := strings.Split(strings.Replace(buf.String(), " ", "", -1), ",")
for _, hostname := range hostnameList {
endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, providerSpecific, setIdentifier)...)
endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, providerSpecific, setIdentifier, useClusterIP)...)
}

return endpoints, nil
}

// endpointsFromService extracts the endpoints from a service object
func (sc *serviceSource) endpoints(svc *v1.Service) []*endpoint.Endpoint {
func (sc *serviceSource) endpoints(svc *v1.Service, useClusterIP bool) []*endpoint.Endpoint {
var endpoints []*endpoint.Endpoint
// Skip endpoints if we do not want entries from annotations
if !sc.ignoreHostnameAnnotation {
providerSpecific, setIdentifier := getProviderSpecificAnnotations(svc.Annotations)
hostnameList := getHostnamesFromAnnotations(svc.Annotations)
var hostnameList []string
if useClusterIP {
hostnameList = getInternalHostnamesFromAnnotations(svc.Annotations)
} else {
hostnameList = getHostnamesFromAnnotations(svc.Annotations)
}
for _, hostname := range hostnameList {
endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, providerSpecific, setIdentifier)...)
endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, providerSpecific, setIdentifier, useClusterIP)...)
}
}
return endpoints
Expand Down Expand Up @@ -354,7 +359,7 @@ func (sc *serviceSource) setResourceLabel(service *v1.Service, endpoints []*endp
}
}

func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, providerSpecific endpoint.ProviderSpecific, setIdentifier string) []*endpoint.Endpoint {
func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, providerSpecific endpoint.ProviderSpecific, setIdentifier string, useClusterIP bool) []*endpoint.Endpoint {
hostname = strings.TrimSuffix(hostname, ".")
ttl, err := getTTLFromAnnotations(svc.Annotations)
if err != nil {
Expand Down Expand Up @@ -382,7 +387,11 @@ func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, pro

switch svc.Spec.Type {
case v1.ServiceTypeLoadBalancer:
targets = append(targets, extractLoadBalancerTargets(svc)...)
if useClusterIP {
targets = append(targets, extractServiceIps(svc)...)
} else {
targets = append(targets, extractLoadBalancerTargets(svc)...)
}
case v1.ServiceTypeClusterIP:
if sc.publishInternal {
targets = append(targets, extractServiceIps(svc)...)
Expand Down
48 changes: 48 additions & 0 deletions source/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,54 @@ func testServiceSourceEndpoints(t *testing.T) {
[]*endpoint.Endpoint{},
false,
},
{
"internal-host annotated services return an endpoint with Cluster IP",
"",
"",
"testing",
"foo",
v1.ServiceTypeLoadBalancer,
"",
"",
false,
false,
map[string]string{},
map[string]string{
internalHostnameAnnotationKey: "foo.internal.example.org.",
},
"1.1.1.1",
[]string{"1.2.3.4"},
[]string{},
[]*endpoint.Endpoint{
{DNSName: "foo.internal.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
},
false,
},
{
"internal-host annotated and host annotated services return an endpoint with Cluster IP and an endpoint with lb IP",
"",
"",
"testing",
"foo",
v1.ServiceTypeLoadBalancer,
"",
"",
false,
false,
map[string]string{},
map[string]string{
hostnameAnnotationKey: "foo.example.org.",
internalHostnameAnnotationKey: "foo.internal.example.org.",
},
"1.1.1.1",
[]string{"1.2.3.4"},
[]string{},
[]*endpoint.Endpoint{
{DNSName: "foo.internal.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
},
false,
},
} {
t.Run(tc.title, func(t *testing.T) {
// Create a Kubernetes testing client
Expand Down
10 changes: 10 additions & 0 deletions source/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ const (
aliasAnnotationKey = "external-dns.alpha.kubernetes.io/alias"
// The value of the controller annotation so that we feel responsible
controllerAnnotationValue = "dns-controller"
// The annotation used for defining the desired hostname
internalHostnameAnnotationKey = "external-dns.alpha.kubernetes.io/internal-hostname"
)

// Provider-specific annotations
Expand Down Expand Up @@ -102,6 +104,14 @@ func getHostnamesFromAnnotations(annotations map[string]string) []string {
return strings.Split(strings.Replace(hostnameAnnotation, " ", "", -1), ",")
}

func getInternalHostnamesFromAnnotations(annotations map[string]string) []string {
internalHostnameAnnotation, exists := annotations[internalHostnameAnnotationKey]
if !exists {
return nil
}
return strings.Split(strings.Replace(internalHostnameAnnotation, " ", "", -1), ",")
}

func getAliasFromAnnotations(annotations map[string]string) bool {
aliasAnnotation, exists := annotations[aliasAnnotationKey]
return exists && aliasAnnotation == "true"
Expand Down

0 comments on commit b1544ac

Please sign in to comment.