diff --git a/plugin/clouddns/README.md b/plugin/clouddns/README.md index 506ecbabc..219d91335 100644 --- a/plugin/clouddns/README.md +++ b/plugin/clouddns/README.md @@ -20,6 +20,7 @@ the hosted zone. ~~~ txt clouddns [ZONE:PROJECT_ID:HOSTED_ZONE_NAME...] { credentials [FILENAME] + endpoint ENDPOINT fallthrough [ZONES...] refresh DURATION } @@ -41,6 +42,10 @@ clouddns [ZONE:PROJECT_ID:HOSTED_ZONE_NAME...] { Google Cloud's [authentication method](https://cloud.google.com/docs/authentication) and [validating credential configurations from external sources](https://docs.cloud.google.com/docs/authentication/client-libraries#external-credentials) for more details. +* `endpoint` can be used to control the endpoint to use when querying Cloud DNS (optional). + **ENDPOINT** is the URL of the endpoint to use. If this is not provided the default Cloud DNS + endpoint is used. Useful for pointing at a local emulator or test environment. + * `fallthrough` If zone matches and no record can be generated, pass request to the next plugin. If **[ZONES...]** is omitted, then fallthrough happens for all zones for which the plugin is authoritative. If specific zones are listed (for example `in-addr.arpa` and `ip6.arpa`), then @@ -90,3 +95,13 @@ example.org { } } ~~~ + +Enable clouddns against a custom Cloud DNS endpoint: + +~~~ txt +example.org { + clouddns example.org.:gcp-example-project:example-zone { + endpoint https://dns.googleapis.com + } +} +~~~ diff --git a/plugin/clouddns/setup.go b/plugin/clouddns/setup.go index 9306134ac..632ad64fe 100644 --- a/plugin/clouddns/setup.go +++ b/plugin/clouddns/setup.go @@ -25,16 +25,10 @@ var log = clog.NewWithPlugin("clouddns") func init() { plugin.Register("clouddns", setup) } // exposed for testing -var f = func(ctx context.Context, opt option.ClientOption) (gcpDNS, error) { - var err error - var client *gcp.Service - if opt != nil { - client, err = gcp.NewService(ctx, opt) - } else { - // if credentials file is not provided in the Corefile - // authenticate the client using env variables - client, err = gcp.NewService(ctx) - } +var f = func(ctx context.Context, opts ...option.ClientOption) (gcpDNS, error) { + // if credentials file is not provided in the Corefile, authenticate the + // client using env variables; option.WithEndpoint, if any, still applies. + client, err := gcp.NewService(ctx, opts...) return gcpClient{client}, err } @@ -65,7 +59,7 @@ func setup(c *caddy.Controller) error { keys[dnsName] = append(keys[dnsName], projectName+":"+hostedZone) } - var opt option.ClientOption + var opts []option.ClientOption refresh := time.Duration(1) * time.Minute // default update frequency to 1 minute for c.NextBlock() { switch c.Val() { @@ -79,7 +73,12 @@ func setup(c *caddy.Controller) error { if err != nil { return plugin.Error("clouddns", c.Errf("invalid credentials file %q: %v", c.Val(), err)) } - opt = option.WithAuthCredentialsFile(credType, c.Val()) + opts = append(opts, option.WithAuthCredentialsFile(credType, c.Val())) + case "endpoint": + if !c.NextArg() { + return plugin.Error("clouddns", c.ArgErr()) + } + opts = append(opts, option.WithEndpoint(c.Val())) case "fallthrough": fall.SetZonesFromArgs(c.RemainingArgs()) case "refresh": @@ -104,7 +103,7 @@ func setup(c *caddy.Controller) error { } ctx, cancel := context.WithCancel(context.Background()) - client, err := f(ctx, opt) + client, err := f(ctx, opts...) if err != nil { cancel() return err diff --git a/plugin/clouddns/setup_test.go b/plugin/clouddns/setup_test.go index 905347137..5a28520fb 100644 --- a/plugin/clouddns/setup_test.go +++ b/plugin/clouddns/setup_test.go @@ -13,7 +13,7 @@ import ( ) func TestSetupCloudDNS(t *testing.T) { - f = func(_ctx context.Context, _opt option.ClientOption) (gcpDNS, error) { + f = func(_ctx context.Context, _opts ...option.ClientOption) (gcpDNS, error) { return fakeGCPClient{}, nil } @@ -73,6 +73,12 @@ func TestSetupCloudDNS(t *testing.T) { }`, true}, {`clouddns example.org.:example-project:zone-name { refresh -5m +}`, true}, + {`clouddns example.org.:example-project:zone-name { + endpoint https://dns.googleapis.com +}`, false}, + {`clouddns example.org.:example-project:zone-name { + endpoint }`, true}, {`clouddns example.org.:example-project:zone-name example.org.:example-project:zone-name { }`, true},