mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-09-20 06:46:19 +08:00
REFACTOR: Add diff2 enable flag to all DNS providers (#1851)
This should enable the diff2 code to be inserted with good "git blame" results for new code. I'm adding this early to catch any problems early.
This commit is contained in:
parent
fe03b29ab2
commit
b0f2945510
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/js"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
@ -57,6 +58,11 @@ func Run(v string) int {
|
|||
Usage: "Enable JS fetch(), dangerous on untrusted code!",
|
||||
Destination: &js.EnableFetch,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "diff2",
|
||||
Usage: "Enable replacement diff algorithm",
|
||||
Destination: &diff2.EnableDiff2,
|
||||
},
|
||||
}
|
||||
sort.Sort(cli.CommandsByName(commands))
|
||||
app.Commands = commands
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/credsfile"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/nameservers"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/normalize"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
|
@ -29,6 +30,8 @@ var enableCFWorkers = flag.Bool("cfworkers", true, "Set false to disable CF work
|
|||
|
||||
func init() {
|
||||
testing.Init()
|
||||
|
||||
flag.BoolVar(&diff2.EnableDiff2, "diff2", false, "enable diff2")
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
|
|
4
pkg/diff2/flag.go
Normal file
4
pkg/diff2/flag.go
Normal file
|
@ -0,0 +1,4 @@
|
|||
package diff2
|
||||
|
||||
// EnableDiff2 is true to activate the experimental diff2 algorithm.
|
||||
var EnableDiff2 bool
|
|
@ -16,6 +16,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
|
@ -121,101 +122,108 @@ func (a *edgeDNSProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
|||
models.PostProcessRecords(existingRecords)
|
||||
txtutil.SplitSingleLongTxt(dc.Records)
|
||||
|
||||
keysToUpdate, err := (diff.New(dc)).ChangedGroups(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
existingRecordsMap := make(map[models.RecordKey][]*models.RecordConfig)
|
||||
for _, r := range existingRecords {
|
||||
key := models.RecordKey{NameFQDN: r.NameFQDN, Type: r.Type}
|
||||
existingRecordsMap[key] = append(existingRecordsMap[key], r)
|
||||
}
|
||||
keysToUpdate, err := (diff.New(dc)).ChangedGroups(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
desiredRecordsMap := dc.Records.GroupedByKey()
|
||||
existingRecordsMap := make(map[models.RecordKey][]*models.RecordConfig)
|
||||
for _, r := range existingRecords {
|
||||
key := models.RecordKey{NameFQDN: r.NameFQDN, Type: r.Type}
|
||||
existingRecordsMap[key] = append(existingRecordsMap[key], r)
|
||||
}
|
||||
|
||||
// Deletes must occur first. For example, if replacing a existing CNAME with an A of the same name:
|
||||
// DELETE CNAME foo.example.net
|
||||
// must occur before
|
||||
// CREATE A foo.example.net
|
||||
// because both an A and a CNAME for the same name is not allowed.
|
||||
desiredRecordsMap := dc.Records.GroupedByKey()
|
||||
|
||||
corrections := []*models.Correction{} // deletes first
|
||||
lastCorrections := []*models.Correction{} // creates and replaces last
|
||||
// Deletes must occur first. For example, if replacing a existing CNAME with an A of the same name:
|
||||
// DELETE CNAME foo.example.net
|
||||
// must occur before
|
||||
// CREATE A foo.example.net
|
||||
// because both an A and a CNAME for the same name is not allowed.
|
||||
|
||||
for key, msg := range keysToUpdate {
|
||||
existing, okExisting := existingRecordsMap[key]
|
||||
desired, okDesired := desiredRecordsMap[key]
|
||||
lastCorrections := []*models.Correction{} // creates and replaces last
|
||||
|
||||
if okExisting && !okDesired {
|
||||
// In the existing map but not in the desired map: Delete
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: strings.Join(msg, "\n "),
|
||||
F: func() error {
|
||||
return deleteRecordset(existing, dc.Name)
|
||||
},
|
||||
})
|
||||
printer.Debugf("deleteRecordset: %s %s\n", key.NameFQDN, key.Type)
|
||||
for _, rdata := range existing {
|
||||
printer.Debugf(" Rdata: %s\n", rdata.GetTargetCombined())
|
||||
}
|
||||
} else if !okExisting && okDesired {
|
||||
// Not in the existing map but in the desired map: Create
|
||||
lastCorrections = append(lastCorrections, &models.Correction{
|
||||
Msg: strings.Join(msg, "\n "),
|
||||
F: func() error {
|
||||
return createRecordset(desired, dc.Name)
|
||||
},
|
||||
})
|
||||
printer.Debugf("createRecordset: %s %s\n", key.NameFQDN, key.Type)
|
||||
for _, rdata := range desired {
|
||||
printer.Debugf(" Rdata: %s\n", rdata.GetTargetCombined())
|
||||
}
|
||||
} else if okExisting && okDesired {
|
||||
// In the existing map and in the desired map: Replace
|
||||
lastCorrections = append(lastCorrections, &models.Correction{
|
||||
Msg: strings.Join(msg, "\n "),
|
||||
F: func() error {
|
||||
return replaceRecordset(desired, dc.Name)
|
||||
},
|
||||
})
|
||||
printer.Debugf("replaceRecordset: %s %s\n", key.NameFQDN, key.Type)
|
||||
for _, rdata := range desired {
|
||||
printer.Debugf(" Rdata: %s\n", rdata.GetTargetCombined())
|
||||
for key, msg := range keysToUpdate {
|
||||
existing, okExisting := existingRecordsMap[key]
|
||||
desired, okDesired := desiredRecordsMap[key]
|
||||
|
||||
if okExisting && !okDesired {
|
||||
// In the existing map but not in the desired map: Delete
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: strings.Join(msg, "\n "),
|
||||
F: func() error {
|
||||
return deleteRecordset(existing, dc.Name)
|
||||
},
|
||||
})
|
||||
printer.Debugf("deleteRecordset: %s %s\n", key.NameFQDN, key.Type)
|
||||
for _, rdata := range existing {
|
||||
printer.Debugf(" Rdata: %s\n", rdata.GetTargetCombined())
|
||||
}
|
||||
} else if !okExisting && okDesired {
|
||||
// Not in the existing map but in the desired map: Create
|
||||
lastCorrections = append(lastCorrections, &models.Correction{
|
||||
Msg: strings.Join(msg, "\n "),
|
||||
F: func() error {
|
||||
return createRecordset(desired, dc.Name)
|
||||
},
|
||||
})
|
||||
printer.Debugf("createRecordset: %s %s\n", key.NameFQDN, key.Type)
|
||||
for _, rdata := range desired {
|
||||
printer.Debugf(" Rdata: %s\n", rdata.GetTargetCombined())
|
||||
}
|
||||
} else if okExisting && okDesired {
|
||||
// In the existing map and in the desired map: Replace
|
||||
lastCorrections = append(lastCorrections, &models.Correction{
|
||||
Msg: strings.Join(msg, "\n "),
|
||||
F: func() error {
|
||||
return replaceRecordset(desired, dc.Name)
|
||||
},
|
||||
})
|
||||
printer.Debugf("replaceRecordset: %s %s\n", key.NameFQDN, key.Type)
|
||||
for _, rdata := range desired {
|
||||
printer.Debugf(" Rdata: %s\n", rdata.GetTargetCombined())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deletes first, then creates and replaces
|
||||
corrections = append(corrections, lastCorrections...)
|
||||
|
||||
// AutoDnsSec correction
|
||||
existingAutoDNSSecEnabled, err := isAutoDNSSecEnabled(dc.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
desiredAutoDNSSecEnabled := dc.AutoDNSSEC == "on"
|
||||
|
||||
if !existingAutoDNSSecEnabled && desiredAutoDNSSecEnabled {
|
||||
// Existing false (disabled), Desired true (enabled)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: "Enable AutoDnsSec\n",
|
||||
F: func() error {
|
||||
return autoDNSSecEnable(true, dc.Name)
|
||||
},
|
||||
})
|
||||
printer.Debugf("autoDNSSecEnable: Enable AutoDnsSec for zone %s\n", dc.Name)
|
||||
} else if existingAutoDNSSecEnabled && !desiredAutoDNSSecEnabled {
|
||||
// Existing true (enabled), Desired false (disabled)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: "Disable AutoDnsSec\n",
|
||||
F: func() error {
|
||||
return autoDNSSecEnable(false, dc.Name)
|
||||
},
|
||||
})
|
||||
printer.Debugf("autoDNSSecEnable: Disable AutoDnsSec for zone %s\n", dc.Name)
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Deletes first, then creates and replaces
|
||||
corrections = append(corrections, lastCorrections...)
|
||||
|
||||
// AutoDnsSec correction
|
||||
existingAutoDNSSecEnabled, err := isAutoDNSSecEnabled(dc.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
desiredAutoDNSSecEnabled := dc.AutoDNSSEC == "on"
|
||||
|
||||
if !existingAutoDNSSecEnabled && desiredAutoDNSSecEnabled {
|
||||
// Existing false (disabled), Desired true (enabled)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: "Enable AutoDnsSec\n",
|
||||
F: func() error {
|
||||
return autoDNSSecEnable(true, dc.Name)
|
||||
},
|
||||
})
|
||||
printer.Debugf("autoDNSSecEnable: Enable AutoDnsSec for zone %s\n", dc.Name)
|
||||
} else if existingAutoDNSSecEnabled && !desiredAutoDNSSecEnabled {
|
||||
// Existing true (enabled), Desired false (disabled)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: "Disable AutoDnsSec\n",
|
||||
F: func() error {
|
||||
return autoDNSSecEnable(false, dc.Name)
|
||||
},
|
||||
})
|
||||
printer.Debugf("autoDNSSecEnable: Disable AutoDnsSec for zone %s\n", dc.Name)
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
|
@ -91,92 +92,98 @@ func (api *autoDNSProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mo
|
|||
models.PostProcessRecords(existingRecords)
|
||||
txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
differ := diff.New(dc)
|
||||
unchanged, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, m := range unchanged {
|
||||
changes = append(changes, m.Desired)
|
||||
}
|
||||
|
||||
for _, m := range del {
|
||||
// Just notify, these records don't have to be deleted explicitly
|
||||
printer.Debugf(m.String())
|
||||
}
|
||||
|
||||
for _, m := range create {
|
||||
printer.Debugf(m.String())
|
||||
changes = append(changes, m.Desired)
|
||||
}
|
||||
|
||||
for _, m := range modify {
|
||||
printer.Debugf("mod")
|
||||
printer.Debugf(m.String())
|
||||
changes = append(changes, m.Desired)
|
||||
}
|
||||
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
if len(create) > 0 || len(del) > 0 || len(modify) > 0 {
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: "Zone update for " + domain,
|
||||
F: func() error {
|
||||
zoneTTL := uint32(0)
|
||||
nameServers := []*models.Nameserver{}
|
||||
resourceRecords := []*ResourceRecord{}
|
||||
differ := diff.New(dc)
|
||||
unchanged, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, record := range changes {
|
||||
// NS records for the APEX should be handled differently
|
||||
if record.Type == "NS" && record.Name == "@" {
|
||||
nameServers = append(nameServers, &models.Nameserver{
|
||||
Name: strings.TrimSuffix(record.GetTargetField(), "."),
|
||||
})
|
||||
for _, m := range unchanged {
|
||||
changes = append(changes, m.Desired)
|
||||
}
|
||||
|
||||
zoneTTL = record.TTL
|
||||
} else {
|
||||
resourceRecord := &ResourceRecord{
|
||||
Name: record.Name,
|
||||
TTL: int64(record.TTL),
|
||||
Type: record.Type,
|
||||
Value: record.GetTargetField(),
|
||||
for _, m := range del {
|
||||
// Just notify, these records don't have to be deleted explicitly
|
||||
printer.Debugf(m.String())
|
||||
}
|
||||
|
||||
for _, m := range create {
|
||||
printer.Debugf(m.String())
|
||||
changes = append(changes, m.Desired)
|
||||
}
|
||||
|
||||
for _, m := range modify {
|
||||
printer.Debugf("mod")
|
||||
printer.Debugf(m.String())
|
||||
changes = append(changes, m.Desired)
|
||||
}
|
||||
|
||||
if len(create) > 0 || len(del) > 0 || len(modify) > 0 {
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: "Zone update for " + domain,
|
||||
F: func() error {
|
||||
zoneTTL := uint32(0)
|
||||
nameServers := []*models.Nameserver{}
|
||||
resourceRecords := []*ResourceRecord{}
|
||||
|
||||
for _, record := range changes {
|
||||
// NS records for the APEX should be handled differently
|
||||
if record.Type == "NS" && record.Name == "@" {
|
||||
nameServers = append(nameServers, &models.Nameserver{
|
||||
Name: strings.TrimSuffix(record.GetTargetField(), "."),
|
||||
})
|
||||
|
||||
zoneTTL = record.TTL
|
||||
} else {
|
||||
resourceRecord := &ResourceRecord{
|
||||
Name: record.Name,
|
||||
TTL: int64(record.TTL),
|
||||
Type: record.Type,
|
||||
Value: record.GetTargetField(),
|
||||
}
|
||||
|
||||
if resourceRecord.Name == "@" {
|
||||
resourceRecord.Name = ""
|
||||
}
|
||||
|
||||
if record.Type == "MX" {
|
||||
resourceRecord.Pref = int32(record.MxPreference)
|
||||
}
|
||||
|
||||
if record.Type == "SRV" {
|
||||
resourceRecord.Value = fmt.Sprintf(
|
||||
"%d %d %d %s",
|
||||
record.SrvPriority,
|
||||
record.SrvWeight,
|
||||
record.SrvPort,
|
||||
record.GetTargetField(),
|
||||
)
|
||||
}
|
||||
|
||||
resourceRecords = append(resourceRecords, resourceRecord)
|
||||
}
|
||||
|
||||
if resourceRecord.Name == "@" {
|
||||
resourceRecord.Name = ""
|
||||
}
|
||||
|
||||
if record.Type == "MX" {
|
||||
resourceRecord.Pref = int32(record.MxPreference)
|
||||
}
|
||||
|
||||
if record.Type == "SRV" {
|
||||
resourceRecord.Value = fmt.Sprintf(
|
||||
"%d %d %d %s",
|
||||
record.SrvPriority,
|
||||
record.SrvWeight,
|
||||
record.SrvPort,
|
||||
record.GetTargetField(),
|
||||
)
|
||||
}
|
||||
|
||||
resourceRecords = append(resourceRecords, resourceRecord)
|
||||
}
|
||||
}
|
||||
|
||||
err := api.updateZone(domain, resourceRecords, nameServers, zoneTTL)
|
||||
err := api.updateZone(domain, resourceRecords, nameServers, zoneTTL)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf(err.Error())
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf(err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
})
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
|
@ -346,100 +347,107 @@ func (c *axfrddnsProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mod
|
|||
models.PostProcessRecords(foundRecords)
|
||||
txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, mod, err := differ.IncrementalDiff(foundRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
// Print a list of changes. Generate an actual change that is the zone
|
||||
changes := false
|
||||
for _, i := range create {
|
||||
changes = true
|
||||
fmt.Fprintln(buf, i)
|
||||
}
|
||||
for _, i := range del {
|
||||
changes = true
|
||||
fmt.Fprintln(buf, i)
|
||||
}
|
||||
for _, i := range mod {
|
||||
changes = true
|
||||
fmt.Fprintln(buf, i)
|
||||
}
|
||||
msg := fmt.Sprintf("DDNS UPDATES to '%s' (primary master: '%s'). Changes:\n%s", dc.Name, c.master, buf)
|
||||
differ := diff.New(dc)
|
||||
_, create, del, mod, err := differ.IncrementalDiff(foundRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corrections := []*models.Correction{}
|
||||
if changes {
|
||||
buf := &bytes.Buffer{}
|
||||
// Print a list of changes. Generate an actual change that is the zone
|
||||
changes := false
|
||||
for _, i := range create {
|
||||
changes = true
|
||||
fmt.Fprintln(buf, i)
|
||||
}
|
||||
for _, i := range del {
|
||||
changes = true
|
||||
fmt.Fprintln(buf, i)
|
||||
}
|
||||
for _, i := range mod {
|
||||
changes = true
|
||||
fmt.Fprintln(buf, i)
|
||||
}
|
||||
msg := fmt.Sprintf("DDNS UPDATES to '%s' (primary master: '%s'). Changes:\n%s", dc.Name, c.master, buf)
|
||||
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
if changes {
|
||||
|
||||
// An RFC2136-compliant server must silently ignore an
|
||||
// update that inserts a non-CNAME RRset when a CNAME RR
|
||||
// with the same name is present in the zone (and
|
||||
// vice-versa). Therefore we prefer to first remove records
|
||||
// and then insert new ones.
|
||||
//
|
||||
// Compliant servers must also silently ignore an update
|
||||
// that removes the last NS record of a zone. Therefore we
|
||||
// don't want to remove all NS records before inserting a
|
||||
// new one. For the particular case of NS record, we prefer
|
||||
// to insert new records before ot remove old ones.
|
||||
//
|
||||
// This remarks does not apply for "modified" NS records, as
|
||||
// updates are processed one-by-one.
|
||||
//
|
||||
// This provider does not allow modifying the TTL of an NS
|
||||
// record in a zone that defines only one NS. That would
|
||||
// would require removing the single NS record, before
|
||||
// adding the new one. But who does that anyway?
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
|
||||
update := new(dns.Msg)
|
||||
update.SetUpdate(dc.Name + ".")
|
||||
update.Id = uint16(c.rand.Intn(math.MaxUint16))
|
||||
for _, c := range create {
|
||||
if c.Desired.Type == "NS" {
|
||||
// An RFC2136-compliant server must silently ignore an
|
||||
// update that inserts a non-CNAME RRset when a CNAME RR
|
||||
// with the same name is present in the zone (and
|
||||
// vice-versa). Therefore we prefer to first remove records
|
||||
// and then insert new ones.
|
||||
//
|
||||
// Compliant servers must also silently ignore an update
|
||||
// that removes the last NS record of a zone. Therefore we
|
||||
// don't want to remove all NS records before inserting a
|
||||
// new one. For the particular case of NS record, we prefer
|
||||
// to insert new records before ot remove old ones.
|
||||
//
|
||||
// This remarks does not apply for "modified" NS records, as
|
||||
// updates are processed one-by-one.
|
||||
//
|
||||
// This provider does not allow modifying the TTL of an NS
|
||||
// record in a zone that defines only one NS. That would
|
||||
// would require removing the single NS record, before
|
||||
// adding the new one. But who does that anyway?
|
||||
|
||||
update := new(dns.Msg)
|
||||
update.SetUpdate(dc.Name + ".")
|
||||
update.Id = uint16(c.rand.Intn(math.MaxUint16))
|
||||
for _, c := range create {
|
||||
if c.Desired.Type == "NS" {
|
||||
update.Insert([]dns.RR{c.Desired.ToRR()})
|
||||
}
|
||||
}
|
||||
for _, c := range del {
|
||||
update.Remove([]dns.RR{c.Existing.ToRR()})
|
||||
}
|
||||
for _, c := range mod {
|
||||
update.Remove([]dns.RR{c.Existing.ToRR()})
|
||||
update.Insert([]dns.RR{c.Desired.ToRR()})
|
||||
}
|
||||
}
|
||||
for _, c := range del {
|
||||
update.Remove([]dns.RR{c.Existing.ToRR()})
|
||||
}
|
||||
for _, c := range mod {
|
||||
update.Remove([]dns.RR{c.Existing.ToRR()})
|
||||
update.Insert([]dns.RR{c.Desired.ToRR()})
|
||||
}
|
||||
for _, c := range create {
|
||||
if c.Desired.Type != "NS" {
|
||||
update.Insert([]dns.RR{c.Desired.ToRR()})
|
||||
for _, c := range create {
|
||||
if c.Desired.Type != "NS" {
|
||||
update.Insert([]dns.RR{c.Desired.ToRR()})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
client := new(dns.Client)
|
||||
client.Net = c.updateMode
|
||||
client.Timeout = dnsTimeout
|
||||
if c.updateKey != nil {
|
||||
client.TsigSecret =
|
||||
map[string]string{c.updateKey.id: c.updateKey.secret}
|
||||
update.SetTsig(c.updateKey.id, c.updateKey.algo, 300, time.Now().Unix())
|
||||
}
|
||||
client := new(dns.Client)
|
||||
client.Net = c.updateMode
|
||||
client.Timeout = dnsTimeout
|
||||
if c.updateKey != nil {
|
||||
client.TsigSecret =
|
||||
map[string]string{c.updateKey.id: c.updateKey.secret}
|
||||
update.SetTsig(c.updateKey.id, c.updateKey.algo, 300, time.Now().Unix())
|
||||
}
|
||||
|
||||
msg, _, err := client.Exchange(update, c.master)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if msg.MsgHdr.Rcode != 0 {
|
||||
return fmt.Errorf("[Error] AXFRDDNS: nameserver refused to update the zone: %s (%d)",
|
||||
dns.RcodeToString[msg.MsgHdr.Rcode],
|
||||
msg.MsgHdr.Rcode)
|
||||
}
|
||||
msg, _, err := client.Exchange(update, c.master)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if msg.MsgHdr.Rcode != 0 {
|
||||
return fmt.Errorf("[Error] AXFRDDNS: nameserver refused to update the zone: %s (%d)",
|
||||
dns.RcodeToString[msg.MsgHdr.Rcode],
|
||||
msg.MsgHdr.Rcode)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
})
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/Azure/go-autorest/autorest/to"
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
|
@ -188,8 +189,6 @@ func (a *azurednsProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mod
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var corrections []*models.Correction
|
||||
|
||||
existingRecords, records, zoneName, err := a.getExistingRecords(dc.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -197,133 +196,141 @@ func (a *azurednsProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mod
|
|||
|
||||
txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
differ := diff.New(dc)
|
||||
namesToUpdate, err := differ.ChangedGroups(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
if len(namesToUpdate) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
updates := map[models.RecordKey][]*models.RecordConfig{}
|
||||
|
||||
for k := range namesToUpdate {
|
||||
updates[k] = nil
|
||||
for _, rc := range dc.Records {
|
||||
if rc.Key() == k {
|
||||
updates[k] = append(updates[k], rc)
|
||||
}
|
||||
differ := diff.New(dc)
|
||||
namesToUpdate, err := differ.ChangedGroups(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for k, recs := range updates {
|
||||
if len(recs) == 0 {
|
||||
var rrset *adns.RecordSet
|
||||
for _, r := range records {
|
||||
if strings.TrimSuffix(*r.Properties.Fqdn, ".") == k.NameFQDN {
|
||||
n1, err := nativeToRecordType(r.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
n2, err := nativeToRecordType(to.StringPtr(k.Type))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n1 == n2 {
|
||||
rrset = r
|
||||
break
|
||||
}
|
||||
if len(namesToUpdate) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
updates := map[models.RecordKey][]*models.RecordConfig{}
|
||||
|
||||
for k := range namesToUpdate {
|
||||
updates[k] = nil
|
||||
for _, rc := range dc.Records {
|
||||
if rc.Key() == k {
|
||||
updates[k] = append(updates[k], rc)
|
||||
}
|
||||
}
|
||||
if rrset != nil {
|
||||
}
|
||||
|
||||
for k, recs := range updates {
|
||||
if len(recs) == 0 {
|
||||
var rrset *adns.RecordSet
|
||||
for _, r := range records {
|
||||
if strings.TrimSuffix(*r.Properties.Fqdn, ".") == k.NameFQDN {
|
||||
n1, err := nativeToRecordType(r.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
n2, err := nativeToRecordType(to.StringPtr(k.Type))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n1 == n2 {
|
||||
rrset = r
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if rrset != nil {
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: strings.Join(namesToUpdate[k], "\n"),
|
||||
F: func() error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 6000*time.Second)
|
||||
defer cancel()
|
||||
rt, err := nativeToRecordType(rrset.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = a.recordsClient.Delete(ctx, *a.resourceGroup, zoneName, *rrset.Name, rt, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
} else {
|
||||
return nil, fmt.Errorf("no record set found to delete. Name: '%s'. Type: '%s'", k.NameFQDN, k.Type)
|
||||
}
|
||||
} else {
|
||||
rrset, recordType, err := a.recordToNative(k, recs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var recordName string
|
||||
for _, r := range recs {
|
||||
i := int64(r.TTL)
|
||||
rrset.Properties.TTL = &i // TODO: make sure that ttls are consistent within a set
|
||||
recordName = r.Name
|
||||
}
|
||||
|
||||
for _, r := range records {
|
||||
existingRecordType, err := nativeToRecordType(r.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
changedRecordType, err := nativeToRecordType(to.StringPtr(k.Type))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if strings.TrimSuffix(*r.Properties.Fqdn, ".") == k.NameFQDN && (changedRecordType == adns.RecordTypeCNAME || existingRecordType == adns.RecordTypeCNAME) {
|
||||
if existingRecordType == adns.RecordTypeA || existingRecordType == adns.RecordTypeAAAA || changedRecordType == adns.RecordTypeA || changedRecordType == adns.RecordTypeAAAA { //CNAME cannot coexist with an A or AA
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: strings.Join(namesToUpdate[k], "\n"),
|
||||
F: func() error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 6000*time.Second)
|
||||
defer cancel()
|
||||
_, err := a.recordsClient.Delete(ctx, *a.resourceGroup, zoneName, recordName, existingRecordType, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: strings.Join(namesToUpdate[k], "\n"),
|
||||
F: func() error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 6000*time.Second)
|
||||
defer cancel()
|
||||
rt, err := nativeToRecordType(rrset.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = a.recordsClient.Delete(ctx, *a.resourceGroup, zoneName, *rrset.Name, rt, nil)
|
||||
_, err := a.recordsClient.CreateOrUpdate(ctx, *a.resourceGroup, zoneName, recordName, recordType, *rrset, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
} else {
|
||||
return nil, fmt.Errorf("no record set found to delete. Name: '%s'. Type: '%s'", k.NameFQDN, k.Type)
|
||||
}
|
||||
} else {
|
||||
rrset, recordType, err := a.recordToNative(k, recs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var recordName string
|
||||
for _, r := range recs {
|
||||
i := int64(r.TTL)
|
||||
rrset.Properties.TTL = &i // TODO: make sure that ttls are consistent within a set
|
||||
recordName = r.Name
|
||||
}
|
||||
|
||||
for _, r := range records {
|
||||
existingRecordType, err := nativeToRecordType(r.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
changedRecordType, err := nativeToRecordType(to.StringPtr(k.Type))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if strings.TrimSuffix(*r.Properties.Fqdn, ".") == k.NameFQDN && (changedRecordType == adns.RecordTypeCNAME || existingRecordType == adns.RecordTypeCNAME) {
|
||||
if existingRecordType == adns.RecordTypeA || existingRecordType == adns.RecordTypeAAAA || changedRecordType == adns.RecordTypeA || changedRecordType == adns.RecordTypeAAAA { //CNAME cannot coexist with an A or AA
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: strings.Join(namesToUpdate[k], "\n"),
|
||||
F: func() error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 6000*time.Second)
|
||||
defer cancel()
|
||||
_, err := a.recordsClient.Delete(ctx, *a.resourceGroup, zoneName, recordName, existingRecordType, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: strings.Join(namesToUpdate[k], "\n"),
|
||||
F: func() error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 6000*time.Second)
|
||||
defer cancel()
|
||||
_, err := a.recordsClient.CreateOrUpdate(ctx, *a.resourceGroup, zoneName, recordName, recordType, *rrset, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Sort the records for cosmetic reasons: It just makes a long list
|
||||
// of deletes or adds easier to read if they are in sorted order.
|
||||
// That said, it may be risky to sort them (sort key is the text
|
||||
// message "Msg") if there are deletes that must happen before adds.
|
||||
// Reading the above code it isn't clear that any of the updates are
|
||||
// order-dependent. That said, all the tests pass.
|
||||
// If in the future this causes a bug, we can either just remove
|
||||
// this next line, or (even better) put any order-dependent
|
||||
// operations in a single models.Correction{}.
|
||||
sort.Slice(corrections, func(i, j int) bool { return diff.CorrectionLess(corrections, i, j) })
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Sort the records for cosmetic reasons: It just makes a long list
|
||||
// of deletes or adds easier to read if they are in sorted order.
|
||||
// That said, it may be risky to sort them (sort key is the text
|
||||
// message "Msg") if there are deletes that must happen before adds.
|
||||
// Reading the above code it isn't clear that any of the updates are
|
||||
// order-dependent. That said, all the tests pass.
|
||||
// If in the future this causes a bug, we can either just remove
|
||||
// this next line, or (even better) put any order-dependent
|
||||
// operations in a single models.Correction{}.
|
||||
sort.Slice(corrections, func(i, j int) bool { return diff.CorrectionLess(corrections, i, j) })
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/prettyzone"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
|
@ -243,72 +244,79 @@ func (c *bindProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.
|
|||
models.PostProcessRecords(foundRecords)
|
||||
txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, mod, err := differ.IncrementalDiff(foundRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
// Print a list of changes. Generate an actual change that is the zone
|
||||
changes := false
|
||||
for _, i := range create {
|
||||
changes = true
|
||||
if c.zoneFileFound {
|
||||
fmt.Fprintln(buf, i)
|
||||
differ := diff.New(dc)
|
||||
_, create, del, mod, err := differ.IncrementalDiff(foundRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for _, i := range del {
|
||||
changes = true
|
||||
if c.zoneFileFound {
|
||||
fmt.Fprintln(buf, i)
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
// Print a list of changes. Generate an actual change that is the zone
|
||||
changes := false
|
||||
for _, i := range create {
|
||||
changes = true
|
||||
if c.zoneFileFound {
|
||||
fmt.Fprintln(buf, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, i := range mod {
|
||||
changes = true
|
||||
if c.zoneFileFound {
|
||||
fmt.Fprintln(buf, i)
|
||||
for _, i := range del {
|
||||
changes = true
|
||||
if c.zoneFileFound {
|
||||
fmt.Fprintln(buf, i)
|
||||
}
|
||||
}
|
||||
for _, i := range mod {
|
||||
changes = true
|
||||
if c.zoneFileFound {
|
||||
fmt.Fprintln(buf, i)
|
||||
}
|
||||
}
|
||||
|
||||
var msg string
|
||||
if c.zoneFileFound {
|
||||
msg = fmt.Sprintf("GENERATE_ZONEFILE: '%s'. Changes:\n%s", dc.Name, buf)
|
||||
} else {
|
||||
msg = fmt.Sprintf("GENERATE_ZONEFILE: '%s' (new file with %d records)\n", dc.Name, len(create))
|
||||
}
|
||||
|
||||
if changes {
|
||||
|
||||
// We only change the serial number if there is a change.
|
||||
desiredSoa.SoaSerial = nextSerial
|
||||
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
printer.Printf("WRITING ZONEFILE: %v\n", c.zonefile)
|
||||
zf, err := os.Create(c.zonefile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create zonefile: %w", err)
|
||||
}
|
||||
// Beware that if there are any fake types, then they will
|
||||
// be commented out on write, but we don't reverse that when
|
||||
// reading, so there will be a diff on every invocation.
|
||||
err = prettyzone.WriteZoneFileRC(zf, dc.Records, dc.Name, 0, comments)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed WriteZoneFile: %w", err)
|
||||
}
|
||||
err = zf.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("closing: %w", err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
var msg string
|
||||
if c.zoneFileFound {
|
||||
msg = fmt.Sprintf("GENERATE_ZONEFILE: '%s'. Changes:\n%s", dc.Name, buf)
|
||||
} else {
|
||||
msg = fmt.Sprintf("GENERATE_ZONEFILE: '%s' (new file with %d records)\n", dc.Name, len(create))
|
||||
}
|
||||
|
||||
corrections := []*models.Correction{}
|
||||
if changes {
|
||||
|
||||
// We only change the serial number if there is a change.
|
||||
desiredSoa.SoaSerial = nextSerial
|
||||
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
printer.Printf("WRITING ZONEFILE: %v\n", c.zonefile)
|
||||
zf, err := os.Create(c.zonefile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create zonefile: %w", err)
|
||||
}
|
||||
// Beware that if there are any fake types, then they will
|
||||
// be commented out on write, but we don't reverse that when
|
||||
// reading, so there will be a diff on every invocation.
|
||||
err = prettyzone.WriteZoneFileRC(zf, dc.Records, dc.Name, 0, comments)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed WriteZoneFile: %w", err)
|
||||
}
|
||||
err = zf.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("closing: %w", err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/transform"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
|
@ -222,99 +223,107 @@ func (c *cloudflareProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*m
|
|||
// Therefore, whether the string is 1 octet or thousands, just store it as
|
||||
// one string in the first element of .TxtStrings.
|
||||
|
||||
differ := diff.New(dc, getProxyMetadata)
|
||||
_, create, del, mod, err := differ.IncrementalDiff(records)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
corrections := []*models.Correction{}
|
||||
differ := diff.New(dc, getProxyMetadata)
|
||||
_, create, del, mod, err := differ.IncrementalDiff(records)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, d := range del {
|
||||
ex := d.Existing
|
||||
if ex.Type == "PAGE_RULE" {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return c.deletePageRule(ex.Original.(cloudflare.PageRule).ID, id) },
|
||||
})
|
||||
} else if ex.Type == "WORKER_ROUTE" {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return c.deleteWorkerRoute(ex.Original.(cloudflare.WorkerRoute).ID, id) },
|
||||
})
|
||||
} else {
|
||||
corr := c.deleteRec(ex.Original.(cloudflare.DNSRecord), id)
|
||||
// DS records must always have a corresponding NS record.
|
||||
// Therefore, we remove DS records before any NS records.
|
||||
if d.Existing.Type == "DS" {
|
||||
corrections = append([]*models.Correction{corr}, corrections...)
|
||||
corrections := []*models.Correction{}
|
||||
|
||||
for _, d := range del {
|
||||
ex := d.Existing
|
||||
if ex.Type == "PAGE_RULE" {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return c.deletePageRule(ex.Original.(cloudflare.PageRule).ID, id) },
|
||||
})
|
||||
} else if ex.Type == "WORKER_ROUTE" {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return c.deleteWorkerRoute(ex.Original.(cloudflare.WorkerRoute).ID, id) },
|
||||
})
|
||||
} else {
|
||||
corrections = append(corrections, corr)
|
||||
corr := c.deleteRec(ex.Original.(cloudflare.DNSRecord), id)
|
||||
// DS records must always have a corresponding NS record.
|
||||
// Therefore, we remove DS records before any NS records.
|
||||
if d.Existing.Type == "DS" {
|
||||
corrections = append([]*models.Correction{corr}, corrections...)
|
||||
} else {
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, d := range create {
|
||||
des := d.Desired
|
||||
if des.Type == "PAGE_RULE" {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return c.createPageRule(id, des.GetTargetField()) },
|
||||
})
|
||||
} else if des.Type == "WORKER_ROUTE" {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return c.createWorkerRoute(id, des.GetTargetField()) },
|
||||
})
|
||||
} else {
|
||||
corr := c.createRec(des, id)
|
||||
// DS records must always have a corresponding NS record.
|
||||
// Therefore, we create NS records before any DS records.
|
||||
if d.Desired.Type == "NS" {
|
||||
corrections = append(corr, corrections...)
|
||||
for _, d := range create {
|
||||
des := d.Desired
|
||||
if des.Type == "PAGE_RULE" {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return c.createPageRule(id, des.GetTargetField()) },
|
||||
})
|
||||
} else if des.Type == "WORKER_ROUTE" {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return c.createWorkerRoute(id, des.GetTargetField()) },
|
||||
})
|
||||
} else {
|
||||
corrections = append(corrections, corr...)
|
||||
corr := c.createRec(des, id)
|
||||
// DS records must always have a corresponding NS record.
|
||||
// Therefore, we create NS records before any DS records.
|
||||
if d.Desired.Type == "NS" {
|
||||
corrections = append(corr, corrections...)
|
||||
} else {
|
||||
corrections = append(corrections, corr...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range mod {
|
||||
rec := d.Desired
|
||||
ex := d.Existing
|
||||
if rec.Type == "PAGE_RULE" {
|
||||
for _, d := range mod {
|
||||
rec := d.Desired
|
||||
ex := d.Existing
|
||||
if rec.Type == "PAGE_RULE" {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return c.updatePageRule(ex.Original.(cloudflare.PageRule).ID, id, rec.GetTargetField()) },
|
||||
})
|
||||
} else if rec.Type == "WORKER_ROUTE" {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error {
|
||||
return c.updateWorkerRoute(ex.Original.(cloudflare.WorkerRoute).ID, id, rec.GetTargetField())
|
||||
},
|
||||
})
|
||||
} else {
|
||||
e := ex.Original.(cloudflare.DNSRecord)
|
||||
proxy := e.Proxiable && rec.Metadata[metaProxy] != "off"
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return c.modifyRecord(id, e.ID, proxy, rec) },
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Add universalSSL change to corrections when needed
|
||||
if changed, newState, err := c.checkUniversalSSL(dc, id); err == nil && changed {
|
||||
var newStateString string
|
||||
if newState {
|
||||
newStateString = "enabled"
|
||||
} else {
|
||||
newStateString = "disabled"
|
||||
}
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return c.updatePageRule(ex.Original.(cloudflare.PageRule).ID, id, rec.GetTargetField()) },
|
||||
})
|
||||
} else if rec.Type == "WORKER_ROUTE" {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error {
|
||||
return c.updateWorkerRoute(ex.Original.(cloudflare.WorkerRoute).ID, id, rec.GetTargetField())
|
||||
},
|
||||
})
|
||||
} else {
|
||||
e := ex.Original.(cloudflare.DNSRecord)
|
||||
proxy := e.Proxiable && rec.Metadata[metaProxy] != "off"
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return c.modifyRecord(id, e.ID, proxy, rec) },
|
||||
Msg: fmt.Sprintf("Universal SSL will be %s for this domain.", newStateString),
|
||||
F: func() error { return c.changeUniversalSSL(id, newState) },
|
||||
})
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Add universalSSL change to corrections when needed
|
||||
if changed, newState, err := c.checkUniversalSSL(dc, id); err == nil && changed {
|
||||
var newStateString string
|
||||
if newState {
|
||||
newStateString = "enabled"
|
||||
} else {
|
||||
newStateString = "disabled"
|
||||
}
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: fmt.Sprintf("Universal SSL will be %s for this domain.", newStateString),
|
||||
F: func() error { return c.changeUniversalSSL(id, newState) },
|
||||
})
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
)
|
||||
|
@ -103,84 +104,90 @@ func (c *cloudnsProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
|||
record.TTL = fixTTL(record.TTL)
|
||||
}
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
// Deletes first so changing type works etc.
|
||||
for _, m := range del {
|
||||
id := m.Existing.Original.(*domainRecord).ID
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, ClouDNS ID: %s", m.String(), id),
|
||||
F: func() error {
|
||||
return c.deleteRecord(domainID, id)
|
||||
},
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// at ClouDNS, we MUST have a NS for a DS
|
||||
// So, when deleting, we must delete the DS first, otherwise deleting the NS throws an error
|
||||
if m.Existing.Type == "DS" {
|
||||
// type DS is prepended - so executed first
|
||||
corrections = append([]*models.Correction{corr}, corrections...)
|
||||
} else {
|
||||
|
||||
// Deletes first so changing type works etc.
|
||||
for _, m := range del {
|
||||
id := m.Existing.Original.(*domainRecord).ID
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, ClouDNS ID: %s", m.String(), id),
|
||||
F: func() error {
|
||||
return c.deleteRecord(domainID, id)
|
||||
},
|
||||
}
|
||||
// at ClouDNS, we MUST have a NS for a DS
|
||||
// So, when deleting, we must delete the DS first, otherwise deleting the NS throws an error
|
||||
if m.Existing.Type == "DS" {
|
||||
// type DS is prepended - so executed first
|
||||
corrections = append([]*models.Correction{corr}, corrections...)
|
||||
} else {
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
}
|
||||
|
||||
var createCorrections []*models.Correction
|
||||
for _, m := range create {
|
||||
req, err := toReq(m.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ClouDNS does not require the trailing period to be specified when creating an NS record where the A or AAAA record exists in the zone.
|
||||
// So, modify it to remove the trailing period.
|
||||
if req["record-type"] == "NS" && strings.HasSuffix(req["record"], domainID+".") {
|
||||
req["record"] = strings.TrimSuffix(req["record"], ".")
|
||||
}
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
return c.createRecord(domainID, req)
|
||||
},
|
||||
}
|
||||
// at ClouDNS, we MUST have a NS for a DS
|
||||
// So, when creating, we must create the NS first, otherwise creating the DS throws an error
|
||||
if m.Desired.Type == "NS" {
|
||||
// type NS is prepended - so executed first
|
||||
createCorrections = append([]*models.Correction{corr}, createCorrections...)
|
||||
} else {
|
||||
createCorrections = append(createCorrections, corr)
|
||||
}
|
||||
}
|
||||
corrections = append(corrections, createCorrections...)
|
||||
|
||||
for _, m := range modify {
|
||||
id := m.Existing.Original.(*domainRecord).ID
|
||||
req, err := toReq(m.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ClouDNS does not require the trailing period to be specified when updating an NS record where the A or AAAA record exists in the zone.
|
||||
// So, modify it to remove the trailing period.
|
||||
if req["record-type"] == "NS" && strings.HasSuffix(req["record"], domainID+".") {
|
||||
req["record"] = strings.TrimSuffix(req["record"], ".")
|
||||
}
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, ClouDNS ID: %s: ", m.String(), id),
|
||||
F: func() error {
|
||||
return c.modifyRecord(domainID, id, req)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
var createCorrections []*models.Correction
|
||||
for _, m := range create {
|
||||
req, err := toReq(m.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ClouDNS does not require the trailing period to be specified when creating an NS record where the A or AAAA record exists in the zone.
|
||||
// So, modify it to remove the trailing period.
|
||||
if req["record-type"] == "NS" && strings.HasSuffix(req["record"], domainID+".") {
|
||||
req["record"] = strings.TrimSuffix(req["record"], ".")
|
||||
}
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
return c.createRecord(domainID, req)
|
||||
},
|
||||
}
|
||||
// at ClouDNS, we MUST have a NS for a DS
|
||||
// So, when creating, we must create the NS first, otherwise creating the DS throws an error
|
||||
if m.Desired.Type == "NS" {
|
||||
// type NS is prepended - so executed first
|
||||
createCorrections = append([]*models.Correction{corr}, createCorrections...)
|
||||
} else {
|
||||
createCorrections = append(createCorrections, corr)
|
||||
}
|
||||
}
|
||||
corrections = append(corrections, createCorrections...)
|
||||
|
||||
for _, m := range modify {
|
||||
id := m.Existing.Original.(*domainRecord).ID
|
||||
req, err := toReq(m.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ClouDNS does not require the trailing period to be specified when updating an NS record where the A or AAAA record exists in the zone.
|
||||
// So, modify it to remove the trailing period.
|
||||
if req["record-type"] == "NS" && strings.HasSuffix(req["record"], domainID+".") {
|
||||
req["record"] = strings.TrimSuffix(req["record"], ".")
|
||||
}
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, ClouDNS ID: %s: ", m.String(), id),
|
||||
F: func() error {
|
||||
return c.modifyRecord(domainID, id, req)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
)
|
||||
|
||||
// GetZoneRecords gets the records of a zone and returns them in RecordConfig format.
|
||||
|
@ -116,74 +117,82 @@ func (client *providerClient) GenerateDomainCorrections(dc *models.DomainConfig,
|
|||
models.PostProcessRecords(foundRecords)
|
||||
//txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, creates, dels, modifications, err := differ.IncrementalDiff(foundRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
// How to generate corrections?
|
||||
|
||||
// (1) Most providers take individual deletes, creates, and
|
||||
// modifications:
|
||||
|
||||
// // Generate changes.
|
||||
// corrections := []*models.Correction{}
|
||||
// for _, del := range dels {
|
||||
// corrections = append(corrections, client.deleteRec(client.dnsserver, dc.Name, del))
|
||||
// }
|
||||
// for _, cre := range creates {
|
||||
// corrections = append(corrections, client.createRec(client.dnsserver, dc.Name, cre)...)
|
||||
// }
|
||||
// for _, m := range modifications {
|
||||
// corrections = append(corrections, client.modifyRec(client.dnsserver, dc.Name, m))
|
||||
// }
|
||||
// return corrections, nil
|
||||
|
||||
// (2) Some providers upload the entire zone every time. Look at
|
||||
// GetDomainCorrections for BIND and NAMECHEAP for inspiration.
|
||||
|
||||
// (3) Others do something entirely different. Like CSCGlobal:
|
||||
|
||||
// CSCGlobal has a unique API. A list of edits is sent in one API
|
||||
// call. Edits aren't permitted if an existing edit is being
|
||||
// processed. Therefore, before we do an edit we block until the
|
||||
// previous edit is done executing.
|
||||
|
||||
var edits []zoneResourceRecordEdit
|
||||
var descriptions []string
|
||||
for _, del := range dels {
|
||||
edits = append(edits, makePurge(dc.Name, del))
|
||||
descriptions = append(descriptions, del.String())
|
||||
}
|
||||
for _, cre := range creates {
|
||||
edits = append(edits, makeAdd(dc.Name, cre))
|
||||
descriptions = append(descriptions, cre.String())
|
||||
}
|
||||
for _, m := range modifications {
|
||||
edits = append(edits, makeEdit(dc.Name, m))
|
||||
descriptions = append(descriptions, m.String())
|
||||
}
|
||||
corrections := []*models.Correction{}
|
||||
if len(edits) > 0 {
|
||||
c := &models.Correction{
|
||||
Msg: "\t" + strings.Join(descriptions, "\n\t"),
|
||||
F: func() error {
|
||||
// CSCGlobal's API only permits one pending update at a time.
|
||||
// Therefore we block until any outstanding updates are done.
|
||||
// We also clear out any failures, since (and I can't believe
|
||||
// I'm writing this) any time something fails, the failure has
|
||||
// to be cleared out with an additional API call.
|
||||
|
||||
err := client.clearRequests(dc.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return client.sendZoneEditRequest(dc.Name, edits)
|
||||
},
|
||||
differ := diff.New(dc)
|
||||
_, creates, dels, modifications, err := differ.IncrementalDiff(foundRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corrections = append(corrections, c)
|
||||
|
||||
// How to generate corrections?
|
||||
|
||||
// (1) Most providers take individual deletes, creates, and
|
||||
// modifications:
|
||||
|
||||
// // Generate changes.
|
||||
// corrections := []*models.Correction{}
|
||||
// for _, del := range dels {
|
||||
// corrections = append(corrections, client.deleteRec(client.dnsserver, dc.Name, del))
|
||||
// }
|
||||
// for _, cre := range creates {
|
||||
// corrections = append(corrections, client.createRec(client.dnsserver, dc.Name, cre)...)
|
||||
// }
|
||||
// for _, m := range modifications {
|
||||
// corrections = append(corrections, client.modifyRec(client.dnsserver, dc.Name, m))
|
||||
// }
|
||||
// return corrections, nil
|
||||
|
||||
// (2) Some providers upload the entire zone every time. Look at
|
||||
// GetDomainCorrections for BIND and NAMECHEAP for inspiration.
|
||||
|
||||
// (3) Others do something entirely different. Like CSCGlobal:
|
||||
|
||||
// CSCGlobal has a unique API. A list of edits is sent in one API
|
||||
// call. Edits aren't permitted if an existing edit is being
|
||||
// processed. Therefore, before we do an edit we block until the
|
||||
// previous edit is done executing.
|
||||
|
||||
var edits []zoneResourceRecordEdit
|
||||
var descriptions []string
|
||||
for _, del := range dels {
|
||||
edits = append(edits, makePurge(dc.Name, del))
|
||||
descriptions = append(descriptions, del.String())
|
||||
}
|
||||
for _, cre := range creates {
|
||||
edits = append(edits, makeAdd(dc.Name, cre))
|
||||
descriptions = append(descriptions, cre.String())
|
||||
}
|
||||
for _, m := range modifications {
|
||||
edits = append(edits, makeEdit(dc.Name, m))
|
||||
descriptions = append(descriptions, m.String())
|
||||
}
|
||||
corrections := []*models.Correction{}
|
||||
if len(edits) > 0 {
|
||||
c := &models.Correction{
|
||||
Msg: "\t" + strings.Join(descriptions, "\n\t"),
|
||||
F: func() error {
|
||||
// CSCGlobal's API only permits one pending update at a time.
|
||||
// Therefore we block until any outstanding updates are done.
|
||||
// We also clear out any failures, since (and I can't believe
|
||||
// I'm writing this) any time something fails, the failure has
|
||||
// to be cleared out with an additional API call.
|
||||
|
||||
err := client.clearRequests(dc.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return client.sendZoneEditRequest(dc.Name, edits)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, c)
|
||||
}
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
|
@ -164,82 +165,88 @@ func PrepDesiredRecords(dc *models.DomainConfig, minTTL uint32) {
|
|||
// made.
|
||||
func (c *desecProvider) GenerateDomainCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, error) {
|
||||
|
||||
var corrections = []*models.Correction{}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
// diff existing vs. current.
|
||||
differ := diff.New(dc)
|
||||
keysToUpdate, err := differ.ChangedGroups(existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(keysToUpdate) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
// diff existing vs. current.
|
||||
differ := diff.New(dc)
|
||||
keysToUpdate, err := differ.ChangedGroups(existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(keysToUpdate) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
desiredRecords := dc.Records.GroupedByKey()
|
||||
var rrs []resourceRecord
|
||||
buf := &bytes.Buffer{}
|
||||
// For any key with an update, delete or replace those records.
|
||||
for label := range keysToUpdate {
|
||||
if _, ok := desiredRecords[label]; !ok {
|
||||
//we could not find this RecordKey in the desiredRecords
|
||||
//this means it must be deleted
|
||||
for i, msg := range keysToUpdate[label] {
|
||||
if i == 0 {
|
||||
rc := resourceRecord{}
|
||||
rc.Type = label.Type
|
||||
rc.Records = make([]string, 0) // empty array of records should delete this rrset
|
||||
rc.TTL = 3600
|
||||
shortname := dnsutil.TrimDomainName(label.NameFQDN, dc.Name)
|
||||
if shortname == "@" {
|
||||
shortname = ""
|
||||
desiredRecords := dc.Records.GroupedByKey()
|
||||
var rrs []resourceRecord
|
||||
buf := &bytes.Buffer{}
|
||||
// For any key with an update, delete or replace those records.
|
||||
for label := range keysToUpdate {
|
||||
if _, ok := desiredRecords[label]; !ok {
|
||||
//we could not find this RecordKey in the desiredRecords
|
||||
//this means it must be deleted
|
||||
for i, msg := range keysToUpdate[label] {
|
||||
if i == 0 {
|
||||
rc := resourceRecord{}
|
||||
rc.Type = label.Type
|
||||
rc.Records = make([]string, 0) // empty array of records should delete this rrset
|
||||
rc.TTL = 3600
|
||||
shortname := dnsutil.TrimDomainName(label.NameFQDN, dc.Name)
|
||||
if shortname == "@" {
|
||||
shortname = ""
|
||||
}
|
||||
rc.Subname = shortname
|
||||
fmt.Fprintln(buf, msg)
|
||||
rrs = append(rrs, rc)
|
||||
} else {
|
||||
//just add the message
|
||||
fmt.Fprintln(buf, msg)
|
||||
}
|
||||
rc.Subname = shortname
|
||||
fmt.Fprintln(buf, msg)
|
||||
rrs = append(rrs, rc)
|
||||
} else {
|
||||
//just add the message
|
||||
fmt.Fprintln(buf, msg)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//it must be an update or create, both can be done with the same api call.
|
||||
ns := recordsToNative(desiredRecords[label], dc.Name)
|
||||
if len(ns) > 1 {
|
||||
panic("we got more than one resource record to create / modify")
|
||||
}
|
||||
for i, msg := range keysToUpdate[label] {
|
||||
if i == 0 {
|
||||
rrs = append(rrs, ns[0])
|
||||
fmt.Fprintln(buf, msg)
|
||||
} else {
|
||||
//noop just for printing the additional messages
|
||||
fmt.Fprintln(buf, msg)
|
||||
} else {
|
||||
//it must be an update or create, both can be done with the same api call.
|
||||
ns := recordsToNative(desiredRecords[label], dc.Name)
|
||||
if len(ns) > 1 {
|
||||
panic("we got more than one resource record to create / modify")
|
||||
}
|
||||
for i, msg := range keysToUpdate[label] {
|
||||
if i == 0 {
|
||||
rrs = append(rrs, ns[0])
|
||||
fmt.Fprintln(buf, msg)
|
||||
} else {
|
||||
//noop just for printing the additional messages
|
||||
fmt.Fprintln(buf, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
msg := fmt.Sprintf("Changes:\n%s", buf)
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
rc := rrs
|
||||
err := c.upsertRR(rc, dc.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
msg := fmt.Sprintf("Changes:\n%s", buf)
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
rc := rrs
|
||||
err := c.upsertRR(rc, dc.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
// NB(tlim): This sort is just to make updates look pretty. It is
|
||||
// cosmetic. The risk here is that there may be some updates that
|
||||
// require a specific order (for example a delete before an add).
|
||||
// However the code doesn't seem to have such situation. All tests
|
||||
// pass. That said, if this breaks anything, the easiest fix might
|
||||
// be to just remove the sort.
|
||||
sort.Slice(corrections, func(i, j int) bool { return diff.CorrectionLess(corrections, i, j) })
|
||||
// NB(tlim): This sort is just to make updates look pretty. It is
|
||||
// cosmetic. The risk here is that there may be some updates that
|
||||
// require a specific order (for example a delete before an add).
|
||||
// However the code doesn't seem to have such situation. All tests
|
||||
// pass. That said, if this breaks anything, the easiest fix might
|
||||
// be to just remove the sort.
|
||||
sort.Slice(corrections, func(i, j int) bool { return diff.CorrectionLess(corrections, i, j) })
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
"github.com/digitalocean/godo"
|
||||
|
@ -145,67 +146,73 @@ func (api *digitaloceanProvider) GetDomainCorrections(dc *models.DomainConfig) (
|
|||
models.PostProcessRecords(existingRecords)
|
||||
txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Deletes first so changing type works etc.
|
||||
for _, m := range delete {
|
||||
id := m.Existing.Original.(*godo.DomainRecord).ID
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, DO ID: %d", m.String(), id),
|
||||
F: func() error {
|
||||
retry:
|
||||
resp, err := api.client.Domains.DeleteRecord(ctx, dc.Name, id)
|
||||
if err != nil {
|
||||
if pauseAndRetry(resp) {
|
||||
goto retry
|
||||
}
|
||||
}
|
||||
return err
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
for _, m := range create {
|
||||
req := toReq(dc, m.Desired)
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
retry:
|
||||
_, resp, err := api.client.Domains.CreateRecord(ctx, dc.Name, req)
|
||||
if err != nil {
|
||||
if pauseAndRetry(resp) {
|
||||
goto retry
|
||||
}
|
||||
}
|
||||
return err
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
for _, m := range modify {
|
||||
id := m.Existing.Original.(*godo.DomainRecord).ID
|
||||
req := toReq(dc, m.Desired)
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, DO ID: %d", m.String(), id),
|
||||
F: func() error {
|
||||
retry:
|
||||
_, resp, err := api.client.Domains.EditRecord(ctx, dc.Name, id, req)
|
||||
if err != nil {
|
||||
if pauseAndRetry(resp) {
|
||||
goto retry
|
||||
}
|
||||
}
|
||||
return err
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
var corrections = []*models.Correction{}
|
||||
|
||||
// Deletes first so changing type works etc.
|
||||
for _, m := range delete {
|
||||
id := m.Existing.Original.(*godo.DomainRecord).ID
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, DO ID: %d", m.String(), id),
|
||||
F: func() error {
|
||||
retry:
|
||||
resp, err := api.client.Domains.DeleteRecord(ctx, dc.Name, id)
|
||||
if err != nil {
|
||||
if pauseAndRetry(resp) {
|
||||
goto retry
|
||||
}
|
||||
}
|
||||
return err
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
for _, m := range create {
|
||||
req := toReq(dc, m.Desired)
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
retry:
|
||||
_, resp, err := api.client.Domains.CreateRecord(ctx, dc.Name, req)
|
||||
if err != nil {
|
||||
if pauseAndRetry(resp) {
|
||||
goto retry
|
||||
}
|
||||
}
|
||||
return err
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
for _, m := range modify {
|
||||
id := m.Existing.Original.(*godo.DomainRecord).ID
|
||||
req := toReq(dc, m.Desired)
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, DO ID: %d", m.String(), id),
|
||||
F: func() error {
|
||||
retry:
|
||||
_, resp, err := api.client.Domains.EditRecord(ctx, dc.Name, id, req)
|
||||
if err != nil {
|
||||
if pauseAndRetry(resp) {
|
||||
goto retry
|
||||
}
|
||||
}
|
||||
return err
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
dnsimpleapi "github.com/dnsimple/dnsimple-go/dnsimple"
|
||||
|
@ -141,6 +142,7 @@ func (c *dnsimpleProvider) GetZoneRecords(domain string) (models.Records, error)
|
|||
// GetDomainCorrections returns corrections that update a domain.
|
||||
func (c *dnsimpleProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||
var corrections []*models.Correction
|
||||
|
||||
err := dc.Punycode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -163,36 +165,43 @@ func (c *dnsimpleProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mod
|
|||
// Normalize
|
||||
models.PostProcessRecords(actual)
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(actual)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(actual)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, del := range del {
|
||||
rec := del.Existing.Original.(dnsimpleapi.ZoneRecord)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: del.String(),
|
||||
F: c.deleteRecordFunc(rec.ID, dc.Name),
|
||||
})
|
||||
}
|
||||
|
||||
for _, cre := range create {
|
||||
rec := cre.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: cre.String(),
|
||||
F: c.createRecordFunc(rec, dc.Name),
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range modify {
|
||||
old := mod.Existing.Original.(dnsimpleapi.ZoneRecord)
|
||||
rec := mod.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: mod.String(),
|
||||
F: c.updateRecordFunc(&old, rec, dc.Name),
|
||||
})
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
for _, del := range del {
|
||||
rec := del.Existing.Original.(dnsimpleapi.ZoneRecord)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: del.String(),
|
||||
F: c.deleteRecordFunc(rec.ID, dc.Name),
|
||||
})
|
||||
}
|
||||
|
||||
for _, cre := range create {
|
||||
rec := cre.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: cre.String(),
|
||||
F: c.createRecordFunc(rec, dc.Name),
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range modify {
|
||||
old := mod.Existing.Original.(dnsimpleapi.ZoneRecord)
|
||||
rec := mod.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: mod.String(),
|
||||
F: c.updateRecordFunc(&old, rec, dc.Name),
|
||||
})
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
)
|
||||
|
@ -100,73 +101,79 @@ func (api *dnsMadeEasyProvider) GetDomainCorrections(dc *models.DomainConfig) ([
|
|||
models.PostProcessRecords(existingRecords)
|
||||
txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
var deleteRecordIds []int
|
||||
deleteDescription := []string{"Batch deletion of records:"}
|
||||
for _, m := range del {
|
||||
originalRecordID := m.Existing.Original.(*recordResponseDataEntry).ID
|
||||
deleteRecordIds = append(deleteRecordIds, originalRecordID)
|
||||
deleteDescription = append(deleteDescription, m.String())
|
||||
}
|
||||
|
||||
if len(deleteRecordIds) > 0 {
|
||||
corr := &models.Correction{
|
||||
Msg: strings.Join(deleteDescription, "\n\t"),
|
||||
F: func() error {
|
||||
return api.deleteRecords(domain.ID, deleteRecordIds)
|
||||
},
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
var createRecords []recordRequestData
|
||||
createDescription := []string{"Batch creation of records:"}
|
||||
for _, m := range create {
|
||||
record := fromRecordConfig(m.Desired)
|
||||
createRecords = append(createRecords, *record)
|
||||
createDescription = append(createDescription, m.String())
|
||||
}
|
||||
|
||||
if len(createRecords) > 0 {
|
||||
corr := &models.Correction{
|
||||
Msg: strings.Join(createDescription, "\n\t"),
|
||||
F: func() error {
|
||||
return api.createRecords(domain.ID, createRecords)
|
||||
},
|
||||
var deleteRecordIds []int
|
||||
deleteDescription := []string{"Batch deletion of records:"}
|
||||
for _, m := range del {
|
||||
originalRecordID := m.Existing.Original.(*recordResponseDataEntry).ID
|
||||
deleteRecordIds = append(deleteRecordIds, originalRecordID)
|
||||
deleteDescription = append(deleteDescription, m.String())
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
var modifyRecords []recordRequestData
|
||||
modifyDescription := []string{"Batch modification of records:"}
|
||||
for _, m := range modify {
|
||||
originalRecord := m.Existing.Original.(*recordResponseDataEntry)
|
||||
|
||||
record := fromRecordConfig(m.Desired)
|
||||
record.ID = originalRecord.ID
|
||||
record.GtdLocation = originalRecord.GtdLocation
|
||||
|
||||
modifyRecords = append(modifyRecords, *record)
|
||||
modifyDescription = append(modifyDescription, m.String())
|
||||
}
|
||||
|
||||
if len(modifyRecords) > 0 {
|
||||
corr := &models.Correction{
|
||||
Msg: strings.Join(modifyDescription, "\n\t"),
|
||||
F: func() error {
|
||||
return api.updateRecords(domain.ID, modifyRecords)
|
||||
},
|
||||
if len(deleteRecordIds) > 0 {
|
||||
corr := &models.Correction{
|
||||
Msg: strings.Join(deleteDescription, "\n\t"),
|
||||
F: func() error {
|
||||
return api.deleteRecords(domain.ID, deleteRecordIds)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
|
||||
var createRecords []recordRequestData
|
||||
createDescription := []string{"Batch creation of records:"}
|
||||
for _, m := range create {
|
||||
record := fromRecordConfig(m.Desired)
|
||||
createRecords = append(createRecords, *record)
|
||||
createDescription = append(createDescription, m.String())
|
||||
}
|
||||
|
||||
if len(createRecords) > 0 {
|
||||
corr := &models.Correction{
|
||||
Msg: strings.Join(createDescription, "\n\t"),
|
||||
F: func() error {
|
||||
return api.createRecords(domain.ID, createRecords)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
var modifyRecords []recordRequestData
|
||||
modifyDescription := []string{"Batch modification of records:"}
|
||||
for _, m := range modify {
|
||||
originalRecord := m.Existing.Original.(*recordResponseDataEntry)
|
||||
|
||||
record := fromRecordConfig(m.Desired)
|
||||
record.ID = originalRecord.ID
|
||||
record.GtdLocation = originalRecord.GtdLocation
|
||||
|
||||
modifyRecords = append(modifyRecords, *record)
|
||||
modifyDescription = append(modifyDescription, m.String())
|
||||
}
|
||||
|
||||
if len(modifyRecords) > 0 {
|
||||
corr := &models.Correction{
|
||||
Msg: strings.Join(modifyDescription, "\n\t"),
|
||||
F: func() error {
|
||||
return api.updateRecords(domain.ID, modifyRecords)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
)
|
||||
|
||||
func (api *domainNameShopProvider) GetZoneRecords(domain string) (models.Records, error) {
|
||||
|
@ -46,61 +47,67 @@ func (api *domainNameShopProvider) GetDomainCorrections(dc *models.DomainConfig)
|
|||
record.TTL = fixTTL(record.TTL)
|
||||
}
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
var corrections = []*models.Correction{}
|
||||
|
||||
// Delete record
|
||||
for _, r := range delete {
|
||||
domainID := r.Existing.Original.(*domainNameShopRecord).DomainID
|
||||
recordID := strconv.Itoa(r.Existing.Original.(*domainNameShopRecord).ID)
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, record id: %s", r.String(), recordID),
|
||||
F: func() error { return api.deleteRecord(domainID, recordID) },
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
// Create records
|
||||
for _, r := range create {
|
||||
// Retrieve the domain name that is targeted. I.e. example.com instead of sub.example.com
|
||||
domainName := strings.Replace(r.Desired.GetLabelFQDN(), r.Desired.GetLabel()+".", "", -1)
|
||||
|
||||
dnsR, err := api.fromRecordConfig(domainName, r.Desired)
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: r.String(),
|
||||
F: func() error { return api.CreateRecord(domainName, dnsR) },
|
||||
// Delete record
|
||||
for _, r := range delete {
|
||||
domainID := r.Existing.Original.(*domainNameShopRecord).DomainID
|
||||
recordID := strconv.Itoa(r.Existing.Original.(*domainNameShopRecord).ID)
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, record id: %s", r.String(), recordID),
|
||||
F: func() error { return api.deleteRecord(domainID, recordID) },
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
corrections = append(corrections, corr)
|
||||
// Create records
|
||||
for _, r := range create {
|
||||
// Retrieve the domain name that is targeted. I.e. example.com instead of sub.example.com
|
||||
domainName := strings.Replace(r.Desired.GetLabelFQDN(), r.Desired.GetLabel()+".", "", -1)
|
||||
|
||||
dnsR, err := api.fromRecordConfig(domainName, r.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: r.String(),
|
||||
F: func() error { return api.CreateRecord(domainName, dnsR) },
|
||||
}
|
||||
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
for _, r := range modify {
|
||||
domainName := strings.Replace(r.Desired.GetLabelFQDN(), r.Desired.GetLabel()+".", "", -1)
|
||||
|
||||
dnsR, err := api.fromRecordConfig(domainName, r.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dnsR.ID = r.Existing.Original.(*domainNameShopRecord).ID
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: r.String(),
|
||||
F: func() error { return api.UpdateRecord(dnsR) },
|
||||
}
|
||||
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
for _, r := range modify {
|
||||
domainName := strings.Replace(r.Desired.GetLabelFQDN(), r.Desired.GetLabel()+".", "", -1)
|
||||
|
||||
dnsR, err := api.fromRecordConfig(domainName, r.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dnsR.ID = r.Existing.Original.(*domainNameShopRecord).ID
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: r.String(),
|
||||
F: func() error { return api.UpdateRecord(dnsR) },
|
||||
}
|
||||
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
)
|
||||
|
@ -189,38 +190,44 @@ func (c *exoscaleProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mod
|
|||
// Normalize
|
||||
models.PostProcessRecords(existingRecords)
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, del := range delete {
|
||||
record := del.Existing.Original.(*egoscale.DNSDomainRecord)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: del.String(),
|
||||
F: c.deleteRecordFunc(*record.ID, domainID),
|
||||
})
|
||||
}
|
||||
|
||||
for _, cre := range create {
|
||||
rc := cre.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: cre.String(),
|
||||
F: c.createRecordFunc(rc, domainID),
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range modify {
|
||||
old := mod.Existing.Original.(*egoscale.DNSDomainRecord)
|
||||
new := mod.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: mod.String(),
|
||||
F: c.updateRecordFunc(old, new, domainID),
|
||||
})
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
var corrections = []*models.Correction{}
|
||||
|
||||
for _, del := range delete {
|
||||
record := del.Existing.Original.(*egoscale.DNSDomainRecord)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: del.String(),
|
||||
F: c.deleteRecordFunc(*record.ID, domainID),
|
||||
})
|
||||
}
|
||||
|
||||
for _, cre := range create {
|
||||
rc := cre.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: cre.String(),
|
||||
F: c.createRecordFunc(rc, domainID),
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range modify {
|
||||
old := mod.Existing.Original.(*egoscale.DNSDomainRecord)
|
||||
new := mod.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: mod.String(),
|
||||
F: c.updateRecordFunc(old, new, domainID),
|
||||
})
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
|
@ -226,113 +227,119 @@ func (client *gandiv5Provider) GenerateDomainCorrections(dc *models.DomainConfig
|
|||
debugRecords("GenDC input", existing)
|
||||
}
|
||||
|
||||
var corrections = []*models.Correction{}
|
||||
|
||||
txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
// diff existing vs. current.
|
||||
differ := diff.New(dc)
|
||||
keysToUpdate, err := differ.ChangedGroups(existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if client.debug {
|
||||
diff.DebugKeyMapMap("GenDC diff", keysToUpdate)
|
||||
}
|
||||
if len(keysToUpdate) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
// Regroup data by FQDN. ChangedGroups returns data grouped by label:RType tuples.
|
||||
affectedLabels, msgsForLabel := gatherAffectedLabels(keysToUpdate)
|
||||
_, desiredRecords := dc.Records.GroupedByFQDN()
|
||||
doesLabelExist := existing.FQDNMap()
|
||||
// diff existing vs. current.
|
||||
differ := diff.New(dc)
|
||||
keysToUpdate, err := differ.ChangedGroups(existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if client.debug {
|
||||
diff.DebugKeyMapMap("GenDC diff", keysToUpdate)
|
||||
}
|
||||
if len(keysToUpdate) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
g := gandi.NewLiveDNSClient(config.Config{
|
||||
APIKey: client.apikey,
|
||||
SharingID: client.sharingid,
|
||||
Debug: client.debug,
|
||||
})
|
||||
// Regroup data by FQDN. ChangedGroups returns data grouped by label:RType tuples.
|
||||
affectedLabels, msgsForLabel := gatherAffectedLabels(keysToUpdate)
|
||||
_, desiredRecords := dc.Records.GroupedByFQDN()
|
||||
doesLabelExist := existing.FQDNMap()
|
||||
|
||||
// For any key with an update, delete or replace those records.
|
||||
for label := range affectedLabels {
|
||||
if len(desiredRecords[label]) == 0 {
|
||||
// No records matching this key? This can only mean that all
|
||||
// the records were deleted. Delete them.
|
||||
g := gandi.NewLiveDNSClient(config.Config{
|
||||
APIKey: client.apikey,
|
||||
SharingID: client.sharingid,
|
||||
Debug: client.debug,
|
||||
})
|
||||
|
||||
msgs := strings.Join(msgsForLabel[label], "\n")
|
||||
domain := dc.Name
|
||||
shortname := dnsutil.TrimDomainName(label, dc.Name)
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: msgs,
|
||||
F: func() error {
|
||||
err := g.DeleteDomainRecordsByName(domain, shortname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
// For any key with an update, delete or replace those records.
|
||||
for label := range affectedLabels {
|
||||
if len(desiredRecords[label]) == 0 {
|
||||
// No records matching this key? This can only mean that all
|
||||
// the records were deleted. Delete them.
|
||||
|
||||
} else {
|
||||
// Replace all the records at a label with our new records.
|
||||
|
||||
// Generate the new data in Gandi's format.
|
||||
ns := recordsToNative(desiredRecords[label], dc.Name)
|
||||
|
||||
if doesLabelExist[label] {
|
||||
// Records exist for this label. Replace them with what we have.
|
||||
|
||||
msg := strings.Join(msgsForLabel[label], "\n")
|
||||
msgs := strings.Join(msgsForLabel[label], "\n")
|
||||
domain := dc.Name
|
||||
shortname := dnsutil.TrimDomainName(label, dc.Name)
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: msg,
|
||||
Msg: msgs,
|
||||
F: func() error {
|
||||
res, err := g.UpdateDomainRecordsByName(domain, shortname, ns)
|
||||
err := g.DeleteDomainRecordsByName(domain, shortname)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%+v: %w", res, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
} else {
|
||||
// First time putting data on this label. Create it.
|
||||
// Replace all the records at a label with our new records.
|
||||
|
||||
// Generate the new data in Gandi's format.
|
||||
ns := recordsToNative(desiredRecords[label], dc.Name)
|
||||
|
||||
if doesLabelExist[label] {
|
||||
// Records exist for this label. Replace them with what we have.
|
||||
|
||||
// We have to create the label one rtype at a time.
|
||||
for _, n := range ns {
|
||||
msg := strings.Join(msgsForLabel[label], "\n")
|
||||
domain := dc.Name
|
||||
shortname := dnsutil.TrimDomainName(label, dc.Name)
|
||||
rtype := n.RrsetType
|
||||
ttl := n.RrsetTTL
|
||||
values := n.RrsetValues
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
res, err := g.CreateDomainRecord(domain, shortname, rtype, ttl, values)
|
||||
res, err := g.UpdateDomainRecordsByName(domain, shortname, ns)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%+v: %w", res, err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
} else {
|
||||
// First time putting data on this label. Create it.
|
||||
|
||||
// We have to create the label one rtype at a time.
|
||||
for _, n := range ns {
|
||||
msg := strings.Join(msgsForLabel[label], "\n")
|
||||
domain := dc.Name
|
||||
shortname := dnsutil.TrimDomainName(label, dc.Name)
|
||||
rtype := n.RrsetType
|
||||
ttl := n.RrsetTTL
|
||||
values := n.RrsetValues
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
res, err := g.CreateDomainRecord(domain, shortname, rtype, ttl, values)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%+v: %w", res, err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NB(tlim): This sort is just to make updates look pretty. It is
|
||||
// cosmetic. The risk here is that there may be some updates that
|
||||
// require a specific order (for example a delete before an add).
|
||||
// However the code doesn't seem to have such situation. All tests
|
||||
// pass. That said, if this breaks anything, the easiest fix might
|
||||
// be to just remove the sort.
|
||||
sort.Slice(corrections, func(i, j int) bool { return diff.CorrectionLess(corrections, i, j) })
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// NB(tlim): This sort is just to make updates look pretty. It is
|
||||
// cosmetic. The risk here is that there may be some updates that
|
||||
// require a specific order (for example a delete before an add).
|
||||
// However the code doesn't seem to have such situation. All tests
|
||||
// pass. That said, if this breaks anything, the easiest fix might
|
||||
// be to just remove the sort.
|
||||
sort.Slice(corrections, func(i, j int) bool { return diff.CorrectionLess(corrections, i, j) })
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
|
@ -204,77 +205,85 @@ func (g *gcloudProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*model
|
|||
models.PostProcessRecords(existingRecords)
|
||||
txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
// first collect keys that have changed
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("incdiff error: %w", err)
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
changedKeys := map[key]bool{}
|
||||
desc := ""
|
||||
for _, c := range create {
|
||||
desc += fmt.Sprintln(c)
|
||||
changedKeys[keyForRec(c.Desired)] = true
|
||||
}
|
||||
for _, d := range delete {
|
||||
desc += fmt.Sprintln(d)
|
||||
changedKeys[keyForRec(d.Existing)] = true
|
||||
}
|
||||
for _, m := range modify {
|
||||
desc += fmt.Sprintln(m)
|
||||
changedKeys[keyForRec(m.Existing)] = true
|
||||
}
|
||||
if len(changedKeys) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
chg := &gdns.Change{Kind: "dns#change"}
|
||||
for ck := range changedKeys {
|
||||
// remove old version (if present)
|
||||
if old, ok := oldRRs[ck]; ok {
|
||||
chg.Deletions = append(chg.Deletions, old)
|
||||
// first collect keys that have changed
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("incdiff error: %w", err)
|
||||
}
|
||||
// collect records to replace with
|
||||
newRRs := &gdns.ResourceRecordSet{
|
||||
Name: ck.Name,
|
||||
Type: ck.Type,
|
||||
Kind: "dns#resourceRecordSet",
|
||||
|
||||
changedKeys := map[key]bool{}
|
||||
desc := ""
|
||||
for _, c := range create {
|
||||
desc += fmt.Sprintln(c)
|
||||
changedKeys[keyForRec(c.Desired)] = true
|
||||
}
|
||||
for _, r := range dc.Records {
|
||||
if keyForRec(r) == ck {
|
||||
newRRs.Rrdatas = append(newRRs.Rrdatas, r.GetTargetCombined())
|
||||
newRRs.Ttl = int64(r.TTL)
|
||||
for _, d := range delete {
|
||||
desc += fmt.Sprintln(d)
|
||||
changedKeys[keyForRec(d.Existing)] = true
|
||||
}
|
||||
for _, m := range modify {
|
||||
desc += fmt.Sprintln(m)
|
||||
changedKeys[keyForRec(m.Existing)] = true
|
||||
}
|
||||
if len(changedKeys) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
chg := &gdns.Change{Kind: "dns#change"}
|
||||
for ck := range changedKeys {
|
||||
// remove old version (if present)
|
||||
if old, ok := oldRRs[ck]; ok {
|
||||
chg.Deletions = append(chg.Deletions, old)
|
||||
}
|
||||
// collect records to replace with
|
||||
newRRs := &gdns.ResourceRecordSet{
|
||||
Name: ck.Name,
|
||||
Type: ck.Type,
|
||||
Kind: "dns#resourceRecordSet",
|
||||
}
|
||||
for _, r := range dc.Records {
|
||||
if keyForRec(r) == ck {
|
||||
newRRs.Rrdatas = append(newRRs.Rrdatas, r.GetTargetCombined())
|
||||
newRRs.Ttl = int64(r.TTL)
|
||||
}
|
||||
}
|
||||
if len(newRRs.Rrdatas) > 0 {
|
||||
chg.Additions = append(chg.Additions, newRRs)
|
||||
}
|
||||
}
|
||||
if len(newRRs.Rrdatas) > 0 {
|
||||
chg.Additions = append(chg.Additions, newRRs)
|
||||
|
||||
// FIXME(tlim): Google will return an error if too many changes are
|
||||
// specified in a single request. We should split up very large
|
||||
// batches. This can be reliably reproduced with the 1201
|
||||
// integration test. The error you get is:
|
||||
// googleapi: Error 403: The change would exceed quota for additions per change., quotaExceeded
|
||||
//log.Printf("PAUSE STT = %+v %v\n", err, resp)
|
||||
//log.Printf("PAUSE ERR = %+v %v\n", err, resp)
|
||||
|
||||
runChange := func() error {
|
||||
retry:
|
||||
resp, err := g.client.Changes.Create(g.project, zoneName, chg).Do()
|
||||
if retryNeeded(resp, err) {
|
||||
goto retry
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("runChange error: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return []*models.Correction{{
|
||||
Msg: desc,
|
||||
F: runChange,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
// FIXME(tlim): Google will return an error if too many changes are
|
||||
// specified in a single request. We should split up very large
|
||||
// batches. This can be reliably reproduced with the 1201
|
||||
// integration test. The error you get is:
|
||||
// googleapi: Error 403: The change would exceed quota for additions per change., quotaExceeded
|
||||
//log.Printf("PAUSE STT = %+v %v\n", err, resp)
|
||||
//log.Printf("PAUSE ERR = %+v %v\n", err, resp)
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
runChange := func() error {
|
||||
retry:
|
||||
resp, err := g.client.Changes.Create(g.project, zoneName, chg).Do()
|
||||
if retryNeeded(resp, err) {
|
||||
goto retry
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("runChange error: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return []*models.Correction{{
|
||||
Msg: desc,
|
||||
F: runChange,
|
||||
}}, nil
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
func nativeToRecord(set *gdns.ResourceRecordSet, rec, origin string) (*models.RecordConfig, error) {
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
|
||||
dnssdk "github.com/G-Core/gcore-dns-sdk-go"
|
||||
|
@ -151,86 +152,92 @@ func generateChangeMsg(updates []string) string {
|
|||
// made.
|
||||
func (c *gcoreProvider) GenerateDomainCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, error) {
|
||||
|
||||
var corrections = []*models.Correction{}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
// diff existing vs. current.
|
||||
differ := diff.New(dc)
|
||||
keysToUpdate, err := differ.ChangedGroups(existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(keysToUpdate) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
desiredRecords := dc.Records.GroupedByKey()
|
||||
existingRecords := existing.GroupedByKey()
|
||||
|
||||
// First pass: delete records to avoid coexisting of conflicting types
|
||||
for label := range keysToUpdate {
|
||||
if _, ok := desiredRecords[label]; !ok {
|
||||
// record deleted in update
|
||||
// Copy all params to avoid overwrites
|
||||
zone := dc.Name
|
||||
name := label.NameFQDN
|
||||
typ := label.Type
|
||||
msg := generateChangeMsg(keysToUpdate[label])
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
return c.provider.DeleteRRSet(c.ctx, zone, name, typ)
|
||||
},
|
||||
})
|
||||
// diff existing vs. current.
|
||||
differ := diff.New(dc)
|
||||
keysToUpdate, err := differ.ChangedGroups(existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass: create and update records
|
||||
for label := range keysToUpdate {
|
||||
if _, ok := desiredRecords[label]; !ok {
|
||||
// record deleted in update
|
||||
// do nothing here
|
||||
|
||||
} else if _, ok := existingRecords[label]; !ok {
|
||||
// record created in update
|
||||
record := recordsToNative(desiredRecords[label], label)
|
||||
if record == nil {
|
||||
panic("No records matching label")
|
||||
}
|
||||
|
||||
// Copy all params to avoid overwrites
|
||||
zone := dc.Name
|
||||
name := label.NameFQDN
|
||||
typ := label.Type
|
||||
rec := *record
|
||||
msg := generateChangeMsg(keysToUpdate[label])
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
return c.provider.CreateRRSet(c.ctx, zone, name, typ, rec)
|
||||
},
|
||||
})
|
||||
|
||||
} else {
|
||||
// record modified in update
|
||||
record := recordsToNative(desiredRecords[label], label)
|
||||
if record == nil {
|
||||
panic("No records matching label")
|
||||
}
|
||||
|
||||
// Copy all params to avoid overwrites
|
||||
zone := dc.Name
|
||||
name := label.NameFQDN
|
||||
typ := label.Type
|
||||
rec := *record
|
||||
msg := generateChangeMsg(keysToUpdate[label])
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
return c.provider.UpdateRRSet(c.ctx, zone, name, typ, rec)
|
||||
},
|
||||
})
|
||||
if len(keysToUpdate) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
desiredRecords := dc.Records.GroupedByKey()
|
||||
existingRecords := existing.GroupedByKey()
|
||||
|
||||
// First pass: delete records to avoid coexisting of conflicting types
|
||||
for label := range keysToUpdate {
|
||||
if _, ok := desiredRecords[label]; !ok {
|
||||
// record deleted in update
|
||||
// Copy all params to avoid overwrites
|
||||
zone := dc.Name
|
||||
name := label.NameFQDN
|
||||
typ := label.Type
|
||||
msg := generateChangeMsg(keysToUpdate[label])
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
return c.provider.DeleteRRSet(c.ctx, zone, name, typ)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass: create and update records
|
||||
for label := range keysToUpdate {
|
||||
if _, ok := desiredRecords[label]; !ok {
|
||||
// record deleted in update
|
||||
// do nothing here
|
||||
|
||||
} else if _, ok := existingRecords[label]; !ok {
|
||||
// record created in update
|
||||
record := recordsToNative(desiredRecords[label], label)
|
||||
if record == nil {
|
||||
panic("No records matching label")
|
||||
}
|
||||
|
||||
// Copy all params to avoid overwrites
|
||||
zone := dc.Name
|
||||
name := label.NameFQDN
|
||||
typ := label.Type
|
||||
rec := *record
|
||||
msg := generateChangeMsg(keysToUpdate[label])
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
return c.provider.CreateRRSet(c.ctx, zone, name, typ, rec)
|
||||
},
|
||||
})
|
||||
|
||||
} else {
|
||||
// record modified in update
|
||||
record := recordsToNative(desiredRecords[label], label)
|
||||
if record == nil {
|
||||
panic("No records matching label")
|
||||
}
|
||||
|
||||
// Copy all params to avoid overwrites
|
||||
zone := dc.Name
|
||||
name := label.NameFQDN
|
||||
typ := label.Type
|
||||
rec := *record
|
||||
msg := generateChangeMsg(keysToUpdate[label])
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
return c.provider.UpdateRRSet(c.ctx, zone, name, typ, rec)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
"github.com/pquerna/otp/totp"
|
||||
|
@ -177,7 +178,6 @@ func (c *hednsProvider) GetNameservers(_ string) ([]*models.Nameserver, error) {
|
|||
|
||||
// GetDomainCorrections returns a list of corrections for the domain.
|
||||
func (c *hednsProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||
var corrections []*models.Correction
|
||||
|
||||
err := dc.Punycode()
|
||||
if err != nil {
|
||||
|
@ -204,48 +204,56 @@ func (c *hednsProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models
|
|||
models.PostProcessRecords(prunedRecords)
|
||||
txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, toCreate, toDelete, toModify, err := differ.IncrementalDiff(prunedRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
for _, del := range toDelete {
|
||||
record := del.Existing
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: del.String(),
|
||||
F: func() error { return c.deleteZoneRecord(record) },
|
||||
})
|
||||
}
|
||||
|
||||
for _, cre := range toCreate {
|
||||
record := cre.Desired
|
||||
record.Original = Record{
|
||||
ZoneName: dc.Name,
|
||||
ZoneID: zoneID,
|
||||
RecordName: cre.Desired.Name,
|
||||
differ := diff.New(dc)
|
||||
_, toCreate, toDelete, toModify, err := differ.IncrementalDiff(prunedRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: cre.String(),
|
||||
F: func() error { return c.editZoneRecord(record, true) },
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range toModify {
|
||||
record := mod.Desired
|
||||
record.Original = Record{
|
||||
ZoneName: dc.Name,
|
||||
ZoneID: zoneID,
|
||||
RecordID: mod.Existing.Original.(Record).RecordID,
|
||||
RecordName: mod.Desired.Name,
|
||||
for _, del := range toDelete {
|
||||
record := del.Existing
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: del.String(),
|
||||
F: func() error { return c.deleteZoneRecord(record) },
|
||||
})
|
||||
}
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: mod.String(),
|
||||
F: func() error { return c.editZoneRecord(record, false) },
|
||||
})
|
||||
|
||||
for _, cre := range toCreate {
|
||||
record := cre.Desired
|
||||
record.Original = Record{
|
||||
ZoneName: dc.Name,
|
||||
ZoneID: zoneID,
|
||||
RecordName: cre.Desired.Name,
|
||||
}
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: cre.String(),
|
||||
F: func() error { return c.editZoneRecord(record, true) },
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range toModify {
|
||||
record := mod.Desired
|
||||
record.Original = Record{
|
||||
ZoneName: dc.Name,
|
||||
ZoneID: zoneID,
|
||||
RecordID: mod.Existing.Original.(Record).RecordID,
|
||||
RecordName: mod.Desired.Name,
|
||||
}
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: mod.String(),
|
||||
F: func() error { return c.editZoneRecord(record, false) },
|
||||
})
|
||||
}
|
||||
|
||||
return corrections, err
|
||||
}
|
||||
|
||||
return corrections, err
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// GetZoneRecords returns all the records for the given domain
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
)
|
||||
|
@ -101,65 +102,71 @@ func (api *hetznerProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mo
|
|||
models.PostProcessRecords(existingRecords)
|
||||
txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
zone, err := api.getZone(domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, m := range del {
|
||||
record := m.Existing.Original.(*record)
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
return api.deleteRecord(*record)
|
||||
},
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
|
||||
zone, err := api.getZone(domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, m := range del {
|
||||
record := m.Existing.Original.(*record)
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
return api.deleteRecord(*record)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
var createRecords []record
|
||||
createDescription := []string{"Batch creation of records:"}
|
||||
for _, m := range create {
|
||||
record := fromRecordConfig(m.Desired, zone)
|
||||
createRecords = append(createRecords, *record)
|
||||
createDescription = append(createDescription, m.String())
|
||||
}
|
||||
if len(createRecords) > 0 {
|
||||
corr := &models.Correction{
|
||||
Msg: strings.Join(createDescription, "\n\t"),
|
||||
F: func() error {
|
||||
return api.bulkCreateRecords(createRecords)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
var modifyRecords []record
|
||||
modifyDescription := []string{"Batch modification of records:"}
|
||||
for _, m := range modify {
|
||||
id := m.Existing.Original.(*record).ID
|
||||
record := fromRecordConfig(m.Desired, zone)
|
||||
record.ID = id
|
||||
modifyRecords = append(modifyRecords, *record)
|
||||
modifyDescription = append(modifyDescription, m.String())
|
||||
}
|
||||
if len(modifyRecords) > 0 {
|
||||
corr := &models.Correction{
|
||||
Msg: strings.Join(modifyDescription, "\n\t"),
|
||||
F: func() error {
|
||||
return api.bulkUpdateRecords(modifyRecords)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
var createRecords []record
|
||||
createDescription := []string{"Batch creation of records:"}
|
||||
for _, m := range create {
|
||||
record := fromRecordConfig(m.Desired, zone)
|
||||
createRecords = append(createRecords, *record)
|
||||
createDescription = append(createDescription, m.String())
|
||||
}
|
||||
if len(createRecords) > 0 {
|
||||
corr := &models.Correction{
|
||||
Msg: strings.Join(createDescription, "\n\t"),
|
||||
F: func() error {
|
||||
return api.bulkCreateRecords(createRecords)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
var modifyRecords []record
|
||||
modifyDescription := []string{"Batch modification of records:"}
|
||||
for _, m := range modify {
|
||||
id := m.Existing.Original.(*record).ID
|
||||
record := fromRecordConfig(m.Desired, zone)
|
||||
record.ID = id
|
||||
modifyRecords = append(modifyRecords, *record)
|
||||
modifyDescription = append(modifyDescription, m.String())
|
||||
}
|
||||
if len(modifyRecords) > 0 {
|
||||
corr := &models.Correction{
|
||||
Msg: strings.Join(modifyDescription, "\n\t"),
|
||||
F: func() error {
|
||||
return api.bulkUpdateRecords(modifyRecords)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
)
|
||||
|
@ -73,62 +74,70 @@ func (n *HXClient) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Corr
|
|||
models.PostProcessRecords(actual)
|
||||
txtutil.SplitSingleLongTxt(dc.Records)
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, mod, err := differ.IncrementalDiff(actual)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
corrections := []*models.Correction{}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
// Print a list of changes. Generate an actual change that is the zone
|
||||
changes := false
|
||||
params := map[string]interface{}{}
|
||||
delrridx := 0
|
||||
addrridx := 0
|
||||
for _, cre := range create {
|
||||
changes = true
|
||||
fmt.Fprintln(buf, cre)
|
||||
rec := cre.Desired
|
||||
recordString, err := n.createRecordString(rec, dc.Name)
|
||||
differ := diff.New(dc)
|
||||
_, create, del, mod, err := differ.IncrementalDiff(actual)
|
||||
if err != nil {
|
||||
return corrections, err
|
||||
return nil, err
|
||||
}
|
||||
params[fmt.Sprintf("ADDRR%d", addrridx)] = recordString
|
||||
addrridx++
|
||||
}
|
||||
for _, d := range del {
|
||||
changes = true
|
||||
fmt.Fprintln(buf, d)
|
||||
rec := d.Existing.Original.(*HXRecord)
|
||||
params[fmt.Sprintf("DELRR%d", delrridx)] = n.deleteRecordString(rec, dc.Name)
|
||||
delrridx++
|
||||
}
|
||||
for _, chng := range mod {
|
||||
changes = true
|
||||
fmt.Fprintln(buf, chng)
|
||||
old := chng.Existing.Original.(*HXRecord)
|
||||
new := chng.Desired
|
||||
params[fmt.Sprintf("DELRR%d", delrridx)] = n.deleteRecordString(old, dc.Name)
|
||||
newRecordString, err := n.createRecordString(new, dc.Name)
|
||||
if err != nil {
|
||||
return corrections, err
|
||||
}
|
||||
params[fmt.Sprintf("ADDRR%d", addrridx)] = newRecordString
|
||||
addrridx++
|
||||
delrridx++
|
||||
}
|
||||
msg := fmt.Sprintf("GENERATE_ZONEFILE: %s\n", dc.Name) + buf.String()
|
||||
|
||||
if changes {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
return n.updateZoneBy(params, dc.Name)
|
||||
},
|
||||
})
|
||||
corrections := []*models.Correction{}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
// Print a list of changes. Generate an actual change that is the zone
|
||||
changes := false
|
||||
params := map[string]interface{}{}
|
||||
delrridx := 0
|
||||
addrridx := 0
|
||||
for _, cre := range create {
|
||||
changes = true
|
||||
fmt.Fprintln(buf, cre)
|
||||
rec := cre.Desired
|
||||
recordString, err := n.createRecordString(rec, dc.Name)
|
||||
if err != nil {
|
||||
return corrections, err
|
||||
}
|
||||
params[fmt.Sprintf("ADDRR%d", addrridx)] = recordString
|
||||
addrridx++
|
||||
}
|
||||
for _, d := range del {
|
||||
changes = true
|
||||
fmt.Fprintln(buf, d)
|
||||
rec := d.Existing.Original.(*HXRecord)
|
||||
params[fmt.Sprintf("DELRR%d", delrridx)] = n.deleteRecordString(rec, dc.Name)
|
||||
delrridx++
|
||||
}
|
||||
for _, chng := range mod {
|
||||
changes = true
|
||||
fmt.Fprintln(buf, chng)
|
||||
old := chng.Existing.Original.(*HXRecord)
|
||||
new := chng.Desired
|
||||
params[fmt.Sprintf("DELRR%d", delrridx)] = n.deleteRecordString(old, dc.Name)
|
||||
newRecordString, err := n.createRecordString(new, dc.Name)
|
||||
if err != nil {
|
||||
return corrections, err
|
||||
}
|
||||
params[fmt.Sprintf("ADDRR%d", addrridx)] = newRecordString
|
||||
addrridx++
|
||||
delrridx++
|
||||
}
|
||||
msg := fmt.Sprintf("GENERATE_ZONEFILE: %s\n", dc.Name) + buf.String()
|
||||
|
||||
if changes {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
return n.updateZoneBy(params, dc.Name)
|
||||
},
|
||||
})
|
||||
}
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
)
|
||||
|
||||
|
@ -125,35 +126,43 @@ func (hp *hostingdeProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*m
|
|||
return nil, err
|
||||
}
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, mod, err := differ.IncrementalDiff(records)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
// NOPURGE
|
||||
if dc.KeepUnknown {
|
||||
del = []diff.Correlation{}
|
||||
}
|
||||
differ := diff.New(dc)
|
||||
_, create, del, mod, err := differ.IncrementalDiff(records)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msg := []string{}
|
||||
for _, c := range append(del, append(create, mod...)...) {
|
||||
msg = append(msg, c.String())
|
||||
}
|
||||
// NOPURGE
|
||||
if dc.KeepUnknown {
|
||||
del = []diff.Correlation{}
|
||||
}
|
||||
|
||||
if len(create) == 0 && len(del) == 0 && len(mod) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
msg := []string{}
|
||||
for _, c := range append(del, append(create, mod...)...) {
|
||||
msg = append(msg, c.String())
|
||||
}
|
||||
|
||||
corrections := []*models.Correction{
|
||||
{
|
||||
Msg: fmt.Sprintf("\n%s", strings.Join(msg, "\n")),
|
||||
F: func() error {
|
||||
return hp.updateRecords(dc.Name, create, del, mod)
|
||||
if len(create) == 0 && len(del) == 0 && len(mod) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
corrections := []*models.Correction{
|
||||
{
|
||||
Msg: fmt.Sprintf("\n%s", strings.Join(msg, "\n")),
|
||||
F: func() error {
|
||||
return hp.updateRecords(dc.Name, create, del, mod)
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
|
@ -247,31 +248,37 @@ func (api *inwxAPI) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Cor
|
|||
return nil, err
|
||||
}
|
||||
|
||||
corrections := []*models.Correction{}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
for _, d := range create {
|
||||
des := d.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return api.createRecord(dc.Name, des) },
|
||||
})
|
||||
}
|
||||
for _, d := range del {
|
||||
existingID := d.Existing.Original.(goinwx.NameserverRecord).ID
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return api.deleteRecord(existingID) },
|
||||
})
|
||||
}
|
||||
for _, d := range mod {
|
||||
rec := d.Desired
|
||||
existingID := d.Existing.Original.(goinwx.NameserverRecord).ID
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return api.updateRecord(existingID, rec) },
|
||||
})
|
||||
for _, d := range create {
|
||||
des := d.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return api.createRecord(dc.Name, des) },
|
||||
})
|
||||
}
|
||||
for _, d := range del {
|
||||
existingID := d.Existing.Original.(goinwx.NameserverRecord).ID
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return api.deleteRecord(existingID) },
|
||||
})
|
||||
}
|
||||
for _, d := range mod {
|
||||
rec := d.Desired
|
||||
existingID := d.Existing.Original.(goinwx.NameserverRecord).ID
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return api.updateRecord(existingID, rec) },
|
||||
})
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"golang.org/x/oauth2"
|
||||
|
@ -155,72 +156,78 @@ func (api *linodeProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mod
|
|||
record.TTL = fixTTL(record.TTL)
|
||||
}
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
// Deletes first so changing type works etc.
|
||||
for _, m := range del {
|
||||
id := m.Existing.Original.(*domainRecord).ID
|
||||
if id == 0 { // Skip ID 0, these are the default nameservers always present
|
||||
continue
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, Linode ID: %d", m.String(), id),
|
||||
F: func() error {
|
||||
return api.deleteRecord(domainID, id)
|
||||
},
|
||||
|
||||
// Deletes first so changing type works etc.
|
||||
for _, m := range del {
|
||||
id := m.Existing.Original.(*domainRecord).ID
|
||||
if id == 0 { // Skip ID 0, these are the default nameservers always present
|
||||
continue
|
||||
}
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, Linode ID: %d", m.String(), id),
|
||||
F: func() error {
|
||||
return api.deleteRecord(domainID, id)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
for _, m := range create {
|
||||
req, err := toReq(dc, m.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
j, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s: %s", m.String(), string(j)),
|
||||
F: func() error {
|
||||
record, err := api.createRecord(domainID, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TTL isn't saved when creating a record, so we will need to modify it immediately afterwards
|
||||
return api.modifyRecord(domainID, record.ID, req)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
for _, m := range modify {
|
||||
id := m.Existing.Original.(*domainRecord).ID
|
||||
if id == 0 { // Skip ID 0, these are the default nameservers always present
|
||||
continue
|
||||
}
|
||||
req, err := toReq(dc, m.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
j, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, Linode ID: %d: %s", m.String(), id, string(j)),
|
||||
F: func() error {
|
||||
return api.modifyRecord(domainID, id, req)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
for _, m := range create {
|
||||
req, err := toReq(dc, m.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
j, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s: %s", m.String(), string(j)),
|
||||
F: func() error {
|
||||
record, err := api.createRecord(domainID, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TTL isn't saved when creating a record, so we will need to modify it immediately afterwards
|
||||
return api.modifyRecord(domainID, record.ID, req)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
for _, m := range modify {
|
||||
id := m.Existing.Original.(*domainRecord).ID
|
||||
if id == 0 { // Skip ID 0, these are the default nameservers always present
|
||||
continue
|
||||
}
|
||||
req, err := toReq(dc, m.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
j, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, Linode ID: %d: %s", m.String(), id, string(j)),
|
||||
F: func() error {
|
||||
return api.modifyRecord(domainID, id, req)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package msdns
|
|||
import (
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
)
|
||||
|
||||
|
@ -13,25 +14,33 @@ func (client *msdnsProvider) GenerateDomainCorrections(dc *models.DomainConfig,
|
|||
models.PostProcessRecords(foundRecords)
|
||||
txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, creates, dels, modifications, err := differ.IncrementalDiff(foundRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, creates, dels, modifications, err := differ.IncrementalDiff(foundRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Generate changes.
|
||||
corrections := []*models.Correction{}
|
||||
for _, del := range dels {
|
||||
corrections = append(corrections, client.deleteRec(client.dnsserver, dc.Name, del))
|
||||
}
|
||||
for _, cre := range creates {
|
||||
corrections = append(corrections, client.createRec(client.dnsserver, dc.Name, cre)...)
|
||||
}
|
||||
for _, m := range modifications {
|
||||
corrections = append(corrections, client.modifyRec(client.dnsserver, dc.Name, m))
|
||||
}
|
||||
return corrections, nil
|
||||
|
||||
}
|
||||
|
||||
// Generate changes.
|
||||
corrections := []*models.Correction{}
|
||||
for _, del := range dels {
|
||||
corrections = append(corrections, client.deleteRec(client.dnsserver, dc.Name, del))
|
||||
}
|
||||
for _, cre := range creates {
|
||||
corrections = append(corrections, client.createRec(client.dnsserver, dc.Name, cre)...)
|
||||
}
|
||||
for _, m := range modifications {
|
||||
corrections = append(corrections, client.modifyRec(client.dnsserver, dc.Name, m))
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
|
||||
}
|
||||
|
||||
func (client *msdnsProvider) deleteRec(dnsserver, domainname string, cor diff.Correlation) *models.Correction {
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
nc "github.com/billputer/go-namecheap"
|
||||
|
@ -190,40 +191,48 @@ func (n *namecheapProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mo
|
|||
// Normalize
|
||||
models.PostProcessRecords(actual)
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(actual)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(actual)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// // because namecheap doesn't have selective create, delete, modify,
|
||||
// // we bundle them all up to send at once. We *do* want to see the
|
||||
// // changes though
|
||||
|
||||
var desc []string
|
||||
for _, i := range create {
|
||||
desc = append(desc, "\n"+i.String())
|
||||
}
|
||||
for _, i := range delete {
|
||||
desc = append(desc, "\n"+i.String())
|
||||
}
|
||||
for _, i := range modify {
|
||||
desc = append(desc, "\n"+i.String())
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("GENERATE_ZONE: %s (%d records)%s", dc.Name, len(dc.Records), desc)
|
||||
corrections := []*models.Correction{}
|
||||
|
||||
// only create corrections if there are changes
|
||||
if len(desc) > 0 {
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
return n.generateRecords(dc)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// // because namecheap doesn't have selective create, delete, modify,
|
||||
// // we bundle them all up to send at once. We *do* want to see the
|
||||
// // changes though
|
||||
|
||||
var desc []string
|
||||
for _, i := range create {
|
||||
desc = append(desc, "\n"+i.String())
|
||||
}
|
||||
for _, i := range delete {
|
||||
desc = append(desc, "\n"+i.String())
|
||||
}
|
||||
for _, i := range modify {
|
||||
desc = append(desc, "\n"+i.String())
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("GENERATE_ZONE: %s (%d records)%s", dc.Name, len(dc.Records), desc)
|
||||
corrections := []*models.Correction{}
|
||||
|
||||
// only create corrections if there are changes
|
||||
if len(desc) > 0 {
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
return n.generateRecords(dc)
|
||||
},
|
||||
})
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/namedotcom/go/namecom"
|
||||
)
|
||||
|
||||
|
@ -53,36 +54,44 @@ func (n *namedotcomProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*m
|
|||
// Normalize
|
||||
models.PostProcessRecords(actual)
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, mod, err := differ.IncrementalDiff(actual)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, mod, err := differ.IncrementalDiff(actual)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corrections := []*models.Correction{}
|
||||
|
||||
for _, d := range del {
|
||||
rec := d.Existing.Original.(*namecom.Record)
|
||||
c := &models.Correction{Msg: d.String(), F: func() error { return n.deleteRecord(rec.ID, dc.Name) }}
|
||||
corrections = append(corrections, c)
|
||||
}
|
||||
for _, cre := range create {
|
||||
rec := cre.Desired
|
||||
c := &models.Correction{Msg: cre.String(), F: func() error { return n.createRecord(rec, dc.Name) }}
|
||||
corrections = append(corrections, c)
|
||||
}
|
||||
for _, chng := range mod {
|
||||
old := chng.Existing.Original.(*namecom.Record)
|
||||
new := chng.Desired
|
||||
c := &models.Correction{Msg: chng.String(), F: func() error {
|
||||
err := n.deleteRecord(old.ID, dc.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return n.createRecord(new, dc.Name)
|
||||
}}
|
||||
corrections = append(corrections, c)
|
||||
}
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
corrections := []*models.Correction{}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
for _, d := range del {
|
||||
rec := d.Existing.Original.(*namecom.Record)
|
||||
c := &models.Correction{Msg: d.String(), F: func() error { return n.deleteRecord(rec.ID, dc.Name) }}
|
||||
corrections = append(corrections, c)
|
||||
}
|
||||
for _, cre := range create {
|
||||
rec := cre.Desired
|
||||
c := &models.Correction{Msg: cre.String(), F: func() error { return n.createRecord(rec, dc.Name) }}
|
||||
corrections = append(corrections, c)
|
||||
}
|
||||
for _, chng := range mod {
|
||||
old := chng.Existing.Original.(*namecom.Record)
|
||||
new := chng.Desired
|
||||
c := &models.Correction{Msg: chng.String(), F: func() error {
|
||||
err := n.deleteRecord(old.ID, dc.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return n.createRecord(new, dc.Name)
|
||||
}}
|
||||
corrections = append(corrections, c)
|
||||
}
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
)
|
||||
|
||||
|
@ -100,48 +101,54 @@ func (api *netcupProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mod
|
|||
// no need for txtutil.SplitSingleLongTxt in function GetDomainCorrections
|
||||
// txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
// Deletes first so changing type works etc.
|
||||
for _, m := range del {
|
||||
req := m.Existing.Original.(*record)
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, Netcup ID: %s", m.String(), req.ID),
|
||||
F: func() error {
|
||||
return api.deleteRecord(domain, req)
|
||||
},
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
|
||||
// Deletes first so changing type works etc.
|
||||
for _, m := range del {
|
||||
req := m.Existing.Original.(*record)
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, Netcup ID: %s", m.String(), req.ID),
|
||||
F: func() error {
|
||||
return api.deleteRecord(domain, req)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
for _, m := range create {
|
||||
req := fromRecordConfig(m.Desired)
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
return api.createRecord(domain, req)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
for _, m := range modify {
|
||||
id := m.Existing.Original.(*record).ID
|
||||
req := fromRecordConfig(m.Desired)
|
||||
req.ID = id
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, Netcup ID: %s: ", m.String(), id),
|
||||
F: func() error {
|
||||
return api.modifyRecord(domain, req)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
for _, m := range create {
|
||||
req := fromRecordConfig(m.Desired)
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
return api.createRecord(domain, req)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
for _, m := range modify {
|
||||
id := m.Existing.Original.(*record).ID
|
||||
req := fromRecordConfig(m.Desired)
|
||||
req.ID = id
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, Netcup ID: %s: ", m.String(), id),
|
||||
F: func() error {
|
||||
return api.modifyRecord(domain, req)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
|
@ -176,7 +177,7 @@ func removeOtherApexNS(dc *models.DomainConfig) {
|
|||
}
|
||||
|
||||
func (n *netlifyProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||
var corrections []*models.Correction
|
||||
|
||||
err := dc.Punycode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -192,58 +193,66 @@ func (n *netlifyProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
|||
txtutil.SplitSingleLongTxt(dc.Records) // Auto split long TXT records
|
||||
removeOtherApexNS(dc)
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(records)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
zone, err := n.getZone(dc.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Deletes first so changing type works etc.
|
||||
for _, m := range del {
|
||||
id := m.Existing.Original.(*dnsRecord).ID
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
return n.deleteDNSRecord(zone.ID, id)
|
||||
},
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(records)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
for _, m := range create {
|
||||
req := toReq(m.Desired)
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
_, err := n.createDNSRecord(zone.ID, req)
|
||||
return err
|
||||
},
|
||||
zone, err := n.getZone(dc.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
for _, m := range modify {
|
||||
id := m.Existing.Original.(*dnsRecord).ID
|
||||
req := toReq(m.Desired)
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
if err := n.deleteDNSRecord(zone.ID, id); err != nil {
|
||||
// Deletes first so changing type works etc.
|
||||
for _, m := range del {
|
||||
id := m.Existing.Original.(*dnsRecord).ID
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
return n.deleteDNSRecord(zone.ID, id)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
for _, m := range create {
|
||||
req := toReq(m.Desired)
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
_, err := n.createDNSRecord(zone.ID, req)
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := n.createDNSRecord(zone.ID, req)
|
||||
return err
|
||||
},
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
|
||||
for _, m := range modify {
|
||||
id := m.Existing.Original.(*dnsRecord).ID
|
||||
req := toReq(m.Desired)
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
if err := n.deleteDNSRecord(zone.ID, id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := n.createDNSRecord(zone.ID, req)
|
||||
return err
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
"gopkg.in/ns1/ns1-go.v2/rest"
|
||||
"gopkg.in/ns1/ns1-go.v2/rest/model/dns"
|
||||
|
@ -162,45 +163,53 @@ func (n *nsone) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correct
|
|||
// Normalize
|
||||
models.PostProcessRecords(existingRecords)
|
||||
|
||||
differ := diff.New(dc)
|
||||
changedGroups, err := differ.ChangedGroups(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
corrections := []*models.Correction{}
|
||||
|
||||
if dnssecCorrections := n.getDomainCorrectionsDNSSEC(domain, dc.AutoDNSSEC); dnssecCorrections != nil {
|
||||
corrections = append(corrections, dnssecCorrections)
|
||||
}
|
||||
|
||||
// each name/type is given to the api as a unit.
|
||||
for k, descs := range changedGroups {
|
||||
key := k
|
||||
|
||||
desc := strings.Join(descs, "\n")
|
||||
_, current := existingGrouped[k]
|
||||
recs, wanted := desiredGrouped[k]
|
||||
if wanted && !current {
|
||||
// pure addition
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: desc,
|
||||
F: func() error { return n.add(recs, dc.Name) },
|
||||
})
|
||||
} else if current && !wanted {
|
||||
// pure deletion
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: desc,
|
||||
F: func() error { return n.remove(key, dc.Name) },
|
||||
})
|
||||
} else {
|
||||
// modification
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: desc,
|
||||
F: func() error { return n.modify(recs, dc.Name) },
|
||||
})
|
||||
differ := diff.New(dc)
|
||||
changedGroups, err := differ.ChangedGroups(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corrections := []*models.Correction{}
|
||||
|
||||
if dnssecCorrections := n.getDomainCorrectionsDNSSEC(domain, dc.AutoDNSSEC); dnssecCorrections != nil {
|
||||
corrections = append(corrections, dnssecCorrections)
|
||||
}
|
||||
|
||||
// each name/type is given to the api as a unit.
|
||||
for k, descs := range changedGroups {
|
||||
key := k
|
||||
|
||||
desc := strings.Join(descs, "\n")
|
||||
_, current := existingGrouped[k]
|
||||
recs, wanted := desiredGrouped[k]
|
||||
if wanted && !current {
|
||||
// pure addition
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: desc,
|
||||
F: func() error { return n.add(recs, dc.Name) },
|
||||
})
|
||||
} else if current && !wanted {
|
||||
// pure deletion
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: desc,
|
||||
F: func() error { return n.remove(key, dc.Name) },
|
||||
})
|
||||
} else {
|
||||
// modification
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: desc,
|
||||
F: func() error { return n.modify(recs, dc.Name) },
|
||||
})
|
||||
}
|
||||
}
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
|
@ -239,75 +240,83 @@ func (o *oracleProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*model
|
|||
}
|
||||
}
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, dels, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
/*
|
||||
Oracle's API doesn't have a way to update an existing record.
|
||||
You can either update an existing RRSet, Domain (FQDN), or Zone in which you have to supply
|
||||
the entire desired state, or you can patch specifying ADD/REMOVE actions.
|
||||
Oracle's API is also increadibly slow, so updating individual RRSets is unbearably slow
|
||||
for any size zone.
|
||||
*/
|
||||
|
||||
corrections := []*models.Correction{}
|
||||
|
||||
if len(create) > 0 {
|
||||
createRecords := models.Records{}
|
||||
desc := ""
|
||||
for _, d := range create {
|
||||
createRecords = append(createRecords, d.Desired)
|
||||
desc += d.String() + "\n"
|
||||
differ := diff.New(dc)
|
||||
_, create, dels, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
desc = desc[:len(desc)-1]
|
||||
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: desc,
|
||||
F: func() error {
|
||||
return o.patch(createRecords, nil, domain)
|
||||
},
|
||||
})
|
||||
}
|
||||
/*
|
||||
Oracle's API doesn't have a way to update an existing record.
|
||||
You can either update an existing RRSet, Domain (FQDN), or Zone in which you have to supply
|
||||
the entire desired state, or you can patch specifying ADD/REMOVE actions.
|
||||
Oracle's API is also increadibly slow, so updating individual RRSets is unbearably slow
|
||||
for any size zone.
|
||||
*/
|
||||
|
||||
if len(dels) > 0 {
|
||||
deleteRecords := models.Records{}
|
||||
desc := ""
|
||||
for _, d := range dels {
|
||||
deleteRecords = append(deleteRecords, d.Existing)
|
||||
desc += d.String() + "\n"
|
||||
corrections := []*models.Correction{}
|
||||
|
||||
if len(create) > 0 {
|
||||
createRecords := models.Records{}
|
||||
desc := ""
|
||||
for _, d := range create {
|
||||
createRecords = append(createRecords, d.Desired)
|
||||
desc += d.String() + "\n"
|
||||
}
|
||||
desc = desc[:len(desc)-1]
|
||||
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: desc,
|
||||
F: func() error {
|
||||
return o.patch(createRecords, nil, domain)
|
||||
},
|
||||
})
|
||||
}
|
||||
desc = desc[:len(desc)-1]
|
||||
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: desc,
|
||||
F: func() error {
|
||||
return o.patch(nil, deleteRecords, domain)
|
||||
},
|
||||
})
|
||||
}
|
||||
if len(dels) > 0 {
|
||||
deleteRecords := models.Records{}
|
||||
desc := ""
|
||||
for _, d := range dels {
|
||||
deleteRecords = append(deleteRecords, d.Existing)
|
||||
desc += d.String() + "\n"
|
||||
}
|
||||
desc = desc[:len(desc)-1]
|
||||
|
||||
if len(modify) > 0 {
|
||||
createRecords := models.Records{}
|
||||
deleteRecords := models.Records{}
|
||||
desc := ""
|
||||
for _, d := range modify {
|
||||
createRecords = append(createRecords, d.Desired)
|
||||
deleteRecords = append(deleteRecords, d.Existing)
|
||||
desc += d.String() + "\n"
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: desc,
|
||||
F: func() error {
|
||||
return o.patch(nil, deleteRecords, domain)
|
||||
},
|
||||
})
|
||||
}
|
||||
desc = desc[:len(desc)-1]
|
||||
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: desc,
|
||||
F: func() error {
|
||||
return o.patch(createRecords, deleteRecords, domain)
|
||||
},
|
||||
})
|
||||
if len(modify) > 0 {
|
||||
createRecords := models.Records{}
|
||||
deleteRecords := models.Records{}
|
||||
desc := ""
|
||||
for _, d := range modify {
|
||||
createRecords = append(createRecords, d.Desired)
|
||||
deleteRecords = append(deleteRecords, d.Existing)
|
||||
desc += d.String() + "\n"
|
||||
}
|
||||
desc = desc[:len(desc)-1]
|
||||
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: desc,
|
||||
F: func() error {
|
||||
return o.patch(createRecords, deleteRecords, domain)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
"github.com/ovh/go-ovh/ovh"
|
||||
)
|
||||
|
@ -128,47 +129,55 @@ func (c *ovhProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.C
|
|||
// Normalize
|
||||
models.PostProcessRecords(actual)
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(actual)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(actual)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corrections := []*models.Correction{}
|
||||
|
||||
for _, del := range delete {
|
||||
rec := del.Existing.Original.(*Record)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: del.String(),
|
||||
F: c.deleteRecordFunc(rec.ID, dc.Name),
|
||||
})
|
||||
}
|
||||
|
||||
for _, cre := range create {
|
||||
rec := cre.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: cre.String(),
|
||||
F: c.createRecordFunc(rec, dc.Name),
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range modify {
|
||||
oldR := mod.Existing.Original.(*Record)
|
||||
newR := mod.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: mod.String(),
|
||||
F: c.updateRecordFunc(oldR, newR, dc.Name),
|
||||
})
|
||||
}
|
||||
|
||||
if len(corrections) > 0 {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: "REFRESH zone " + dc.Name,
|
||||
F: func() error {
|
||||
return c.refreshZone(dc.Name)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
corrections := []*models.Correction{}
|
||||
|
||||
for _, del := range delete {
|
||||
rec := del.Existing.Original.(*Record)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: del.String(),
|
||||
F: c.deleteRecordFunc(rec.ID, dc.Name),
|
||||
})
|
||||
}
|
||||
|
||||
for _, cre := range create {
|
||||
rec := cre.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: cre.String(),
|
||||
F: c.createRecordFunc(rec, dc.Name),
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range modify {
|
||||
oldR := mod.Existing.Original.(*Record)
|
||||
newR := mod.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: mod.String(),
|
||||
F: c.updateRecordFunc(oldR, newR, dc.Name),
|
||||
})
|
||||
}
|
||||
|
||||
if len(corrections) > 0 {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: "REFRESH zone " + dc.Name,
|
||||
F: func() error {
|
||||
return c.refreshZone(dc.Name)
|
||||
},
|
||||
})
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
)
|
||||
|
||||
|
@ -123,62 +124,68 @@ func (api *packetframeProvider) GetDomainCorrections(dc *models.DomainConfig) ([
|
|||
// Normalize
|
||||
models.PostProcessRecords(existingRecords)
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
for _, m := range create {
|
||||
req, err := toReq(zone.ID, dc, m.Desired)
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
_, err := api.createRecord(req)
|
||||
return err
|
||||
},
|
||||
|
||||
for _, m := range create {
|
||||
req, err := toReq(zone.ID, dc, m.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
_, err := api.createRecord(req)
|
||||
return err
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
|
||||
for _, m := range delete {
|
||||
original := m.Existing.Original.(*domainRecord)
|
||||
if original.ID == "0" { // Skip the default nameservers
|
||||
continue
|
||||
}
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
err := api.deleteRecord(zone.ID, original.ID)
|
||||
return err
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
for _, m := range modify {
|
||||
original := m.Existing.Original.(*domainRecord)
|
||||
if original.ID == "0" { // Skip the default nameservers
|
||||
continue
|
||||
}
|
||||
|
||||
req, _ := toReq(zone.ID, dc, m.Desired)
|
||||
req.ID = original.ID
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
err := api.modifyRecord(req)
|
||||
return err
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
for _, m := range delete {
|
||||
original := m.Existing.Original.(*domainRecord)
|
||||
if original.ID == "0" { // Skip the default nameservers
|
||||
continue
|
||||
}
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
err := api.deleteRecord(zone.ID, original.ID)
|
||||
return err
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
for _, m := range modify {
|
||||
original := m.Existing.Original.(*domainRecord)
|
||||
if original.ID == "0" { // Skip the default nameservers
|
||||
continue
|
||||
}
|
||||
|
||||
req, _ := toReq(zone.ID, dc, m.Desired)
|
||||
req.ID = original.ID
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
err := api.modifyRecord(req)
|
||||
return err
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
)
|
||||
|
@ -98,57 +99,63 @@ func (c *porkbunProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
|||
record.TTL = fixTTL(record.TTL)
|
||||
}
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
// Deletes first so changing type works etc.
|
||||
for _, m := range del {
|
||||
id := m.Existing.Original.(*domainRecord).ID
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, porkbun ID: %s", m.String(), id),
|
||||
F: func() error {
|
||||
return c.deleteRecord(dc.Name, id)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
for _, m := range create {
|
||||
req, err := toReq(m.Desired)
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
return c.createRecord(dc.Name, req)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
for _, m := range modify {
|
||||
id := m.Existing.Original.(*domainRecord).ID
|
||||
req, err := toReq(m.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Deletes first so changing type works etc.
|
||||
for _, m := range del {
|
||||
id := m.Existing.Original.(*domainRecord).ID
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, porkbun ID: %s", m.String(), id),
|
||||
F: func() error {
|
||||
return c.deleteRecord(dc.Name, id)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, porkbun ID: %s: ", m.String(), id),
|
||||
F: func() error {
|
||||
return c.modifyRecord(dc.Name, id, req)
|
||||
},
|
||||
for _, m := range create {
|
||||
req, err := toReq(m.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
return c.createRecord(dc.Name, req)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
|
||||
for _, m := range modify {
|
||||
id := m.Existing.Original.(*domainRecord).ID
|
||||
req, err := toReq(m.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corr := &models.Correction{
|
||||
Msg: fmt.Sprintf("%s, porkbun ID: %s: ", m.String(), id),
|
||||
F: func() error {
|
||||
return c.modifyRecord(dc.Name, id, req)
|
||||
},
|
||||
}
|
||||
corrections = append(corrections, corr)
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/mittwald/go-powerdns/apis/zones"
|
||||
"github.com/mittwald/go-powerdns/pdnshttp"
|
||||
)
|
||||
|
@ -48,7 +49,6 @@ func (dsp *powerdnsProvider) GetZoneRecords(domain string) (models.Records, erro
|
|||
|
||||
// GetDomainCorrections returns a list of corrections to update a domain.
|
||||
func (dsp *powerdnsProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||
var corrections []*models.Correction
|
||||
|
||||
// get current zone records
|
||||
curRecords, err := dsp.GetZoneRecords(dc.Name)
|
||||
|
@ -62,65 +62,73 @@ func (dsp *powerdnsProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*m
|
|||
}
|
||||
models.PostProcessRecords(curRecords)
|
||||
|
||||
// create record diff by group
|
||||
keysToUpdate, err := (diff.New(dc)).ChangedGroups(curRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
desiredRecords := dc.Records.GroupedByKey()
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
var cuCorrections []*models.Correction
|
||||
var dCorrections []*models.Correction
|
||||
// create record diff by group
|
||||
keysToUpdate, err := (diff.New(dc)).ChangedGroups(curRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
desiredRecords := dc.Records.GroupedByKey()
|
||||
|
||||
// add create/update and delete corrections separately
|
||||
for label, msgs := range keysToUpdate {
|
||||
labelName := label.NameFQDN + "."
|
||||
labelType := label.Type
|
||||
msgJoined := strings.Join(msgs, "\n ")
|
||||
var cuCorrections []*models.Correction
|
||||
var dCorrections []*models.Correction
|
||||
|
||||
if _, ok := desiredRecords[label]; !ok {
|
||||
// no record found so delete it
|
||||
dCorrections = append(dCorrections, &models.Correction{
|
||||
Msg: msgJoined,
|
||||
F: func() error {
|
||||
return dsp.client.Zones().RemoveRecordSetFromZone(context.Background(), dsp.ServerName, dc.Name, labelName, labelType)
|
||||
},
|
||||
})
|
||||
} else {
|
||||
// record found so create or update it
|
||||
ttl := desiredRecords[label][0].TTL
|
||||
var records []zones.Record
|
||||
for _, recordContent := range desiredRecords[label] {
|
||||
records = append(records, zones.Record{
|
||||
Content: recordContent.GetTargetCombined(),
|
||||
// add create/update and delete corrections separately
|
||||
for label, msgs := range keysToUpdate {
|
||||
labelName := label.NameFQDN + "."
|
||||
labelType := label.Type
|
||||
msgJoined := strings.Join(msgs, "\n ")
|
||||
|
||||
if _, ok := desiredRecords[label]; !ok {
|
||||
// no record found so delete it
|
||||
dCorrections = append(dCorrections, &models.Correction{
|
||||
Msg: msgJoined,
|
||||
F: func() error {
|
||||
return dsp.client.Zones().RemoveRecordSetFromZone(context.Background(), dsp.ServerName, dc.Name, labelName, labelType)
|
||||
},
|
||||
})
|
||||
} else {
|
||||
// record found so create or update it
|
||||
ttl := desiredRecords[label][0].TTL
|
||||
var records []zones.Record
|
||||
for _, recordContent := range desiredRecords[label] {
|
||||
records = append(records, zones.Record{
|
||||
Content: recordContent.GetTargetCombined(),
|
||||
})
|
||||
}
|
||||
cuCorrections = append(cuCorrections, &models.Correction{
|
||||
Msg: msgJoined,
|
||||
F: func() error {
|
||||
return dsp.client.Zones().AddRecordSetToZone(context.Background(), dsp.ServerName, dc.Name, zones.ResourceRecordSet{
|
||||
Name: labelName,
|
||||
Type: labelType,
|
||||
TTL: int(ttl),
|
||||
Records: records,
|
||||
ChangeType: zones.ChangeTypeReplace,
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
cuCorrections = append(cuCorrections, &models.Correction{
|
||||
Msg: msgJoined,
|
||||
F: func() error {
|
||||
return dsp.client.Zones().AddRecordSetToZone(context.Background(), dsp.ServerName, dc.Name, zones.ResourceRecordSet{
|
||||
Name: labelName,
|
||||
Type: labelType,
|
||||
TTL: int(ttl),
|
||||
Records: records,
|
||||
ChangeType: zones.ChangeTypeReplace,
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// append corrections in the right order
|
||||
// delete corrections must be run first to avoid correlations with existing RR
|
||||
corrections = append(corrections, dCorrections...)
|
||||
corrections = append(corrections, cuCorrections...)
|
||||
|
||||
// DNSSec corrections
|
||||
dnssecCorrections, err := dsp.getDNSSECCorrections(dc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corrections = append(corrections, dnssecCorrections...)
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// append corrections in the right order
|
||||
// delete corrections must be run first to avoid correlations with existing RR
|
||||
corrections = append(corrections, dCorrections...)
|
||||
corrections = append(corrections, cuCorrections...)
|
||||
|
||||
// DNSSec corrections
|
||||
dnssecCorrections, err := dsp.getDNSSECCorrections(dc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corrections = append(corrections, dnssecCorrections...)
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
|
@ -261,8 +262,6 @@ func (r *route53Provider) getZoneRecords(zone r53Types.HostedZone) (models.Recor
|
|||
func (r *route53Provider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||
dc.Punycode()
|
||||
|
||||
var corrections = []*models.Correction{}
|
||||
|
||||
zone, err := r.getZone(dc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -284,108 +283,134 @@ func (r *route53Provider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
|||
models.PostProcessRecords(existingRecords)
|
||||
txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
// diff
|
||||
differ := diff.New(dc, getAliasMap)
|
||||
namesToUpdate, err := differ.ChangedGroups(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
if len(namesToUpdate) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
// diff
|
||||
differ := diff.New(dc, getAliasMap)
|
||||
namesToUpdate, err := differ.ChangedGroups(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
updates := map[models.RecordKey][]*models.RecordConfig{}
|
||||
if len(namesToUpdate) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// for each name we need to update, collect relevant records from our desired domain state
|
||||
for k := range namesToUpdate {
|
||||
updates[k] = nil
|
||||
for _, rc := range dc.Records {
|
||||
if rc.Key() == k {
|
||||
updates[k] = append(updates[k], rc)
|
||||
updates := map[models.RecordKey][]*models.RecordConfig{}
|
||||
|
||||
// for each name we need to update, collect relevant records from our desired domain state
|
||||
for k := range namesToUpdate {
|
||||
updates[k] = nil
|
||||
for _, rc := range dc.Records {
|
||||
if rc.Key() == k {
|
||||
updates[k] = append(updates[k], rc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// updateOrder is the order that the updates will happen.
|
||||
// The order should be sorted by NameFQDN, then Type, with R53_ALIAS_*
|
||||
// types sorted after all other types. R53_ALIAS_* needs to be last
|
||||
// because they are order dependent (aliases must refer to labels
|
||||
// that already exist).
|
||||
var updateOrder []models.RecordKey
|
||||
// Collect the keys
|
||||
for k := range updates {
|
||||
updateOrder = append(updateOrder, k)
|
||||
}
|
||||
// Sort themm
|
||||
sort.Slice(updateOrder, func(i, j int) bool {
|
||||
if updateOrder[i].Type == updateOrder[j].Type {
|
||||
// updateOrder is the order that the updates will happen.
|
||||
// The order should be sorted by NameFQDN, then Type, with R53_ALIAS_*
|
||||
// types sorted after all other types. R53_ALIAS_* needs to be last
|
||||
// because they are order dependent (aliases must refer to labels
|
||||
// that already exist).
|
||||
var updateOrder []models.RecordKey
|
||||
// Collect the keys
|
||||
for k := range updates {
|
||||
updateOrder = append(updateOrder, k)
|
||||
}
|
||||
// Sort themm
|
||||
sort.Slice(updateOrder, func(i, j int) bool {
|
||||
if updateOrder[i].Type == updateOrder[j].Type {
|
||||
return updateOrder[i].NameFQDN < updateOrder[j].NameFQDN
|
||||
}
|
||||
|
||||
if strings.HasPrefix(updateOrder[i].Type, "R53_ALIAS_") {
|
||||
return false
|
||||
}
|
||||
if strings.HasPrefix(updateOrder[j].Type, "R53_ALIAS_") {
|
||||
return true
|
||||
}
|
||||
|
||||
if updateOrder[i].NameFQDN == updateOrder[j].NameFQDN {
|
||||
return updateOrder[i].Type < updateOrder[j].Type
|
||||
}
|
||||
return updateOrder[i].NameFQDN < updateOrder[j].NameFQDN
|
||||
}
|
||||
})
|
||||
|
||||
if strings.HasPrefix(updateOrder[i].Type, "R53_ALIAS_") {
|
||||
return false
|
||||
}
|
||||
if strings.HasPrefix(updateOrder[j].Type, "R53_ALIAS_") {
|
||||
return true
|
||||
}
|
||||
// we collect all changes into one of two categories now:
|
||||
// pure deletions where we delete an entire record set,
|
||||
// or changes where we upsert an entire record set.
|
||||
dels := []r53Types.Change{}
|
||||
delDesc := []string{}
|
||||
changes := []r53Types.Change{}
|
||||
changeDesc := []string{}
|
||||
|
||||
if updateOrder[i].NameFQDN == updateOrder[j].NameFQDN {
|
||||
return updateOrder[i].Type < updateOrder[j].Type
|
||||
}
|
||||
return updateOrder[i].NameFQDN < updateOrder[j].NameFQDN
|
||||
})
|
||||
|
||||
// we collect all changes into one of two categories now:
|
||||
// pure deletions where we delete an entire record set,
|
||||
// or changes where we upsert an entire record set.
|
||||
dels := []r53Types.Change{}
|
||||
delDesc := []string{}
|
||||
changes := []r53Types.Change{}
|
||||
changeDesc := []string{}
|
||||
|
||||
for _, k := range updateOrder {
|
||||
recs := updates[k]
|
||||
// If there are no records in our desired state for a key, this
|
||||
// indicates we should delete all records at that key.
|
||||
if len(recs) == 0 {
|
||||
// To delete, we submit the original resource set we got from r53.
|
||||
var (
|
||||
rrset r53Types.ResourceRecordSet
|
||||
found bool
|
||||
)
|
||||
// Find the original resource set:
|
||||
for _, r := range r.originalRecords {
|
||||
if unescape(r.Name) == k.NameFQDN && (string(r.Type) == k.Type || k.Type == "R53_ALIAS_"+string(r.Type)) {
|
||||
rrset = r
|
||||
found = true
|
||||
break
|
||||
for _, k := range updateOrder {
|
||||
recs := updates[k]
|
||||
// If there are no records in our desired state for a key, this
|
||||
// indicates we should delete all records at that key.
|
||||
if len(recs) == 0 {
|
||||
// To delete, we submit the original resource set we got from r53.
|
||||
var (
|
||||
rrset r53Types.ResourceRecordSet
|
||||
found bool
|
||||
)
|
||||
// Find the original resource set:
|
||||
for _, r := range r.originalRecords {
|
||||
if unescape(r.Name) == k.NameFQDN && (string(r.Type) == k.Type || k.Type == "R53_ALIAS_"+string(r.Type)) {
|
||||
rrset = r
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
// This should not happen.
|
||||
return nil, fmt.Errorf("no record set found to delete. Name: '%s'. Type: '%s'", k.NameFQDN, k.Type)
|
||||
}
|
||||
// Assemble the change and add it to the list:
|
||||
chg := r53Types.Change{
|
||||
Action: r53Types.ChangeActionDelete,
|
||||
ResourceRecordSet: &rrset,
|
||||
}
|
||||
dels = append(dels, chg)
|
||||
delDesc = append(delDesc, strings.Join(namesToUpdate[k], "\n"))
|
||||
} else {
|
||||
// If it isn't a delete, it must be either a change or create. In
|
||||
// either case, we build a new record set from the desired state and
|
||||
// UPSERT it.
|
||||
|
||||
if strings.HasPrefix(k.Type, "R53_ALIAS_") {
|
||||
// Each R53_ALIAS_* requires an individual change.
|
||||
if len(recs) != 1 {
|
||||
log.Fatal("Only one R53_ALIAS_ permitted on a label")
|
||||
if !found {
|
||||
// This should not happen.
|
||||
return nil, fmt.Errorf("no record set found to delete. Name: '%s'. Type: '%s'", k.NameFQDN, k.Type)
|
||||
}
|
||||
for _, r := range recs {
|
||||
rrset := aliasToRRSet(zone, r)
|
||||
rrset.Name = aws.String(k.NameFQDN)
|
||||
// Assemble the change and add it to the list:
|
||||
chg := r53Types.Change{
|
||||
Action: r53Types.ChangeActionDelete,
|
||||
ResourceRecordSet: &rrset,
|
||||
}
|
||||
dels = append(dels, chg)
|
||||
delDesc = append(delDesc, strings.Join(namesToUpdate[k], "\n"))
|
||||
} else {
|
||||
// If it isn't a delete, it must be either a change or create. In
|
||||
// either case, we build a new record set from the desired state and
|
||||
// UPSERT it.
|
||||
|
||||
if strings.HasPrefix(k.Type, "R53_ALIAS_") {
|
||||
// Each R53_ALIAS_* requires an individual change.
|
||||
if len(recs) != 1 {
|
||||
log.Fatal("Only one R53_ALIAS_ permitted on a label")
|
||||
}
|
||||
for _, r := range recs {
|
||||
rrset := aliasToRRSet(zone, r)
|
||||
rrset.Name = aws.String(k.NameFQDN)
|
||||
// Assemble the change and add it to the list:
|
||||
chg := r53Types.Change{
|
||||
Action: r53Types.ChangeActionUpsert,
|
||||
ResourceRecordSet: rrset,
|
||||
}
|
||||
changes = append(changes, chg)
|
||||
changeDesc = append(changeDesc, strings.Join(namesToUpdate[k], "\n"))
|
||||
}
|
||||
} else {
|
||||
// All other keys combine their updates into one rrset:
|
||||
rrset := &r53Types.ResourceRecordSet{
|
||||
Name: aws.String(k.NameFQDN),
|
||||
Type: r53Types.RRType(k.Type),
|
||||
}
|
||||
for _, r := range recs {
|
||||
val := r.GetTargetCombined()
|
||||
rr := r53Types.ResourceRecord{
|
||||
Value: aws.String(val),
|
||||
}
|
||||
rrset.ResourceRecords = append(rrset.ResourceRecords, rr)
|
||||
i := int64(r.TTL)
|
||||
rrset.TTL = &i // TODO: make sure that ttls are consistent within a set
|
||||
}
|
||||
// Assemble the change and add it to the list:
|
||||
chg := r53Types.Change{
|
||||
Action: r53Types.ChangeActionUpsert,
|
||||
|
@ -394,79 +419,61 @@ func (r *route53Provider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
|||
changes = append(changes, chg)
|
||||
changeDesc = append(changeDesc, strings.Join(namesToUpdate[k], "\n"))
|
||||
}
|
||||
} else {
|
||||
// All other keys combine their updates into one rrset:
|
||||
rrset := &r53Types.ResourceRecordSet{
|
||||
Name: aws.String(k.NameFQDN),
|
||||
Type: r53Types.RRType(k.Type),
|
||||
}
|
||||
for _, r := range recs {
|
||||
val := r.GetTargetCombined()
|
||||
rr := r53Types.ResourceRecord{
|
||||
Value: aws.String(val),
|
||||
}
|
||||
rrset.ResourceRecords = append(rrset.ResourceRecords, rr)
|
||||
i := int64(r.TTL)
|
||||
rrset.TTL = &i // TODO: make sure that ttls are consistent within a set
|
||||
}
|
||||
// Assemble the change and add it to the list:
|
||||
chg := r53Types.Change{
|
||||
Action: r53Types.ChangeActionUpsert,
|
||||
ResourceRecordSet: rrset,
|
||||
}
|
||||
changes = append(changes, chg)
|
||||
changeDesc = append(changeDesc, strings.Join(namesToUpdate[k], "\n"))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
addCorrection := func(msg string, req *r53.ChangeResourceRecordSetsInput) {
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
var err error
|
||||
req.HostedZoneId = zone.Id
|
||||
withRetry(func() error {
|
||||
_, err = r.client.ChangeResourceRecordSets(context.Background(), req)
|
||||
addCorrection := func(msg string, req *r53.ChangeResourceRecordSetsInput) {
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: msg,
|
||||
F: func() error {
|
||||
var err error
|
||||
req.HostedZoneId = zone.Id
|
||||
withRetry(func() error {
|
||||
_, err = r.client.ChangeResourceRecordSets(context.Background(), req)
|
||||
return err
|
||||
})
|
||||
return err
|
||||
})
|
||||
return err
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
batcher := newChangeBatcher(dels)
|
||||
for batcher.Next() {
|
||||
start, end := batcher.Batch()
|
||||
batch := dels[start:end]
|
||||
descBatchStr := "\n" + strings.Join(delDesc[start:end], "\n") + "\n"
|
||||
req := &r53.ChangeResourceRecordSetsInput{
|
||||
ChangeBatch: &r53Types.ChangeBatch{Changes: batch},
|
||||
}
|
||||
addCorrection(descBatchStr, req)
|
||||
}
|
||||
if err := batcher.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
batcher = newChangeBatcher(changes)
|
||||
for batcher.Next() {
|
||||
start, end := batcher.Batch()
|
||||
batch := changes[start:end]
|
||||
descBatchStr := "\n" + strings.Join(changeDesc[start:end], "\n") + "\n"
|
||||
req := &r53.ChangeResourceRecordSetsInput{
|
||||
ChangeBatch: &r53Types.ChangeBatch{Changes: batch},
|
||||
}
|
||||
addCorrection(descBatchStr, req)
|
||||
}
|
||||
if err := batcher.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
|
||||
}
|
||||
|
||||
batcher := newChangeBatcher(dels)
|
||||
for batcher.Next() {
|
||||
start, end := batcher.Batch()
|
||||
batch := dels[start:end]
|
||||
descBatchStr := "\n" + strings.Join(delDesc[start:end], "\n") + "\n"
|
||||
req := &r53.ChangeResourceRecordSetsInput{
|
||||
ChangeBatch: &r53Types.ChangeBatch{Changes: batch},
|
||||
}
|
||||
addCorrection(descBatchStr, req)
|
||||
}
|
||||
if err := batcher.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
batcher = newChangeBatcher(changes)
|
||||
for batcher.Next() {
|
||||
start, end := batcher.Batch()
|
||||
batch := changes[start:end]
|
||||
descBatchStr := "\n" + strings.Join(changeDesc[start:end], "\n") + "\n"
|
||||
req := &r53.ChangeResourceRecordSetsInput{
|
||||
ChangeBatch: &r53Types.ChangeBatch{Changes: batch},
|
||||
}
|
||||
addCorrection(descBatchStr, req)
|
||||
}
|
||||
if err := batcher.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
|
||||
}
|
||||
|
||||
func nativeToRecords(set r53Types.ResourceRecordSet, origin string) ([]*models.RecordConfig, error) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
|
||||
)
|
||||
|
||||
|
@ -51,44 +52,50 @@ func (api *rwthProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*model
|
|||
models.PostProcessRecords(existingRecords)
|
||||
txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
for _, d := range create {
|
||||
des := d.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return api.createRecord(dc.Name, des) },
|
||||
})
|
||||
}
|
||||
for _, d := range del {
|
||||
existingRecord := d.Existing.Original.(RecordReply)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return api.destroyRecord(existingRecord) },
|
||||
})
|
||||
}
|
||||
for _, d := range modify {
|
||||
rec := d.Desired
|
||||
existingID := d.Existing.Original.(RecordReply).ID
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return api.updateRecord(existingID, *rec) },
|
||||
})
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(existingRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, d := range create {
|
||||
des := d.Desired
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return api.createRecord(dc.Name, des) },
|
||||
})
|
||||
}
|
||||
for _, d := range del {
|
||||
existingRecord := d.Existing.Original.(RecordReply)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return api.destroyRecord(existingRecord) },
|
||||
})
|
||||
}
|
||||
for _, d := range modify {
|
||||
rec := d.Desired
|
||||
existingID := d.Existing.Original.(RecordReply).ID
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: d.String(),
|
||||
F: func() error { return api.updateRecord(existingID, *rec) },
|
||||
})
|
||||
}
|
||||
|
||||
// And deploy if any corrections were applied
|
||||
if len(corrections) > 0 {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: fmt.Sprintf("Deploy zone %s", domain),
|
||||
F: func() error { return api.deployZone(domain) },
|
||||
})
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// And deploy if any corrections were applied
|
||||
if len(corrections) > 0 {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: fmt.Sprintf("Deploy zone %s", domain),
|
||||
F: func() error { return api.deployZone(domain) },
|
||||
})
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
"github.com/softlayer/softlayer-go/datatypes"
|
||||
|
@ -67,7 +68,6 @@ func (s *softlayerProvider) GetZoneRecords(domain string) (models.Records, error
|
|||
|
||||
// GetDomainCorrections returns corrections to update a domain.
|
||||
func (s *softlayerProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||
corrections := []*models.Correction{}
|
||||
|
||||
domain, err := s.getDomain(&dc.Name)
|
||||
|
||||
|
@ -81,33 +81,41 @@ func (s *softlayerProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mo
|
|||
return nil, err
|
||||
}
|
||||
|
||||
_, create, delete, modify, err := diff.New(dc).IncrementalDiff(actual)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
_, create, delete, modify, err := diff.New(dc).IncrementalDiff(actual)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, del := range delete {
|
||||
existing := del.Existing.Original.(datatypes.Dns_Domain_ResourceRecord)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: del.String(),
|
||||
F: s.deleteRecordFunc(*existing.Id),
|
||||
})
|
||||
}
|
||||
|
||||
for _, cre := range create {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: cre.String(),
|
||||
F: s.createRecordFunc(cre.Desired, domain),
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range modify {
|
||||
existing := mod.Existing.Original.(datatypes.Dns_Domain_ResourceRecord)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: mod.String(),
|
||||
F: s.updateRecordFunc(&existing, mod.Desired),
|
||||
})
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
for _, del := range delete {
|
||||
existing := del.Existing.Original.(datatypes.Dns_Domain_ResourceRecord)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: del.String(),
|
||||
F: s.deleteRecordFunc(*existing.Id),
|
||||
})
|
||||
}
|
||||
|
||||
for _, cre := range create {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: cre.String(),
|
||||
F: s.createRecordFunc(cre.Desired, domain),
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range modify {
|
||||
existing := mod.Existing.Original.(datatypes.Dns_Domain_ResourceRecord)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: mod.String(),
|
||||
F: s.updateRecordFunc(&existing, mod.Desired),
|
||||
})
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
"github.com/transip/gotransip/v6"
|
||||
"github.com/transip/gotransip/v6/domain"
|
||||
|
@ -79,7 +80,6 @@ func init() {
|
|||
}
|
||||
|
||||
func (n *transipProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||
var corrections []*models.Correction
|
||||
|
||||
curRecords, err := n.GetZoneRecords(dc.Name)
|
||||
if err != nil {
|
||||
|
@ -94,69 +94,77 @@ func (n *transipProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
|||
|
||||
models.PostProcessRecords(curRecords)
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(curRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
for _, del := range del {
|
||||
entry, err := recordToNative(del.Existing)
|
||||
differ := diff.New(dc)
|
||||
_, create, del, modify, err := differ.IncrementalDiff(curRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: del.String(),
|
||||
F: func() error { return n.domains.RemoveDNSEntry(dc.Name, entry) },
|
||||
})
|
||||
}
|
||||
|
||||
for _, cre := range create {
|
||||
entry, err := recordToNative(cre.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: cre.String(),
|
||||
F: func() error { return n.domains.AddDNSEntry(dc.Name, entry) },
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range modify {
|
||||
targetEntry, err := recordToNative(mod.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TransIP identifies records by (Label, TTL Type), we can only update it if only the contents
|
||||
// has changed. Otherwise we delete the old record and create the new one
|
||||
if canUpdateDNSEntry(mod.Desired, mod.Existing) {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: mod.String(),
|
||||
F: func() error { return n.domains.UpdateDNSEntry(dc.Name, targetEntry) },
|
||||
})
|
||||
} else {
|
||||
oldEntry, err := recordToNative(mod.Existing)
|
||||
for _, del := range del {
|
||||
entry, err := recordToNative(del.Existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: mod.String() + "[1/2]",
|
||||
F: func() error { return n.domains.RemoveDNSEntry(dc.Name, oldEntry) },
|
||||
},
|
||||
&models.Correction{
|
||||
Msg: mod.String() + "[2/2]",
|
||||
F: func() error { return n.domains.AddDNSEntry(dc.Name, targetEntry) },
|
||||
},
|
||||
)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: del.String(),
|
||||
F: func() error { return n.domains.RemoveDNSEntry(dc.Name, entry) },
|
||||
})
|
||||
}
|
||||
|
||||
for _, cre := range create {
|
||||
entry, err := recordToNative(cre.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: cre.String(),
|
||||
F: func() error { return n.domains.AddDNSEntry(dc.Name, entry) },
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range modify {
|
||||
targetEntry, err := recordToNative(mod.Desired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TransIP identifies records by (Label, TTL Type), we can only update it if only the contents
|
||||
// has changed. Otherwise we delete the old record and create the new one
|
||||
if canUpdateDNSEntry(mod.Desired, mod.Existing) {
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: mod.String(),
|
||||
F: func() error { return n.domains.UpdateDNSEntry(dc.Name, targetEntry) },
|
||||
})
|
||||
} else {
|
||||
oldEntry, err := recordToNative(mod.Existing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corrections = append(corrections,
|
||||
&models.Correction{
|
||||
Msg: mod.String() + "[1/2]",
|
||||
F: func() error { return n.domains.RemoveDNSEntry(dc.Name, oldEntry) },
|
||||
},
|
||||
&models.Correction{
|
||||
Msg: mod.String() + "[2/2]",
|
||||
F: func() error { return n.domains.AddDNSEntry(dc.Name, targetEntry) },
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
"github.com/vultr/govultr/v2"
|
||||
)
|
||||
|
@ -117,44 +118,50 @@ func (api *vultrProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode
|
|||
|
||||
models.PostProcessRecords(curRecords)
|
||||
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(curRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var corrections []*models.Correction
|
||||
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
|
||||
|
||||
for _, mod := range delete {
|
||||
id := mod.Existing.Original.(govultr.DomainRecord).ID
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: fmt.Sprintf("%s; Vultr RecordID: %v", mod.String(), id),
|
||||
F: func() error {
|
||||
return api.client.DomainRecord.Delete(context.Background(), dc.Name, id)
|
||||
},
|
||||
})
|
||||
differ := diff.New(dc)
|
||||
_, create, delete, modify, err := differ.IncrementalDiff(curRecords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, mod := range delete {
|
||||
id := mod.Existing.Original.(govultr.DomainRecord).ID
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: fmt.Sprintf("%s; Vultr RecordID: %v", mod.String(), id),
|
||||
F: func() error {
|
||||
return api.client.DomainRecord.Delete(context.Background(), dc.Name, id)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range create {
|
||||
r := toVultrRecord(dc, mod.Desired, "0")
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: mod.String(),
|
||||
F: func() error {
|
||||
_, err := api.client.DomainRecord.Create(context.Background(), dc.Name, &govultr.DomainRecordReq{Name: r.Name, Type: r.Type, Data: r.Data, TTL: r.TTL, Priority: &r.Priority})
|
||||
return err
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range modify {
|
||||
r := toVultrRecord(dc, mod.Desired, mod.Existing.Original.(govultr.DomainRecord).ID)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: fmt.Sprintf("%s; Vultr RecordID: %v", mod.String(), r.ID),
|
||||
F: func() error {
|
||||
return api.client.DomainRecord.Update(context.Background(), dc.Name, r.ID, &govultr.DomainRecordReq{Name: r.Name, Type: r.Type, Data: r.Data, TTL: r.TTL, Priority: &r.Priority})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
for _, mod := range create {
|
||||
r := toVultrRecord(dc, mod.Desired, "0")
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: mod.String(),
|
||||
F: func() error {
|
||||
_, err := api.client.DomainRecord.Create(context.Background(), dc.Name, &govultr.DomainRecordReq{Name: r.Name, Type: r.Type, Data: r.Data, TTL: r.TTL, Priority: &r.Priority})
|
||||
return err
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
for _, mod := range modify {
|
||||
r := toVultrRecord(dc, mod.Desired, mod.Existing.Original.(govultr.DomainRecord).ID)
|
||||
corrections = append(corrections, &models.Correction{
|
||||
Msg: fmt.Sprintf("%s; Vultr RecordID: %v", mod.String(), r.ID),
|
||||
F: func() error {
|
||||
return api.client.DomainRecord.Update(context.Background(), dc.Name, r.ID, &govultr.DomainRecordReq{Name: r.Name, Type: r.Type, Data: r.Data, TTL: r.TTL, Priority: &r.Priority})
|
||||
},
|
||||
})
|
||||
}
|
||||
// Insert Future diff2 version here.
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue