dns: ignore TXT errors unless GRPC_GO_IGNORE_TXT_ERRORS=false (#3299)

This commit is contained in:
Doug Fawley 2020-01-07 13:08:22 -08:00 committed by GitHub
parent cf9eb4f51c
commit b91517cd56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 3 deletions

View File

@ -25,11 +25,14 @@ import (
)
const (
prefix = "GRPC_GO_"
retryStr = prefix + "RETRY"
prefix = "GRPC_GO_"
retryStr = prefix + "RETRY"
txtErrIgnoreStr = prefix + "IGNORE_TXT_ERRORS"
)
var (
// Retry is set if retry is explicitly enabled via "GRPC_GO_RETRY=on".
Retry = strings.EqualFold(os.Getenv(retryStr), "on")
// TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false").
TXTErrIgnore = !strings.EqualFold(os.Getenv(retryStr), "false")
)

View File

@ -33,6 +33,7 @@ import (
"time"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/internal/envconfig"
"google.golang.org/grpc/internal/grpcrand"
"google.golang.org/grpc/resolver"
"google.golang.org/grpc/serviceconfig"
@ -278,6 +279,9 @@ func handleDNSError(err error, lookupType string) error {
func (d *dnsResolver) lookupTXT() *serviceconfig.ParseResult {
ss, err := d.resolver.LookupTXT(d.ctx, txtPrefix+d.host)
if err != nil {
if envconfig.TXTErrIgnore {
return nil
}
if err = handleDNSError(err, "TXT"); err != nil {
return &serviceconfig.ParseResult{Err: err}
}

View File

@ -30,6 +30,7 @@ import (
"testing"
"time"
"google.golang.org/grpc/internal/envconfig"
"google.golang.org/grpc/internal/leakcheck"
"google.golang.org/grpc/resolver"
"google.golang.org/grpc/serviceconfig"
@ -830,7 +831,11 @@ func mutateTbl(target string) func() {
hostLookupTbl.tbl[target] = oldHostTblEntry
hostLookupTbl.Unlock()
txtLookupTbl.Lock()
txtLookupTbl.tbl[txtPrefix+target] = oldTxtTblEntry
if len(oldTxtTblEntry) == 0 {
delete(txtLookupTbl.tbl, txtPrefix+target)
} else {
txtLookupTbl.tbl[txtPrefix+target] = oldTxtTblEntry
}
txtLookupTbl.Unlock()
}
}
@ -1039,6 +1044,38 @@ func TestDisableServiceConfig(t *testing.T) {
}
}
func TestTXTError(t *testing.T) {
defer leakcheck.Check(t)
defer func(v bool) { envconfig.TXTErrIgnore = v }(envconfig.TXTErrIgnore)
for _, ignore := range []bool{false, true} {
envconfig.TXTErrIgnore = ignore
b := NewBuilder()
cc := &testClientConn{target: "ipv4.single.fake"} // has A records but not TXT records.
r, err := b.Build(resolver.Target{Endpoint: "ipv4.single.fake"}, cc, resolver.BuildOptions{})
if err != nil {
t.Fatalf("%v\n", err)
}
defer r.Close()
var cnt int
var state resolver.State
for i := 0; i < 2000; i++ {
state, cnt = cc.getState()
if cnt > 0 {
break
}
time.Sleep(time.Millisecond)
}
if cnt == 0 {
t.Fatalf("UpdateState not called after 2s; aborting")
}
if !ignore && (state.ServiceConfig == nil || state.ServiceConfig.Err == nil) {
t.Errorf("state.ServiceConfig = %v; want non-nil error", state.ServiceConfig)
} else if ignore && state.ServiceConfig != nil {
t.Errorf("state.ServiceConfig = %v; want nil", state.ServiceConfig)
}
}
}
func TestDNSResolverRetry(t *testing.T) {
b := NewBuilder()
target := "ipv4.single.fake"