2016-08-23 08:31:50 +08:00
package diff
import (
2023-05-21 01:21:45 +08:00
"github.com/StackExchange/dnscontrol/v4/models"
2023-02-19 23:54:53 +08:00
"github.com/fatih/color"
2016-08-23 08:31:50 +08:00
)
2022-12-12 06:28:58 +08:00
// Correlation stores a difference between two records.
2017-01-12 03:38:07 +08:00
type Correlation struct {
d * differ
Existing * models . RecordConfig
Desired * models . RecordConfig
}
2018-01-10 01:53:16 +08:00
// Changeset stores many Correlation.
2017-01-12 03:38:07 +08:00
type Changeset [ ] Correlation
2016-08-23 08:31:50 +08:00
2018-01-10 01:53:16 +08:00
// Differ is an interface for computing the difference between two zones.
2017-01-12 03:38:07 +08:00
type Differ interface {
2018-01-10 01:53:16 +08:00
// IncrementalDiff performs a diff on a record-by-record basis, and returns a sets for which records need to be created, deleted, or modified.
2023-10-23 01:56:13 +08:00
IncrementalDiff ( existing [ ] * models . RecordConfig ) ( reportMsgs [ ] string , create , toDelete , modify Changeset , err error )
2017-09-13 23:49:15 +08:00
// 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.
2023-10-23 01:56:13 +08:00
ChangedGroups ( existing [ ] * models . RecordConfig ) ( map [ models . RecordKey ] [ ] string , [ ] string , error )
2022-11-08 00:27:04 +08:00
}
2017-01-12 03:38:07 +08:00
type differ struct {
}
// get normalized content for record. target, ttl, mxprio, and specified metadata
func ( d * differ ) content ( r * models . RecordConfig ) string {
2023-10-23 01:56:13 +08:00
return r . ToDiffable ( )
2016-08-23 08:31:50 +08:00
}
2020-06-18 21:37:57 +08:00
// ChangesetLess returns true if c[i] < c[j].
2020-05-31 00:03:33 +08:00
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.
}
2020-07-07 08:18:24 +08:00
// CorrectionLess returns true when comparing corrections.
2020-07-01 17:55:20 +08:00
func CorrectionLess ( c [ ] * models . Correction , i , j int ) bool {
return c [ i ] . Msg < c [ j ] . Msg
}
2016-08-23 08:31:50 +08:00
func ( c Correlation ) String ( ) string {
if c . Existing == nil {
2023-02-28 14:14:06 +08:00
return color . GreenString ( "+ CREATE %s %s %s" , c . Desired . Type , c . Desired . GetLabelFQDN ( ) , c . d . content ( c . Desired ) )
2016-08-23 08:31:50 +08:00
}
if c . Desired == nil {
2023-02-28 14:14:06 +08:00
return color . RedString ( "- DELETE %s %s %s" , c . Existing . Type , c . Existing . GetLabelFQDN ( ) , c . d . content ( c . Existing ) )
2017-01-12 03:38:07 +08:00
}
2023-02-19 23:54:53 +08:00
return color . YellowString ( "± MODIFY %s %s: (%s) -> (%s)" , c . Existing . Type , c . Existing . GetLabelFQDN ( ) , c . d . content ( c . Existing ) , c . d . content ( c . Desired ) )
2017-01-12 03:38:07 +08:00
}