From 984e7de398a7639d23b2bb298c113fb328838032 Mon Sep 17 00:00:00 2001 From: xunpan Date: Wed, 17 Jul 2019 02:47:23 -0400 Subject: [PATCH 1/2] add option for coredns to specify prefix name --- main.go | 2 +- pkg/apis/externaldns/types.go | 4 +++- provider/coredns.go | 41 ++++++++++++++++++----------------- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/main.go b/main.go index 5c6737f7e..4f546b50f 100644 --- a/main.go +++ b/main.go @@ -176,7 +176,7 @@ func main() { }, ) case "coredns", "skydns": - p, err = provider.NewCoreDNSProvider(domainFilter, cfg.DryRun) + p, err = provider.NewCoreDNSProvider(domainFilter, cfg.CoreDNSPrefix, cfg.DryRun) case "exoscale": p, err = provider.NewExoscaleProvider(cfg.ExoscaleEndpoint, cfg.ExoscaleAPIKey, cfg.ExoscaleAPISecret, cfg.DryRun, provider.ExoscaleWithDomain(domainFilter), provider.ExoscaleWithLogging()), nil case "inmemory": diff --git a/pkg/apis/externaldns/types.go b/pkg/apis/externaldns/types.go index 2107d746c..aed44a75d 100644 --- a/pkg/apis/externaldns/types.go +++ b/pkg/apis/externaldns/types.go @@ -69,6 +69,7 @@ type Config struct { AzureResourceGroup string CloudflareProxied bool CloudflareZonesPerPage int + CoreDNSPrefix string RcodezeroTXTEncrypt bool InfobloxGridHost string InfobloxWapiPort int @@ -155,6 +156,7 @@ var defaultConfig = &Config{ AzureResourceGroup: "", CloudflareProxied: false, CloudflareZonesPerPage: 50, + CoreDNSPrefix: "/skydns/", RcodezeroTXTEncrypt: false, InfobloxGridHost: "", InfobloxWapiPort: 443, @@ -294,6 +296,7 @@ func (cfg *Config) ParseFlags(args []string) error { app.Flag("azure-resource-group", "When using the Azure provider, override the Azure resource group to use (optional)").Default(defaultConfig.AzureResourceGroup).StringVar(&cfg.AzureResourceGroup) app.Flag("cloudflare-proxied", "When using the Cloudflare provider, specify if the proxy mode must be enabled (default: disabled)").BoolVar(&cfg.CloudflareProxied) app.Flag("cloudflare-zones-per-page", "When using the Cloudflare provider, specify how many zones per page listed, max. possible 50 (default: 50)").Default(strconv.Itoa(defaultConfig.CloudflareZonesPerPage)).IntVar(&cfg.CloudflareZonesPerPage) + app.Flag("coredns-prefix", "When using the CoreDNS provider, specify the prefix name").Default(defaultConfig.CoreDNSPrefix).StringVar(&cfg.CoreDNSPrefix) app.Flag("infoblox-grid-host", "When using the Infoblox provider, specify the Grid Manager host (required when --provider=infoblox)").Default(defaultConfig.InfobloxGridHost).StringVar(&cfg.InfobloxGridHost) app.Flag("infoblox-wapi-port", "When using the Infoblox provider, specify the WAPI port (default: 443)").Default(strconv.Itoa(defaultConfig.InfobloxWapiPort)).IntVar(&cfg.InfobloxWapiPort) app.Flag("infoblox-wapi-username", "When using the Infoblox provider, specify the WAPI username (default: admin)").Default(defaultConfig.InfobloxWapiUsername).StringVar(&cfg.InfobloxWapiUsername) @@ -308,7 +311,6 @@ func (cfg *Config) ParseFlags(args []string) error { app.Flag("dyn-min-ttl", "Minimal TTL (in seconds) for records. This value will be used if the provided TTL for a service/ingress is lower than this.").IntVar(&cfg.DynMinTTLSeconds) app.Flag("oci-config-file", "When using the OCI provider, specify the OCI configuration file (required when --provider=oci").Default(defaultConfig.OCIConfigFile).StringVar(&cfg.OCIConfigFile) app.Flag("rcodezero-txt-encrypt", "When using the Rcodezero provider with txt registry option, set if TXT rrs are encrypted (default: false)").Default(strconv.FormatBool(defaultConfig.RcodezeroTXTEncrypt)).BoolVar(&cfg.RcodezeroTXTEncrypt) - app.Flag("inmemory-zone", "Provide a list of pre-configured zones for the inmemory provider; specify multiple times for multiple zones (optional)").Default("").StringsVar(&cfg.InMemoryZones) app.Flag("pdns-server", "When using the PowerDNS/PDNS provider, specify the URL to the pdns server (required when --provider=pdns)").Default(defaultConfig.PDNSServer).StringVar(&cfg.PDNSServer) app.Flag("pdns-api-key", "When using the PowerDNS/PDNS provider, specify the API key to use to authorize requests (required when --provider=pdns)").Default(defaultConfig.PDNSAPIKey).StringVar(&cfg.PDNSAPIKey) diff --git a/provider/coredns.go b/provider/coredns.go index bd09f40a1..019003ceb 100644 --- a/provider/coredns.go +++ b/provider/coredns.go @@ -45,8 +45,6 @@ const ( priority = 10 // default priority when nothing is set etcdTimeout = 5 * time.Second - coreDNSPrefix = "/skydns/" - randomPrefixLabel = "prefix" ) @@ -58,9 +56,10 @@ type coreDNSClient interface { } type coreDNSProvider struct { - dryRun bool - domainFilter DomainFilter - client coreDNSClient + dryRun bool + coreDNSPrefix string + domainFilter DomainFilter + client coreDNSClient } // Service represents CoreDNS etcd record @@ -245,15 +244,17 @@ func newETCDClient() (coreDNSClient, error) { } // NewCoreDNSProvider is a CoreDNS provider constructor -func NewCoreDNSProvider(domainFilter DomainFilter, dryRun bool) (Provider, error) { +func NewCoreDNSProvider(domainFilter DomainFilter, prefix string, dryRun bool) (Provider, error) { client, err := newETCDClient() if err != nil { return nil, err } + return coreDNSProvider{ - client: client, - dryRun: dryRun, - domainFilter: domainFilter, + client: client, + dryRun: dryRun, + coreDNSPrefix: prefix, + domainFilter: domainFilter, }, nil } @@ -261,12 +262,12 @@ func NewCoreDNSProvider(domainFilter DomainFilter, dryRun bool) (Provider, error // it may be mapped to one or two records of type A, CNAME, TXT, A+TXT, CNAME+TXT func (p coreDNSProvider) Records() ([]*endpoint.Endpoint, error) { var result []*endpoint.Endpoint - services, err := p.client.GetServices(coreDNSPrefix) + services, err := p.client.GetServices(p.coreDNSPrefix) if err != nil { return nil, err } for _, service := range services { - domains := strings.Split(strings.TrimPrefix(service.Key, coreDNSPrefix), "/") + domains := strings.Split(strings.TrimPrefix(service.Key, p.coreDNSPrefix), "/") reverse(domains) dnsName := strings.Join(domains[service.TargetStrip:], ".") if !p.domainFilter.Match(dnsName) { @@ -327,7 +328,7 @@ func (p coreDNSProvider) ApplyChanges(ctx context.Context, changes *plan.Changes service := Service{ Host: target, Text: ep.Labels["originalText"], - Key: etcdKeyFor(prefix + "." + dnsName), + Key: p.etcdKeyFor(prefix + "." + dnsName), TargetStrip: strings.Count(prefix, ".") + 1, TTL: uint32(ep.RecordTTL), } @@ -345,7 +346,7 @@ func (p coreDNSProvider) ApplyChanges(ctx context.Context, changes *plan.Changes prefix = fmt.Sprintf("%08x", rand.Int31()) } services = append(services, Service{ - Key: etcdKeyFor(prefix + "." + dnsName), + Key: p.etcdKeyFor(prefix + "." + dnsName), TargetStrip: strings.Count(prefix, ".") + 1, TTL: uint32(ep.RecordTTL), }) @@ -374,7 +375,7 @@ func (p coreDNSProvider) ApplyChanges(ctx context.Context, changes *plan.Changes if ep.Labels[randomPrefixLabel] != "" { dnsName = ep.Labels[randomPrefixLabel] + "." + dnsName } - key := etcdKeyFor(dnsName) + key := p.etcdKeyFor(dnsName) log.Infof("Delete key %s", key) if !p.dryRun { err := p.client.DeleteService(key) @@ -387,6 +388,12 @@ func (p coreDNSProvider) ApplyChanges(ctx context.Context, changes *plan.Changes return nil } +func (p coreDNSProvider) etcdKeyFor(dnsName string) string { + domains := strings.Split(dnsName, ".") + reverse(domains) + return p.coreDNSPrefix + strings.Join(domains, "/") +} + func guessRecordType(target string) string { if net.ParseIP(target) != nil { return endpoint.RecordTypeA @@ -394,12 +401,6 @@ func guessRecordType(target string) string { return endpoint.RecordTypeCNAME } -func etcdKeyFor(dnsName string) string { - domains := strings.Split(dnsName, ".") - reverse(domains) - return coreDNSPrefix + strings.Join(domains, "/") -} - func reverse(slice []string) { for i := 0; i < len(slice)/2; i++ { j := len(slice) - i - 1 From 1260d7b456ff28989145ed8aba08ed77771d8b72 Mon Sep 17 00:00:00 2001 From: xunpan Date: Wed, 17 Jul 2019 03:21:29 -0400 Subject: [PATCH 2/2] add test case for coredns-prefix --- pkg/apis/externaldns/types_test.go | 5 +++++ provider/coredns_test.go | 32 ++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/pkg/apis/externaldns/types_test.go b/pkg/apis/externaldns/types_test.go index dc580a036..375ec5b51 100644 --- a/pkg/apis/externaldns/types_test.go +++ b/pkg/apis/externaldns/types_test.go @@ -54,6 +54,7 @@ var ( AzureResourceGroup: "", CloudflareProxied: false, CloudflareZonesPerPage: 50, + CoreDNSPrefix: "/skydns/", InfobloxGridHost: "", InfobloxWapiPort: 443, InfobloxWapiUsername: "admin", @@ -115,6 +116,7 @@ var ( AzureResourceGroup: "arg", CloudflareProxied: true, CloudflareZonesPerPage: 20, + CoreDNSPrefix: "/coredns/", InfobloxGridHost: "127.0.0.1", InfobloxWapiPort: 8443, InfobloxWapiUsername: "infoblox", @@ -182,6 +184,7 @@ var ( AzureResourceGroup: "", CloudflareProxied: false, CloudflareZonesPerPage: 50, + CoreDNSPrefix: "/skydns/", InfobloxGridHost: "", InfobloxWapiPort: 443, InfobloxWapiUsername: "admin", @@ -250,6 +253,7 @@ func TestParseFlags(t *testing.T) { "--azure-resource-group=arg", "--cloudflare-proxied", "--cloudflare-zones-per-page=20", + "--coredns-prefix=/coredns/", "--infoblox-grid-host=127.0.0.1", "--infoblox-wapi-port=8443", "--infoblox-wapi-username=infoblox", @@ -325,6 +329,7 @@ func TestParseFlags(t *testing.T) { "EXTERNAL_DNS_AZURE_RESOURCE_GROUP": "arg", "EXTERNAL_DNS_CLOUDFLARE_PROXIED": "1", "EXTERNAL_DNS_CLOUDFLARE_ZONES_PER_PAGE": "20", + "EXTERNAL_DNS_COREDNS_PREFIX": "/coredns/", "EXTERNAL_DNS_INFOBLOX_GRID_HOST": "127.0.0.1", "EXTERNAL_DNS_INFOBLOX_WAPI_PORT": "8443", "EXTERNAL_DNS_INFOBLOX_WAPI_USERNAME": "infoblox", diff --git a/provider/coredns_test.go b/provider/coredns_test.go index 698207a0d..e86cc2fe5 100644 --- a/provider/coredns_test.go +++ b/provider/coredns_test.go @@ -25,6 +25,8 @@ import ( "github.com/kubernetes-incubator/external-dns/plan" ) +const defaultCoreDNSPrefix = "/skydns/" + type fakeETCDClient struct { services map[string]*Service } @@ -60,7 +62,10 @@ func TestAServiceTranslation(t *testing.T) { "/skydns/com/example": {Host: expectedTarget}, }, } - provider := coreDNSProvider{client: client} + provider := coreDNSProvider{ + client: client, + coreDNSPrefix: defaultCoreDNSPrefix, + } endpoints, err := provider.Records() if err != nil { t.Fatal(err) @@ -89,7 +94,10 @@ func TestCNAMEServiceTranslation(t *testing.T) { "/skydns/com/example": {Host: expectedTarget}, }, } - provider := coreDNSProvider{client: client} + provider := coreDNSProvider{ + client: client, + coreDNSPrefix: defaultCoreDNSPrefix, + } endpoints, err := provider.Records() if err != nil { t.Fatal(err) @@ -118,7 +126,10 @@ func TestTXTServiceTranslation(t *testing.T) { "/skydns/com/example": {Text: expectedTarget}, }, } - provider := coreDNSProvider{client: client} + provider := coreDNSProvider{ + client: client, + coreDNSPrefix: defaultCoreDNSPrefix, + } endpoints, err := provider.Records() if err != nil { t.Fatal(err) @@ -149,7 +160,10 @@ func TestAWithTXTServiceTranslation(t *testing.T) { "/skydns/com/example": {Host: "1.2.3.4", Text: "string"}, }, } - provider := coreDNSProvider{client: client} + provider := coreDNSProvider{ + client: client, + coreDNSPrefix: defaultCoreDNSPrefix, + } endpoints, err := provider.Records() if err != nil { t.Fatal(err) @@ -188,7 +202,10 @@ func TestCNAMEWithTXTServiceTranslation(t *testing.T) { "/skydns/com/example": {Host: "example.net", Text: "string"}, }, } - provider := coreDNSProvider{client: client} + provider := coreDNSProvider{ + client: client, + coreDNSPrefix: defaultCoreDNSPrefix, + } endpoints, err := provider.Records() if err != nil { t.Fatal(err) @@ -219,7 +236,10 @@ func TestCoreDNSApplyChanges(t *testing.T) { client := fakeETCDClient{ map[string]*Service{}, } - coredns := coreDNSProvider{client: client} + coredns := coreDNSProvider{ + client: client, + coreDNSPrefix: defaultCoreDNSPrefix, + } changes1 := &plan.Changes{ Create: []*endpoint.Endpoint{