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