Initial IPv6 support

This commit is contained in:
Skyler Mäntysaari 2021-11-12 23:40:20 -08:00 committed by John Gardiner Myers
parent 9bb9a80c71
commit 6f42a8a2da
9 changed files with 151 additions and 9 deletions

View File

@ -166,7 +166,7 @@ type Endpoint struct {
DNSName string `json:"dnsName,omitempty"`
// The targets the DNS record points to
Targets Targets `json:"targets,omitempty"`
// RecordType type of record, e.g. CNAME, A, SRV, TXT etc
// RecordType type of record, e.g. CNAME, A, AAAA, SRV, TXT etc
RecordType string `json:"recordType,omitempty"`
// Identifier to distinguish multiple records with the same name and type (e.g. Route53 records with routing policies other than 'simple')
SetIdentifier string `json:"setIdentifier,omitempty"`

View File

@ -35,6 +35,22 @@ func TestNewEndpoint(t *testing.T) {
}
}
func TestNewEndpointWithIPv6(t *testing.T) {
e := NewEndpoint("example.org", "AAAA", "foo.com")
if e.DNSName != "example.com" || e.Targets[0] != "foo.com" || e.RecordType != "AAAA" {
t.Error("Endpoint is not initialized correctly")
}
if e.Labels == nil {
t.Error("Labels is not initialized")
}
w := NewEndpoint("example.org", "", "load-balancer.com.")
if w.DNSName != "example.org" || e.Targets[0] != "load-balancer.com" || w.RecordType != "" {
t.Error("Endpoint is not initialized correctly")
}
}
func TestTargetsSame(t *testing.T) {
tests := []Targets{
{""},

View File

@ -327,7 +327,7 @@ var defaultConfig = &Config{
TransIPAccountName: "",
TransIPPrivateKeyFile: "",
DigitalOceanAPIPageSize: 50,
ManagedDNSRecordTypes: []string{endpoint.RecordTypeA, endpoint.RecordTypeCNAME},
ManagedDNSRecordTypes: []string{endpoint.RecordTypeA, endpoint.RecordTypeAAAA, endpoint.RecordTypeCNAME},
GoDaddyAPIKey: "",
GoDaddySecretKey: "",
GoDaddyTTL: 600,
@ -424,7 +424,7 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("crd-source-apiversion", "API version of the CRD for crd source, e.g. `externaldns.k8s.io/v1alpha1`, valid only when using crd source").Default(defaultConfig.CRDSourceAPIVersion).StringVar(&cfg.CRDSourceAPIVersion)
app.Flag("crd-source-kind", "Kind of the CRD for the crd source in API group and version specified by crd-source-apiversion").Default(defaultConfig.CRDSourceKind).StringVar(&cfg.CRDSourceKind)
app.Flag("service-type-filter", "The service types to take care about (default: all, expected: ClusterIP, NodePort, LoadBalancer or ExternalName)").StringsVar(&cfg.ServiceTypeFilter)
app.Flag("managed-record-types", "Record types to manage; specify multiple times to include many; (default: A, CNAME) (supported records: CNAME, A, NS").Default("A", "CNAME").StringsVar(&cfg.ManagedDNSRecordTypes)
app.Flag("managed-record-types", "Record types to manage; specify multiple times to include many; (default: A, AAAA, CNAME) (supported records: CNAME, A, AAAA, NS").Default("A", "AAAA", "CNAME").StringsVar(&cfg.ManagedDNSRecordTypes)
app.Flag("default-targets", "Set globally default IP address that will apply as a target instead of source addresses. Specify multiple times for multiple targets (optional)").StringsVar(&cfg.DefaultTargets)
app.Flag("target-net-filter", "Limit possible targets by a net filter; specify multiple times for multiple possible nets (optional)").StringsVar(&cfg.TargetNetFilter)
app.Flag("exclude-target-net", "Exclude target nets (optional)").StringsVar(&cfg.ExcludeTargetNets)

View File

@ -122,7 +122,7 @@ var (
TransIPAccountName: "",
TransIPPrivateKeyFile: "",
DigitalOceanAPIPageSize: 50,
ManagedDNSRecordTypes: []string{endpoint.RecordTypeA, endpoint.RecordTypeCNAME},
ManagedDNSRecordTypes: []string{endpoint.RecordTypeA, endpoint.RecordTypeAAAA, endpoint.RecordTypeCNAME},
RFC2136BatchChangeSize: 50,
OCPRouterName: "default",
IBMCloudProxied: false,
@ -233,7 +233,7 @@ var (
TransIPAccountName: "transip",
TransIPPrivateKeyFile: "/path/to/transip.key",
DigitalOceanAPIPageSize: 100,
ManagedDNSRecordTypes: []string{endpoint.RecordTypeA, endpoint.RecordTypeCNAME, endpoint.RecordTypeNS},
ManagedDNSRecordTypes: []string{endpoint.RecordTypeA, endpoint.RecordTypeAAAA, endpoint.RecordTypeCNAME, endpoint.RecordTypeNS},
RFC2136BatchChangeSize: 100,
IBMCloudProxied: true,
IBMCloudConfigFile: "ibmcloud.json",

View File

@ -315,7 +315,6 @@ func (p *PDNSProvider) ConvertEndpointsToZones(eps []*endpoint.Endpoint, changet
if ep.RecordType == "CNAME" {
t = provider.EnsureTrailingDot(t)
}
records = append(records, pgo.Record{Content: t})
}
rrset := pgo.RrSet{

View File

@ -456,6 +456,14 @@ func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, pro
DNSName: hostname,
}
epAAAA := &endpoint.Endpoint{
RecordTTL: ttl,
RecordType: endpoint.RecordTypeAAAA,
Labels: endpoint.NewLabels(),
Targets: make(endpoint.Targets, 0, defaultTargetsCapacity),
DNSName: hostname,
}
epCNAME := &endpoint.Endpoint{
RecordTTL: ttl,
RecordType: endpoint.RecordTypeCNAME,
@ -497,6 +505,9 @@ func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, pro
if suitableType(t) == endpoint.RecordTypeA {
epA.Targets = append(epA.Targets, t)
}
if suitableType(t) == endpoint.RecordTypeAAAA {
epAAAA.Targets = append(epAAAA.Targets, t)
}
if suitableType(t) == endpoint.RecordTypeCNAME {
epCNAME.Targets = append(epCNAME.Targets, t)
}
@ -505,6 +516,9 @@ func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, pro
if len(epA.Targets) > 0 {
endpoints = append(endpoints, epA)
}
if len(epAAAA.Targets) > 0 {
endpoints = append(endpoints, epAAAA)
}
if len(epCNAME.Targets) > 0 {
endpoints = append(endpoints, epCNAME)
}

View File

@ -187,6 +187,7 @@ func testServiceSourceEndpoints(t *testing.T) {
labels map[string]string
annotations map[string]string
clusterIP string
ipFamilies []v1.IPFamily
externalIPs []string
lbs []string
serviceTypesFilter []string
@ -201,6 +202,7 @@ func testServiceSourceEndpoints(t *testing.T) {
svcType: v1.ServiceTypeLoadBalancer,
labels: map[string]string{},
annotations: map[string]string{},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -214,6 +216,7 @@ func testServiceSourceEndpoints(t *testing.T) {
ignoreHostnameAnnotation: true,
labels: map[string]string{},
annotations: map[string]string{},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -228,6 +231,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -245,6 +249,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -259,6 +264,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
clusterIP: "1.2.3.4",
externalIPs: []string{},
lbs: []string{},
@ -273,6 +279,7 @@ func testServiceSourceEndpoints(t *testing.T) {
fqdnTemplate: "{{.Name}}.fqdn.org,{{.Name}}.fqdn.com",
labels: map[string]string{},
annotations: map[string]string{},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -290,6 +297,7 @@ func testServiceSourceEndpoints(t *testing.T) {
ignoreHostnameAnnotation: true,
labels: map[string]string{},
annotations: map[string]string{},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -309,6 +317,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org., bar.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -331,6 +340,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org., bar.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -348,6 +358,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org., bar.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -365,6 +376,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org, bar.example.org",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -382,6 +394,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"lb.example.com"}, // Kubernetes omits the trailing dot
serviceTypesFilter: []string{},
@ -398,6 +411,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org", // Trailing dot is omitted
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4", "lb.example.com"}, // Kubernetes omits the trailing dot
serviceTypesFilter: []string{},
@ -416,6 +430,7 @@ func testServiceSourceEndpoints(t *testing.T) {
controllerAnnotationKey: controllerAnnotationValue,
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -434,6 +449,7 @@ func testServiceSourceEndpoints(t *testing.T) {
controllerAnnotationKey: "some-other-tool",
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -449,6 +465,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -466,6 +483,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -480,6 +498,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -498,6 +517,7 @@ func testServiceSourceEndpoints(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
"service.beta.kubernetes.io/external-traffic": "OnlyLocal",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -516,6 +536,7 @@ func testServiceSourceEndpoints(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
"service.beta.kubernetes.io/external-traffic": "SomethingElse",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -532,6 +553,7 @@ func testServiceSourceEndpoints(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
"service.beta.kubernetes.io/external-traffic": "OnlyLocal",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -549,6 +571,7 @@ func testServiceSourceEndpoints(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
"service.beta.kubernetes.io/external-traffic": "Global",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -567,6 +590,7 @@ func testServiceSourceEndpoints(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
"service.beta.kubernetes.io/external-traffic": "OnlyLocal",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -581,6 +605,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{},
serviceTypesFilter: []string{},
@ -595,6 +620,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{"10.2.3.4", "11.2.3.4"},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -611,6 +637,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4", "8.8.8.8"},
serviceTypesFilter: []string{},
@ -627,6 +654,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
"zalando.org/dnsname": "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -642,6 +670,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
"zalando.org/dnsname": "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -658,6 +687,7 @@ func testServiceSourceEndpoints(t *testing.T) {
labels: map[string]string{
"dns": "route53",
},
ipFamilies: []v1.IPFamily{"IPv4"},
annotations: map[string]string{
"domainName": "foo.example.org., bar.example.org",
},
@ -679,6 +709,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
kopsDNSControllerInternalHostnameAnnotationKey: "internal.foo.example.org",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4", "lb.example.com"},
serviceTypesFilter: []string{},
@ -698,6 +729,7 @@ func testServiceSourceEndpoints(t *testing.T) {
kopsDNSControllerInternalHostnameAnnotationKey: "internal.foo.example.org., internal.bar.example.org",
kopsDNSControllerHostnameAnnotationKey: "foo.example.org., bar.example.org",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -716,6 +748,7 @@ func testServiceSourceEndpoints(t *testing.T) {
fqdnTemplate: "{{.Name}}.bar.example.com",
labels: map[string]string{},
annotations: map[string]string{},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4", "elb.com"},
serviceTypesFilter: []string{},
@ -734,6 +767,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4", "elb.com"},
serviceTypesFilter: []string{},
@ -753,6 +787,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
"zalando.org/dnsname": "mate.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -768,6 +803,7 @@ func testServiceSourceEndpoints(t *testing.T) {
fqdnTemplate: "{{.Calibre}}.bar.example.com",
labels: map[string]string{},
annotations: map[string]string{},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -783,6 +819,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -800,6 +837,7 @@ func testServiceSourceEndpoints(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
ttlAnnotationKey: "foo",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -817,6 +855,7 @@ func testServiceSourceEndpoints(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
ttlAnnotationKey: "10",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -834,6 +873,7 @@ func testServiceSourceEndpoints(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
ttlAnnotationKey: "1m",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -851,6 +891,7 @@ func testServiceSourceEndpoints(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
ttlAnnotationKey: "-10",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{},
@ -867,6 +908,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{string(v1.ServiceTypeLoadBalancer)},
@ -883,6 +925,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
hostnameAnnotationKey: "foo.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
serviceTypesFilter: []string{string(v1.ServiceTypeLoadBalancer)},
@ -897,6 +940,7 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{
internalHostnameAnnotationKey: "foo.internal.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
clusterIP: "1.1.1.1",
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
@ -915,6 +959,7 @@ func testServiceSourceEndpoints(t *testing.T) {
hostnameAnnotationKey: "foo.example.org.",
internalHostnameAnnotationKey: "foo.internal.example.org.",
},
ipFamilies: []v1.IPFamily{"IPv4"},
clusterIP: "1.1.1.1",
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
@ -932,6 +977,7 @@ func testServiceSourceEndpoints(t *testing.T) {
labels: map[string]string{
"app": "web-external",
},
ipFamilies: []v1.IPFamily{"IPv4"},
clusterIP: "1.1.1.1",
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
@ -950,6 +996,7 @@ func testServiceSourceEndpoints(t *testing.T) {
labels: map[string]string{
"app": "web-external",
},
ipFamilies: []v1.IPFamily{"IPv4"},
clusterIP: "1.1.1.1",
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
@ -968,6 +1015,7 @@ func testServiceSourceEndpoints(t *testing.T) {
labels: map[string]string{
"app": "web-internal",
},
ipFamilies: []v1.IPFamily{"IPv4"},
clusterIP: "1.1.1.1",
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
@ -984,6 +1032,7 @@ func testServiceSourceEndpoints(t *testing.T) {
labels: map[string]string{
"app": "web-internal",
},
ipFamilies: []v1.IPFamily{"IPv4"},
clusterIP: "1.1.1.1",
externalIPs: []string{},
lbs: []string{"1.2.3.4"},
@ -992,6 +1041,38 @@ func testServiceSourceEndpoints(t *testing.T) {
annotations: map[string]string{hostnameAnnotationKey: "annotation.bar.example.com"},
expected: []*endpoint.Endpoint{},
},
{
title: "dual-stack load-balancer service gets both addresses",
svcNamespace: "testing",
svcName: "foobar",
svcType: v1.ServiceTypeLoadBalancer,
labels: map[string]string{},
ipFamilies: []v1.IPFamily{"IPv4", "IPv6"},
clusterIP: "1.1.1.2,2001:db8::2",
externalIPs: []string{},
lbs: []string{"1.1.1.1", "2001:db8::1"},
serviceTypesFilter: []string{},
annotations: map[string]string{hostnameAnnotationKey: "foobar.example.org"},
expected: []*endpoint.Endpoint{
{DNSName: "foobar.example.org", Targets: endpoint.Targets{"1.1.1.1", "2001:db8::1"}},
},
},
{
title: "IPv6-only load-balancer service gets IPv6 endpoint",
svcNamespace: "testing",
svcName: "foobar-v6",
svcType: v1.ServiceTypeLoadBalancer,
labels: map[string]string{},
ipFamilies: []v1.IPFamily{"IPv6"},
clusterIP: "2001:db8::1",
externalIPs: []string{},
lbs: []string{"2001:db8::2"},
serviceTypesFilter: []string{},
annotations: map[string]string{hostnameAnnotationKey: "foobar-v6.example.org"},
expected: []*endpoint.Endpoint{
{DNSName: "foobar-v6.example.org", Targets: endpoint.Targets{"2001:db8::2"}},
},
},
} {
tc := tc
t.Run(tc.title, func(t *testing.T) {

View File

@ -239,8 +239,10 @@ func getTargetsFromTargetAnnotation(annotations map[string]string) endpoint.Targ
// suitableType returns the DNS resource record type suitable for the target.
// In this case type A for IPs and type CNAME for everything else.
func suitableType(target string) string {
if net.ParseIP(target) != nil {
if net.ParseIP(target) != nil && net.ParseIP(target).To4() != nil {
return endpoint.RecordTypeA
} else if net.ParseIP(target) != nil && net.ParseIP(target).To16() != nil {
return endpoint.RecordTypeAAAA
}
return endpoint.RecordTypeCNAME
}
@ -250,12 +252,23 @@ func endpointsForHostname(hostname string, targets endpoint.Targets, ttl endpoin
var endpoints []*endpoint.Endpoint
var aTargets endpoint.Targets
var aaaaTargets endpoint.Targets
var cnameTargets endpoint.Targets
for _, t := range targets {
switch suitableType(t) {
case endpoint.RecordTypeA:
aTargets = append(aTargets, t)
if !isIPv6String(t) {
aTargets = append(aTargets, t)
} else {
continue
}
case endpoint.RecordTypeAAAA:
if isIPv6String(t) {
aaaaTargets = append(aaaaTargets, t)
} else {
continue
}
default:
cnameTargets = append(cnameTargets, t)
}
@ -274,6 +287,19 @@ func endpointsForHostname(hostname string, targets endpoint.Targets, ttl endpoin
endpoints = append(endpoints, epA)
}
if len(aaaaTargets) > 0 {
epAAAA := &endpoint.Endpoint{
DNSName: strings.TrimSuffix(hostname, "."),
Targets: aaaaTargets,
RecordTTL: ttl,
RecordType: endpoint.RecordTypeAAAA,
Labels: endpoint.NewLabels(),
ProviderSpecific: providerSpecific,
SetIdentifier: setIdentifier,
}
endpoints = append(endpoints, epAAAA)
}
if len(cnameTargets) > 0 {
epCNAME := &endpoint.Endpoint{
DNSName: strings.TrimSuffix(hostname, "."),
@ -286,7 +312,6 @@ func endpointsForHostname(hostname string, targets endpoint.Targets, ttl endpoin
}
endpoints = append(endpoints, epCNAME)
}
return endpoints
}
@ -348,3 +373,9 @@ func waitForDynamicCacheSync(ctx context.Context, factory dynamicInformerFactory
}
return nil
}
// isIPv6String returns if ip is IPv6.
func isIPv6String(ip string) bool {
netIP := net.ParseIP(ip)
return netIP != nil && netIP.To4() == nil
}

View File

@ -94,6 +94,7 @@ func TestSuitableType(t *testing.T) {
target, recordType, expected string
}{
{"8.8.8.8", "", "A"},
{"2001:db8::1", "", "AAAA"},
{"foo.example.org", "", "CNAME"},
{"bar.eu-central-1.elb.amazonaws.com", "", "CNAME"},
} {