mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-02-26 00:23:00 +08:00
79 lines
2.8 KiB
Go
79 lines
2.8 KiB
Go
package diff
|
|
|
|
import (
|
|
"github.com/StackExchange/dnscontrol/v4/models"
|
|
"github.com/fatih/color"
|
|
)
|
|
|
|
// Correlation stores a difference between two records.
|
|
type Correlation struct {
|
|
d *differ
|
|
Existing *models.RecordConfig
|
|
Desired *models.RecordConfig
|
|
}
|
|
|
|
// Changeset stores many Correlation.
|
|
type Changeset []Correlation
|
|
|
|
// Differ is an interface for computing the difference between two zones.
|
|
type Differ interface {
|
|
// IncrementalDiff performs a diff on a record-by-record basis, and returns a sets for which records need to be created, deleted, or modified.
|
|
IncrementalDiff(existing []*models.RecordConfig) (reportMsgs []string, create, toDelete, modify Changeset, err error)
|
|
// ChangedGroups performs a diff more appropriate for providers with a "RecordSet" model, where all records with the same name and type are grouped.
|
|
// Individual record changes are often not useful in such scenarios. Instead we return a map of record keys to a list of change descriptions within that group.
|
|
ChangedGroups(existing []*models.RecordConfig) (map[models.RecordKey][]string, []string, error)
|
|
}
|
|
|
|
type differ struct {
|
|
}
|
|
|
|
// get normalized content for record. target, ttl, mxprio, and specified metadata
|
|
func (d *differ) content(r *models.RecordConfig) string {
|
|
return r.ToDiffable()
|
|
}
|
|
|
|
// ChangesetLess returns true if c[i] < c[j].
|
|
func ChangesetLess(c Changeset, i, j int) bool {
|
|
var a, b string
|
|
// Which fields are we comparing?
|
|
// Usually only Desired OR Existing content exists (we're either
|
|
// adding or deleting records). In those cases, just use whichever
|
|
// isn't nil.
|
|
// In the case where both Desired AND Existing exist, it doesn't
|
|
// matter which we use as long as we are consistent. I flipped a
|
|
// coin and picked to use Desired in that case.
|
|
|
|
if c[i].Desired != nil {
|
|
a = c[i].Desired.NameFQDN
|
|
} else {
|
|
a = c[i].Existing.NameFQDN
|
|
}
|
|
|
|
if c[j].Desired != nil {
|
|
b = c[j].Desired.NameFQDN
|
|
} else {
|
|
b = c[j].Existing.NameFQDN
|
|
}
|
|
|
|
return a < b
|
|
|
|
// TODO(tlim): This won't correctly sort:
|
|
// []string{"example.com", "foo.example.com", "bar.example.com"}
|
|
// A simple way to do that correctly is to split on ".", reverse the
|
|
// elements, and sort on the result.
|
|
}
|
|
|
|
// CorrectionLess returns true when comparing corrections.
|
|
func CorrectionLess(c []*models.Correction, i, j int) bool {
|
|
return c[i].Msg < c[j].Msg
|
|
}
|
|
|
|
func (c Correlation) String() string {
|
|
if c.Existing == nil {
|
|
return color.GreenString("+ CREATE %s %s %s", c.Desired.Type, c.Desired.GetLabelFQDN(), c.d.content(c.Desired))
|
|
}
|
|
if c.Desired == nil {
|
|
return color.RedString("- DELETE %s %s %s", c.Existing.Type, c.Existing.GetLabelFQDN(), c.d.content(c.Existing))
|
|
}
|
|
return color.YellowString("± MODIFY %s %s: (%s) -> (%s)", c.Existing.Type, c.Existing.GetLabelFQDN(), c.d.content(c.Existing), c.d.content(c.Desired))
|
|
}
|