diff --git a/main.go b/main.go index 77509fa2b..a7da20457 100644 --- a/main.go +++ b/main.go @@ -178,7 +178,7 @@ func main() { }, ) case "coredns", "skydns": - p, err = provider.NewCoreDNSProvider(domainFilter, cfg.DryRun) + p, err = provider.NewCoreDNSProvider(domainFilter, cfg.CoreDNSPrefix, cfg.DryRun) case "rdns": p, err = provider.NewRDNSProvider( provider.RDNSConfig{ diff --git a/pkg/apis/externaldns/types.go b/pkg/apis/externaldns/types.go index 101227474..bf7a99ba2 100644 --- a/pkg/apis/externaldns/types.go +++ b/pkg/apis/externaldns/types.go @@ -71,6 +71,7 @@ type Config struct { AzureResourceGroup string CloudflareProxied bool CloudflareZonesPerPage int + CoreDNSPrefix string RcodezeroTXTEncrypt bool InfobloxGridHost string InfobloxWapiPort int @@ -159,6 +160,7 @@ var defaultConfig = &Config{ AzureResourceGroup: "", CloudflareProxied: false, CloudflareZonesPerPage: 50, + CoreDNSPrefix: "/skydns/", RcodezeroTXTEncrypt: false, InfobloxGridHost: "", InfobloxWapiPort: 443, @@ -302,6 +304,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) @@ -316,7 +319,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/pkg/apis/externaldns/types_test.go b/pkg/apis/externaldns/types_test.go index 041356a9e..584e166be 100644 --- a/pkg/apis/externaldns/types_test.go +++ b/pkg/apis/externaldns/types_test.go @@ -56,6 +56,7 @@ var ( AzureResourceGroup: "", CloudflareProxied: false, CloudflareZonesPerPage: 50, + CoreDNSPrefix: "/skydns/", InfobloxGridHost: "", InfobloxWapiPort: 443, InfobloxWapiUsername: "admin", @@ -119,6 +120,7 @@ var ( AzureResourceGroup: "arg", CloudflareProxied: true, CloudflareZonesPerPage: 20, + CoreDNSPrefix: "/coredns/", InfobloxGridHost: "127.0.0.1", InfobloxWapiPort: 8443, InfobloxWapiUsername: "infoblox", @@ -188,6 +190,7 @@ var ( AzureResourceGroup: "", CloudflareProxied: false, CloudflareZonesPerPage: 50, + CoreDNSPrefix: "/skydns/", InfobloxGridHost: "", InfobloxWapiPort: 443, InfobloxWapiUsername: "admin", @@ -257,6 +260,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", @@ -334,6 +338,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.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 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{