mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-01-17 21:07:49 +08:00
129 lines
3.1 KiB
Go
129 lines
3.1 KiB
Go
package diff2
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/gobwas/glob"
|
|
|
|
"github.com/StackExchange/dnscontrol/v3/models"
|
|
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
|
|
)
|
|
|
|
func handsoff(
|
|
existing, desired models.Records,
|
|
unmanaged []*models.UnmanagedConfig,
|
|
beSafe bool,
|
|
) (models.Records, error) {
|
|
|
|
// What foreign items should we ignore?
|
|
foreign, err := manyQueries(existing, unmanaged)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(foreign) != 0 {
|
|
printer.Printf("INFO: Foreign records being ignored: (%d)\n", len(foreign))
|
|
for i, r := range foreign {
|
|
printer.Printf("- % 4d: %s %s %s\n", i, r.GetLabelFQDN(), r.Type, r.GetTargetRFC1035Quoted())
|
|
}
|
|
}
|
|
|
|
// What desired items might conflict?
|
|
conflicts, err := manyQueries(desired, unmanaged)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(conflicts) != 0 {
|
|
level := "WARN"
|
|
if beSafe {
|
|
level = "ERROR"
|
|
}
|
|
printer.Printf("%s: dnsconfig.js records that overlap MANAGED: (%d)\n", level, len(conflicts))
|
|
for i, r := range conflicts {
|
|
printer.Printf("- % 4d: %s %s %s\n", i, r.GetLabelFQDN(), r.Type, r.GetTargetRFC1035Quoted())
|
|
}
|
|
if beSafe {
|
|
return nil, fmt.Errorf("ERROR: Unsafe to continue. Add DISABLE_UNMANAGED_SAFETY_CHECK to D() to override")
|
|
}
|
|
}
|
|
|
|
// Add the foreign items to the desired list.
|
|
// (Rather than literally ignoring them, we just add them to the desired list
|
|
// and all the diffing algorithms become more simple.)
|
|
desired = append(desired, foreign...)
|
|
|
|
return desired, nil
|
|
}
|
|
|
|
func manyQueries(rcs models.Records, queries []*models.UnmanagedConfig) (result models.Records, err error) {
|
|
|
|
for _, q := range queries {
|
|
|
|
lab := q.Label
|
|
if lab == "" {
|
|
lab = "*"
|
|
}
|
|
glabel, err := glob.Compile(lab)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
targ := q.Target
|
|
if targ == "" {
|
|
targ = "*"
|
|
}
|
|
gtarget, err := glob.Compile(targ)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
hasRType := compileTypeGlob(q.RType)
|
|
|
|
for _, rc := range rcs {
|
|
if match(rc, glabel, gtarget, hasRType) {
|
|
result = append(result, rc)
|
|
}
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func compileTypeGlob(g string) map[string]bool {
|
|
m := map[string]bool{}
|
|
for _, j := range strings.Split(g, ",") {
|
|
m[strings.TrimSpace(j)] = true
|
|
}
|
|
return m
|
|
}
|
|
|
|
func match(rc *models.RecordConfig, glabel, gtarget glob.Glob, hasRType map[string]bool) bool {
|
|
printer.Printf("DEBUG: match(%v, %v, %v, %v)\n", rc.NameFQDN, glabel, gtarget, hasRType)
|
|
|
|
// _ = glabel.Match(rc.NameFQDN)
|
|
// _ = matchType(rc.Type, hasRType)
|
|
// x := rc.GetTargetField()
|
|
// _ = gtarget.Match(x)
|
|
|
|
if !glabel.Match(rc.NameFQDN) {
|
|
printer.Printf("DEBUG: REJECTED LABEL: %s:%v\n", rc.NameFQDN, glabel)
|
|
return false
|
|
} else if !matchType(rc.Type, hasRType) {
|
|
printer.Printf("DEBUG: REJECTED TYPE: %s:%v\n", rc.Type, hasRType)
|
|
return false
|
|
} else if gtarget == nil {
|
|
return true
|
|
} else if !gtarget.Match(rc.GetTargetField()) {
|
|
printer.Printf("DEBUG: REJECTED TARGET: %v:%v\n", rc.GetTargetField(), gtarget)
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func matchType(s string, hasRType map[string]bool) bool {
|
|
printer.Printf("DEBUG: matchType map=%v\n", hasRType)
|
|
if len(hasRType) == 0 {
|
|
return true
|
|
}
|
|
_, ok := hasRType[s]
|
|
return ok
|
|
}
|