mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-01-11 01:47:53 +08:00
ff8ce26cee
This functionality is required by the GCLOUD provider, which supports
recordsets of type DS but only for child records of the zone, to enable
further delegation. It does not support them at the apex of the zone (@)
because Google Cloud DNS is not itself a registrar which needs to model
this information.
A related change (14ff68b151
, #760) was
previously introduced to enable DS support in Google, which broke
integration tests with this provider.
To cleanly support this, we introduce a new provider capability
CanUseDSForChildren and appropriate integration tests. Further, it is no
longer possible to verify a provider has the proper capabilities for a
zone simply by existence of particular records; we adapt the capability
checks to enable inspection of the individual recordsets where this is
required.
Closes #762
74 lines
2.1 KiB
Go
74 lines
2.1 KiB
Go
package normalize
|
|
|
|
import (
|
|
"go/ast"
|
|
"go/parser"
|
|
"go/token"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
const providersImportDir = "../../providers"
|
|
const providersPackageName = "providers"
|
|
|
|
func TestCapabilitiesAreFiltered(t *testing.T) {
|
|
// Any capabilities which we wish to whitelist because it's not directly
|
|
// something we can test against.
|
|
skipCheckCapabilities := make(map[string]struct{})
|
|
skipCheckCapabilities["CanUseTXTMulti"] = struct{}{}
|
|
|
|
fset := token.NewFileSet()
|
|
pkgs, err := parser.ParseDir(fset, providersImportDir, nil, 0)
|
|
if err != nil {
|
|
t.Fatalf("unable to load Go code from providers: %s", err)
|
|
}
|
|
providers, ok := pkgs[providersPackageName]
|
|
if !ok {
|
|
t.Fatalf("did not find package %q in %q", providersPackageName, providersImportDir)
|
|
}
|
|
|
|
constantNames := make([]string, 0, 50)
|
|
capabilityInts := make(map[string]int, 50)
|
|
|
|
// providers.Scope was nil in my testing
|
|
for fileName := range providers.Files {
|
|
scope := providers.Files[fileName].Scope
|
|
for itemName, obj := range scope.Objects {
|
|
if obj.Kind != ast.Con {
|
|
continue
|
|
}
|
|
// In practice, the object.Type is nil here so we can't filter for
|
|
// capabilities so easily.
|
|
if !strings.HasPrefix(itemName, "CanUse") {
|
|
continue
|
|
}
|
|
constantNames = append(constantNames, itemName)
|
|
capabilityInts[itemName] = obj.Data.(int)
|
|
}
|
|
}
|
|
sort.Strings(constantNames)
|
|
|
|
if len(providerCapabilityChecks) == 0 {
|
|
t.Fatal("missing entries in providerCapabilityChecks")
|
|
}
|
|
|
|
capIntsToNames := make(map[int]string, len(providerCapabilityChecks))
|
|
for _, pair := range providerCapabilityChecks {
|
|
for _, cap := range pair.caps {
|
|
capIntsToNames[int(cap)] = pair.rType
|
|
}
|
|
}
|
|
|
|
for _, capName := range constantNames {
|
|
capInt := capabilityInts[capName]
|
|
if _, ok := skipCheckCapabilities[capName]; ok {
|
|
t.Logf("ok: providers.%s (%d) is exempt from checkProviderCapabilities", capName, capInt)
|
|
} else if rType, ok := capIntsToNames[capInt]; ok {
|
|
t.Logf("ok: providers.%s (%d) is checked for with %q", capName, capInt, rType)
|
|
} else {
|
|
t.Errorf("MISSING: providers.%s (%d) is not checked by checkProviderCapabilities", capName, capInt)
|
|
}
|
|
}
|
|
|
|
}
|