mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
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 (14ff68b151b5db1f24bcdaccb30b6fa95897940a, #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
75 lines
2.1 KiB
Go
75 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)
|
|
}
|
|
}
|
|
|
|
}
|