Skip to content

Commit

Permalink
Merge pull request #1412 from ouzklcn/feature/rfc2136-min-ttl
Browse files Browse the repository at this point in the history
Add option to define minimum TTL for rfc2136 provider
  • Loading branch information
k8s-ci-robot committed Feb 19, 2020
2 parents 6337a6d + 21275c9 commit 5fc6adf
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 12 deletions.
2 changes: 1 addition & 1 deletion main.go
Expand Up @@ -240,7 +240,7 @@ func main() {
p, err = provider.NewOCIProvider(*config, domainFilter, zoneIDFilter, cfg.DryRun)
}
case "rfc2136":
p, err = provider.NewRfc2136Provider(cfg.RFC2136Host, cfg.RFC2136Port, cfg.RFC2136Zone, cfg.RFC2136Insecure, cfg.RFC2136TSIGKeyName, cfg.RFC2136TSIGSecret, cfg.RFC2136TSIGSecretAlg, cfg.RFC2136TAXFR, domainFilter, cfg.DryRun, nil)
p, err = provider.NewRfc2136Provider(cfg.RFC2136Host, cfg.RFC2136Port, cfg.RFC2136Zone, cfg.RFC2136Insecure, cfg.RFC2136TSIGKeyName, cfg.RFC2136TSIGSecret, cfg.RFC2136TSIGSecretAlg, cfg.RFC2136TAXFR, domainFilter, cfg.DryRun, cfg.RFC2136MinTTL, nil)
case "ns1":
p, err = provider.NewNS1Provider(
provider.NS1Config{
Expand Down
3 changes: 3 additions & 0 deletions pkg/apis/externaldns/types.go
Expand Up @@ -130,6 +130,7 @@ type Config struct {
RFC2136TSIGSecret string `secure:"yes"`
RFC2136TSIGSecretAlg string
RFC2136TAXFR bool
RFC2136MinTTL time.Duration
NS1Endpoint string
NS1IgnoreSSL bool
TransIPAccountName string
Expand Down Expand Up @@ -223,6 +224,7 @@ var defaultConfig = &Config{
RFC2136TSIGSecret: "",
RFC2136TSIGSecretAlg: "",
RFC2136TAXFR: true,
RFC2136MinTTL: 0,
NS1Endpoint: "",
NS1IgnoreSSL: false,
TransIPAccountName: "",
Expand Down Expand Up @@ -366,6 +368,7 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("rfc2136-tsig-secret", "When using the RFC2136 provider, specify the TSIG (base64) value to attached to DNS messages (required when --rfc2136-insecure=false)").Default(defaultConfig.RFC2136TSIGSecret).StringVar(&cfg.RFC2136TSIGSecret)
app.Flag("rfc2136-tsig-secret-alg", "When using the RFC2136 provider, specify the TSIG (base64) value to attached to DNS messages (required when --rfc2136-insecure=false)").Default(defaultConfig.RFC2136TSIGSecretAlg).StringVar(&cfg.RFC2136TSIGSecretAlg)
app.Flag("rfc2136-tsig-axfr", "When using the RFC2136 provider, specify the TSIG (base64) value to attached to DNS messages (required when --rfc2136-insecure=false)").BoolVar(&cfg.RFC2136TAXFR)
app.Flag("rfc2136-min-ttl", "When using the RFC2136 provider, specify minimal TTL (in duration format) for records. This value will be used if the provided TTL for a service/ingress is lower than this").Default(defaultConfig.RFC2136MinTTL.String()).DurationVar(&cfg.RFC2136MinTTL)

// Flags related to TransIP provider
app.Flag("transip-account", "When using the TransIP provider, specify the account name (required when --provider=transip)").Default(defaultConfig.TransIPAccountName).StringVar(&cfg.TransIPAccountName)
Expand Down
6 changes: 6 additions & 0 deletions pkg/apis/externaldns/validation/validation.go
Expand Up @@ -82,6 +82,12 @@ func ValidateConfig(cfg *externaldns.Config) error {
}
}

if cfg.Provider == "rfc2136" {
if cfg.RFC2136MinTTL < 0 {
return errors.New("TTL specified for rfc2136 is negative")
}
}

if cfg.IgnoreHostnameAnnotation && cfg.FQDNTemplate == "" {
return errors.New("FQDN Template must be set if ignoring annotations")
}
Expand Down
26 changes: 26 additions & 0 deletions pkg/apis/externaldns/validation/validation_test.go
Expand Up @@ -124,3 +124,29 @@ func TestValidateBadIgnoreHostnameAnnotationsConfig(t *testing.T) {

assert.Error(t, ValidateConfig(cfg))
}

func TestValidateBadRfc2136Config(t *testing.T) {
cfg := externaldns.NewConfig()

cfg.LogFormat = "json"
cfg.Sources = []string{"test-source"}
cfg.Provider = "rfc2136"
cfg.RFC2136MinTTL = -1

err := ValidateConfig(cfg)

assert.NotNil(t, err)
}

func TestValidateGoodRfc2136Config(t *testing.T) {
cfg := externaldns.NewConfig()

cfg.LogFormat = "json"
cfg.Sources = []string{"test-source"}
cfg.Provider = "rfc2136"
cfg.RFC2136MinTTL = 3600

err := ValidateConfig(cfg)

assert.Nil(t, err)
}
12 changes: 10 additions & 2 deletions provider/rfc2136.go
Expand Up @@ -41,6 +41,7 @@ type rfc2136Provider struct {
tsigSecretAlg string
insecure bool
axfr bool
minTTL time.Duration

// only consider hosted zones managing domains ending in this suffix
domainFilter DomainFilter
Expand All @@ -64,7 +65,7 @@ type rfc2136Actions interface {
}

// NewRfc2136Provider is a factory function for OpenStack rfc2136 providers
func NewRfc2136Provider(host string, port int, zoneName string, insecure bool, keyName string, secret string, secretAlg string, axfr bool, domainFilter DomainFilter, dryRun bool, actions rfc2136Actions) (Provider, error) {
func NewRfc2136Provider(host string, port int, zoneName string, insecure bool, keyName string, secret string, secretAlg string, axfr bool, domainFilter DomainFilter, dryRun bool, minTTL time.Duration, actions rfc2136Actions) (Provider, error) {
secretAlgChecked, ok := tsigAlgs[secretAlg]
if !ok && !insecure {
return nil, errors.Errorf("%s is not supported TSIG algorithm", secretAlg)
Expand All @@ -77,6 +78,7 @@ func NewRfc2136Provider(host string, port int, zoneName string, insecure bool, k
domainFilter: domainFilter,
dryRun: dryRun,
axfr: axfr,
minTTL: minTTL,
}
if actions != nil {
r.actions = actions
Expand Down Expand Up @@ -253,8 +255,14 @@ func (r rfc2136Provider) UpdateRecord(m *dns.Msg, ep *endpoint.Endpoint) error {

func (r rfc2136Provider) AddRecord(m *dns.Msg, ep *endpoint.Endpoint) error {
log.Debugf("AddRecord.ep=%s", ep)

var ttl = int64(r.minTTL.Seconds())
if ep.RecordTTL.IsConfigured() && int64(ep.RecordTTL) > ttl {
ttl = int64(ep.RecordTTL)
}

for _, target := range ep.Targets {
newRR := fmt.Sprintf("%s %d %s %s", ep.DNSName, ep.RecordTTL, ep.RecordType, target)
newRR := fmt.Sprintf("%s %d %s %s", ep.DNSName, ttl, ep.RecordType, target)
log.Infof("Adding RR: %s", newRR)

rr, err := dns.NewRR(newRR)
Expand Down
66 changes: 57 additions & 9 deletions provider/rfc2136_test.go
Expand Up @@ -18,8 +18,10 @@ package provider

import (
"context"
"fmt"
"strings"
"testing"
"time"

"github.com/miekg/dns"
log "github.com/sirupsen/logrus"
Expand All @@ -44,14 +46,8 @@ func newStub() *rfc2136Stub {
}

func (r *rfc2136Stub) SendMessage(msg *dns.Msg) error {
const searchPattern = "AUTHORITY SECTION:"

data := msg.String()
log.Info(data)

authoritySectionOffset := strings.Index(data, searchPattern)
lines := strings.Split(strings.TrimSpace(data[authoritySectionOffset+len(searchPattern):]), "\n")

log.Info(msg.String())
lines := extractAuthoritySectionFromMessage(msg)
for _, line := range lines {
// break at first empty line
if len(strings.TrimSpace(line)) == 0 {
Expand Down Expand Up @@ -98,7 +94,13 @@ func (r *rfc2136Stub) IncomeTransfer(m *dns.Msg, a string) (env chan *dns.Envelo
}

func createRfc2136StubProvider(stub *rfc2136Stub) (Provider, error) {
return NewRfc2136Provider("", 0, "", false, "key", "secret", "hmac-sha512", true, DomainFilter{}, false, stub)
return NewRfc2136Provider("", 0, "", false, "key", "secret", "hmac-sha512", true, DomainFilter{}, false, 300*time.Second, stub)
}

func extractAuthoritySectionFromMessage(msg fmt.Stringer) []string {
const searchPattern = "AUTHORITY SECTION:"
authoritySectionOffset := strings.Index(msg.String(), searchPattern)
return strings.Split(strings.TrimSpace(msg.String()[authoritySectionOffset+len(searchPattern):]), "\n")
}

// TestRfc2136GetRecordsMultipleTargets simulates a single record with multiple targets.
Expand Down Expand Up @@ -162,6 +164,7 @@ func TestRfc2136ApplyChanges(t *testing.T) {
DNSName: "v1.foo.com",
RecordType: "A",
Targets: []string{"1.2.3.4"},
RecordTTL: endpoint.TTL(400),
},
{
DNSName: "v1.foobar.com",
Expand Down Expand Up @@ -198,3 +201,48 @@ func TestRfc2136ApplyChanges(t *testing.T) {
assert.True(t, strings.Contains(stub.updateMsgs[1].String(), "v2.foobar.com"))

}

func TestRfc2136ApplyChangesWithDifferentTTLs(t *testing.T) {
stub := newStub()

provider, err := createRfc2136StubProvider(stub)
assert.NoError(t, err)

p := &plan.Changes{
Create: []*endpoint.Endpoint{
{
DNSName: "v1.foo.com",
RecordType: "A",
Targets: []string{"2.1.1.1"},
RecordTTL: endpoint.TTL(400),
},
{
DNSName: "v2.foo.com",
RecordType: "A",
Targets: []string{"3.2.2.2"},
RecordTTL: endpoint.TTL(200),
},
{
DNSName: "v3.foo.com",
RecordType: "A",
Targets: []string{"4.3.3.3"},
},
},
}

err = provider.ApplyChanges(context.Background(), p)
assert.NoError(t, err)

createRecords := extractAuthoritySectionFromMessage(stub.createMsgs[0])
assert.Equal(t, 3, len(createRecords))
assert.True(t, strings.Contains(createRecords[0], "v1.foo.com"))
assert.True(t, strings.Contains(createRecords[0], "2.1.1.1"))
assert.True(t, strings.Contains(createRecords[0], "400"))
assert.True(t, strings.Contains(createRecords[1], "v2.foo.com"))
assert.True(t, strings.Contains(createRecords[1], "3.2.2.2"))
assert.True(t, strings.Contains(createRecords[1], "300"))
assert.True(t, strings.Contains(createRecords[2], "v3.foo.com"))
assert.True(t, strings.Contains(createRecords[2], "4.3.3.3"))
assert.True(t, strings.Contains(createRecords[2], "300"))

}

0 comments on commit 5fc6adf

Please sign in to comment.