Route53: make provider timeouts configurable (#588)

This commit is contained in:
Conor Mongey 2018-07-18 16:37:35 +01:00 committed by Ludovic Fernandez
parent baad3dea99
commit 8b6701514c
2 changed files with 49 additions and 18 deletions

View file

@ -3,6 +3,7 @@
package route53 package route53
import ( import (
"errors"
"fmt" "fmt"
"math/rand" "math/rand"
"os" "os"
@ -17,15 +18,30 @@ import (
"github.com/xenolf/lego/acme" "github.com/xenolf/lego/acme"
) )
const ( // Config is used to configure the creation of the DNSProvider
maxRetries = 5 type Config struct {
route53TTL = 10 MaxRetries int
) TTL int
PropagationTimeout time.Duration
PollingInterval time.Duration
HostedZoneID string
}
// NewDefaultConfig returns a default configuration for the DNSProvider
func NewDefaultConfig() *Config {
return &Config{
MaxRetries: 5,
TTL: 10,
PropagationTimeout: time.Minute * 2,
PollingInterval: time.Second * 4,
HostedZoneID: os.Getenv("AWS_HOSTED_ZONE_ID"),
}
}
// DNSProvider implements the acme.ChallengeProvider interface // DNSProvider implements the acme.ChallengeProvider interface
type DNSProvider struct { type DNSProvider struct {
client *route53.Route53 client *route53.Route53
hostedZoneID string config *Config
} }
// customRetryer implements the client.Retryer interface by composing the // customRetryer implements the client.Retryer interface by composing the
@ -65,35 +81,49 @@ func (d customRetryer) RetryRules(r *request.Request) time.Duration {
// //
// See also: https://github.com/aws/aws-sdk-go/wiki/configuring-sdk // See also: https://github.com/aws/aws-sdk-go/wiki/configuring-sdk
func NewDNSProvider() (*DNSProvider, error) { func NewDNSProvider() (*DNSProvider, error) {
hostedZoneID := os.Getenv("AWS_HOSTED_ZONE_ID") return NewDNSProviderConfig(NewDefaultConfig())
}
// NewDNSProviderConfig takes a given config ans returns a custom configured
// DNSProvider instance
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
if config == nil {
return nil, errors.New("the configuration of the Route53 DNS provider is nil")
}
r := customRetryer{} r := customRetryer{}
r.NumMaxRetries = maxRetries r.NumMaxRetries = config.MaxRetries
config := request.WithRetryer(aws.NewConfig(), r) sessionCfg := request.WithRetryer(aws.NewConfig(), r)
session, err := session.NewSessionWithOptions(session.Options{Config: *config}) session, err := session.NewSessionWithOptions(session.Options{Config: *sessionCfg})
if err != nil { if err != nil {
return nil, err return nil, err
} }
client := route53.New(session) client := route53.New(session)
return &DNSProvider{ return &DNSProvider{
client: client, client: client,
hostedZoneID: hostedZoneID, config: config,
}, nil }, nil
} }
// Timeout returns the timeout and interval to use when checking for DNS
// propagation.
func (r *DNSProvider) Timeout() (timeout, interval time.Duration) {
return r.config.PropagationTimeout, r.config.PollingInterval
}
// Present creates a TXT record using the specified parameters // Present creates a TXT record using the specified parameters
func (r *DNSProvider) Present(domain, token, keyAuth string) error { func (r *DNSProvider) Present(domain, token, keyAuth string) error {
fqdn, value, _ := acme.DNS01Record(domain, keyAuth) fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
value = `"` + value + `"` value = `"` + value + `"`
return r.changeRecord("UPSERT", fqdn, value, route53TTL) return r.changeRecord("UPSERT", fqdn, value, r.config.TTL)
} }
// CleanUp removes the TXT record matching the specified parameters // CleanUp removes the TXT record matching the specified parameters
func (r *DNSProvider) CleanUp(domain, token, keyAuth string) error { func (r *DNSProvider) CleanUp(domain, token, keyAuth string) error {
fqdn, value, _ := acme.DNS01Record(domain, keyAuth) fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
value = `"` + value + `"` value = `"` + value + `"`
return r.changeRecord("DELETE", fqdn, value, route53TTL) return r.changeRecord("DELETE", fqdn, value, r.config.TTL)
} }
func (r *DNSProvider) changeRecord(action, fqdn, value string, ttl int) error { func (r *DNSProvider) changeRecord(action, fqdn, value string, ttl int) error {
@ -123,7 +153,7 @@ func (r *DNSProvider) changeRecord(action, fqdn, value string, ttl int) error {
statusID := resp.ChangeInfo.Id statusID := resp.ChangeInfo.Id
return acme.WaitFor(120*time.Second, 4*time.Second, func() (bool, error) { return acme.WaitFor(r.config.PropagationTimeout, r.config.PollingInterval, func() (bool, error) {
reqParams := &route53.GetChangeInput{ reqParams := &route53.GetChangeInput{
Id: statusID, Id: statusID,
} }
@ -139,8 +169,8 @@ func (r *DNSProvider) changeRecord(action, fqdn, value string, ttl int) error {
} }
func (r *DNSProvider) getHostedZoneID(fqdn string) (string, error) { func (r *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
if r.hostedZoneID != "" { if r.config.HostedZoneID != "" {
return r.hostedZoneID, nil return r.config.HostedZoneID, nil
} }
authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers) authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)

View file

@ -42,7 +42,8 @@ func makeRoute53Provider(ts *httptest.Server) *DNSProvider {
} }
client := route53.New(session.New(config)) client := route53.New(session.New(config))
return &DNSProvider{client: client} cfg := NewDefaultConfig()
return &DNSProvider{client: client, config: cfg}
} }
func TestCredentialsFromEnv(t *testing.T) { func TestCredentialsFromEnv(t *testing.T) {