diff --git a/.golangci.yml b/.golangci.yml index 29eec3fe0..6dfae1b2f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -10,6 +10,7 @@ linters: - canonicalheader - copyloopvar - durationcheck + - errorlint - godoclint - gosec - govet diff --git a/core/dnsserver/server_grpc_test.go b/core/dnsserver/server_grpc_test.go index 3a74b1677..dc10dce8e 100644 --- a/core/dnsserver/server_grpc_test.go +++ b/core/dnsserver/server_grpc_test.go @@ -457,7 +457,7 @@ func TestGRPCResponseTsigStatusReturnsStoredStatus(t *testing.T) { tsigStatus: want, } - if got := r.TsigStatus(); got != want { + if got := r.TsigStatus(); !errors.Is(got, want) { t.Fatalf("TsigStatus() = %v, want %v", got, want) } } diff --git a/core/dnsserver/server_https_test.go b/core/dnsserver/server_https_test.go index e36c3d1d1..872f47ac9 100644 --- a/core/dnsserver/server_https_test.go +++ b/core/dnsserver/server_https_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "crypto/tls" + "errors" "io" "net" "net/http" @@ -579,7 +580,7 @@ func TestServeHTTPAcceptsValidTSIG(t *testing.T) { func TestDoHWriterTsigStatusReturnsStoredStatus(t *testing.T) { dw := &DoHWriter{tsigStatus: dns.ErrSecret} - if dw.TsigStatus() != dns.ErrSecret { + if !errors.Is(dw.TsigStatus(), dns.ErrSecret) { t.Fatal("expected TsigStatus to return stored tsigStatus") } } diff --git a/core/dnsserver/server_quic.go b/core/dnsserver/server_quic.go index 0deb80c37..6e1cc6a41 100644 --- a/core/dnsserver/server_quic.go +++ b/core/dnsserver/server_quic.go @@ -191,7 +191,7 @@ func (s *ServerQUIC) serveQUICStream(stream *quic.Stream, conn *quic.Conn) { // io.EOF does not really mean that there's any error, it is just // the STREAM FIN indicating that there will be no data to read // anymore from this stream. - if err != nil && err != io.EOF { + if err != nil && !errors.Is(err, io.EOF) { s.closeQUICConn(conn, DoQCodeProtocolError) return diff --git a/core/dnsserver/server_quic_test.go b/core/dnsserver/server_quic_test.go index 28d8931be..878c6bb69 100644 --- a/core/dnsserver/server_quic_test.go +++ b/core/dnsserver/server_quic_test.go @@ -455,7 +455,7 @@ func TestDoQWriterTsigStatusReturnsStoredStatus(t *testing.T) { tsigStatus: want, } - if got := w.TsigStatus(); got != want { + if got := w.TsigStatus(); !errors.Is(got, want) { t.Fatalf("TsigStatus() = %v, want %v", got, want) } } diff --git a/plugin/autopath/setup.go b/plugin/autopath/setup.go index a041e364c..d3dfe6fa3 100644 --- a/plugin/autopath/setup.go +++ b/plugin/autopath/setup.go @@ -57,7 +57,7 @@ func autoPathParse(c *caddy.Controller) (*AutoPath, string, error) { // assume file on disk rc, err := dns.ClientConfigFromFile(resolv) if err != nil { - return ap, "", fmt.Errorf("failed to parse %q: %v", resolv, err) + return ap, "", fmt.Errorf("failed to parse %q: %w", resolv, err) } ap.search = rc.Search plugin.Zones(ap.search).Normalize() diff --git a/plugin/azure/azure_test.go b/plugin/azure/azure_test.go index 9be2695f0..3b1649ffe 100644 --- a/plugin/azure/azure_test.go +++ b/plugin/azure/azure_test.go @@ -2,6 +2,7 @@ package azure import ( "context" + "errors" "reflect" "testing" @@ -141,7 +142,7 @@ func TestAzure(t *testing.T) { rec := dnstest.NewRecorder(&test.ResponseWriter{}) code, err := demoAzure.ServeDNS(context.Background(), rec, req) - if err != tc.expectedErr { + if !errors.Is(err, tc.expectedErr) { t.Fatalf("Test %d: Expected error %v, but got %v", ti, tc.expectedErr, err) } diff --git a/plugin/bind/setup.go b/plugin/bind/setup.go index 1e3ac53f0..a853e1560 100644 --- a/plugin/bind/setup.go +++ b/plugin/bind/setup.go @@ -18,7 +18,7 @@ func setup(c *caddy.Controller) error { all := []string{} ifaces, err := net.Interfaces() if err != nil { - log.Warning(plugin.Error("bind", fmt.Errorf("failed to get interfaces list, cannot bind by interface name: %s", err))) + log.Warning(plugin.Error("bind", fmt.Errorf("failed to get interfaces list, cannot bind by interface name: %w", err))) } for c.Next() { diff --git a/plugin/chaos/chaos_test.go b/plugin/chaos/chaos_test.go index e5d4a55aa..c2cf640ce 100644 --- a/plugin/chaos/chaos_test.go +++ b/plugin/chaos/chaos_test.go @@ -2,6 +2,7 @@ package chaos import ( "context" + "errors" "testing" "github.com/coredns/coredns/plugin" @@ -62,7 +63,7 @@ func TestChaos(t *testing.T) { rec := dnstest.NewRecorder(&test.ResponseWriter{}) code, err := em.ServeDNS(ctx, rec, req) - if err != tc.expectedErr { + if !errors.Is(err, tc.expectedErr) { t.Errorf("Test %d: Expected error %v, but got %v", i, tc.expectedErr, err) } if code != tc.expectedCode { diff --git a/plugin/clouddns/clouddns.go b/plugin/clouddns/clouddns.go index 08b842848..9dfdaabd7 100644 --- a/plugin/clouddns/clouddns.go +++ b/plugin/clouddns/clouddns.go @@ -165,12 +165,12 @@ func updateZoneFromRRS(rrs *gcp.ResourceRecordSetsListResponse, z *file.Zone) er rfc1035 = fmt.Sprintf("%s %d IN %s %s", dns.Fqdn(rr.Name), rr.Ttl, rr.Type, value) r, err = dns.NewRR(rfc1035) if err != nil { - return fmt.Errorf("failed to parse resource record: %v", err) + return fmt.Errorf("failed to parse resource record: %w", err) } err = z.Insert(r) if err != nil { - return fmt.Errorf("failed to insert record: %v", err) + return fmt.Errorf("failed to insert record: %w", err) } } } @@ -197,7 +197,7 @@ func (h *CloudDNS) updateZones(ctx context.Context) error { newZ.Upstream = h.upstream rrListResponse, err = h.client.listRRSets(ctx, hostedZone.projectName, hostedZone.zoneName) if err != nil { - err = fmt.Errorf("failed to list resource records for %v:%v:%v from gcp: %v", zName, hostedZone.projectName, hostedZone.zoneName, err) + err = fmt.Errorf("failed to list resource records for %v:%v:%v from gcp: %w", zName, hostedZone.projectName, hostedZone.zoneName, err) return } updateZoneFromRRS(rrListResponse, newZ) diff --git a/plugin/clouddns/clouddns_test.go b/plugin/clouddns/clouddns_test.go index d42354415..4b95992cd 100644 --- a/plugin/clouddns/clouddns_test.go +++ b/plugin/clouddns/clouddns_test.go @@ -291,7 +291,7 @@ func TestCloudDNS(t *testing.T) { rec := dnstest.NewRecorder(&test.ResponseWriter{}) code, err := r.ServeDNS(ctx, rec, req) - if err != tc.expectedErr { + if !errors.Is(err, tc.expectedErr) { t.Fatalf("Test %d: Expected error %v, but got %v", ti, tc.expectedErr, err) } if code != tc.wantRetCode { diff --git a/plugin/erratic/erratic_test.go b/plugin/erratic/erratic_test.go index de8dbe4d6..7eb66f9f3 100644 --- a/plugin/erratic/erratic_test.go +++ b/plugin/erratic/erratic_test.go @@ -2,6 +2,7 @@ package erratic import ( "context" + "errors" "testing" "github.com/coredns/coredns/plugin/pkg/dnstest" @@ -34,7 +35,7 @@ func TestErraticDrop(t *testing.T) { rec := dnstest.NewRecorder(&test.ResponseWriter{}) code, err := e.ServeDNS(ctx, rec, req) - if err != tc.expectedErr { + if !errors.Is(err, tc.expectedErr) { t.Errorf("Test %d: Expected error %q, but got %q", i, tc.expectedErr, err) } if code != tc.expectedCode { @@ -68,7 +69,7 @@ func TestErraticTruncate(t *testing.T) { rec := dnstest.NewRecorder(&test.ResponseWriter{}) code, err := e.ServeDNS(ctx, rec, req) - if err != tc.expectedErr { + if !errors.Is(err, tc.expectedErr) { t.Errorf("Test %d: Expected error %q, but got %q", i, tc.expectedErr, err) } if code != tc.expectedCode { diff --git a/plugin/errors/errors_test.go b/plugin/errors/errors_test.go index 4c0f2a190..936803251 100644 --- a/plugin/errors/errors_test.go +++ b/plugin/errors/errors_test.go @@ -56,7 +56,7 @@ func TestErrors(t *testing.T) { rec := dnstest.NewRecorder(&test.ResponseWriter{}) code, err := em.ServeDNS(ctx, rec, req) - if err != tc.expectedErr { + if !errors.Is(err, tc.expectedErr) { t.Errorf("Test %d: Expected error %v, but got %v", i, tc.expectedErr, err) } diff --git a/plugin/etcd/etcd.go b/plugin/etcd/etcd.go index 09e295d5e..662f16e40 100644 --- a/plugin/etcd/etcd.go +++ b/plugin/etcd/etcd.go @@ -67,7 +67,7 @@ func (e *Etcd) Lookup(ctx context.Context, state request.Request, name string, t // IsNameError implements the ServiceBackend interface. func (e *Etcd) IsNameError(err error) bool { - return err == errKeyNotFound + return errors.Is(err, errKeyNotFound) } // Records looks up records in etcd. If exact is true, it will lookup just this diff --git a/plugin/file/file.go b/plugin/file/file.go index c3b541e6c..e562372c8 100644 --- a/plugin/file/file.go +++ b/plugin/file/file.go @@ -167,7 +167,7 @@ func Parse(f io.Reader, origin, fileName string, serial int64) (*Zone, error) { } } if zp.Err() != nil { - return nil, fmt.Errorf("failed to parse file %q for origin %s with error %v", fileName, origin, zp.Err()) + return nil, fmt.Errorf("failed to parse file %q for origin %s with error %w", fileName, origin, zp.Err()) } if !seenSOA { return nil, fmt.Errorf("file %q has no SOA record for origin %s", fileName, origin) diff --git a/plugin/file/reload.go b/plugin/file/reload.go index afba78a34..2c53fd53f 100644 --- a/plugin/file/reload.go +++ b/plugin/file/reload.go @@ -1,6 +1,7 @@ package file import ( + "errors" "os" "path/filepath" "time" @@ -30,7 +31,8 @@ func (z *Zone) Reload(t *transfer.Transfer) error { zone, err := Parse(reader, z.origin, zFile, serial) reader.Close() if err != nil { - if _, ok := err.(*serialErr); !ok { + var serialErr *serialErr + if !errors.As(err, &serialErr) { log.Errorf("Parsing zone %q: %v", z.origin, err) } continue diff --git a/plugin/forward/forward.go b/plugin/forward/forward.go index f8e1ffca8..dac767db9 100644 --- a/plugin/forward/forward.go +++ b/plugin/forward/forward.go @@ -169,7 +169,7 @@ func (f *Forward) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg for { ret, err = proxy.Connect(ctx, state, opts) - if err == proxyPkg.ErrCachedClosed { // Remote side closed conn, can only happen with TCP. + if errors.Is(err, proxyPkg.ErrCachedClosed) { // Remote side closed conn, can only happen with TCP. continue } // Retry with TCP if truncated and prefer_udp configured. diff --git a/plugin/forward/health_test.go b/plugin/forward/health_test.go index 677dbd7b3..45ce4217c 100644 --- a/plugin/forward/health_test.go +++ b/plugin/forward/health_test.go @@ -2,6 +2,7 @@ package forward import ( "context" + "errors" "sync/atomic" "testing" "time" @@ -343,8 +344,8 @@ func TestAllUpstreamsDown(t *testing.T) { t.Errorf("Expected Response code: %d, Got: %d", dns.RcodeServerFailure, resp) } - if err != ErrNoHealthy { - t.Errorf("Expected error message: no healthy proxies, Got: %s", err.Error()) + if !errors.Is(err, ErrNoHealthy) { + t.Errorf("Expected error message: no healthy proxies, Got: %v", err) } q1 := atomic.LoadUint32(&qs) @@ -358,7 +359,7 @@ func TestAllUpstreamsDown(t *testing.T) { req = new(dns.Msg) req.SetQuestion("example.org.", dns.TypeA) _, err = f.ServeDNS(context.TODO(), &test.ResponseWriter{}, req) - if err == ErrNoHealthy { + if errors.Is(err, ErrNoHealthy) { t.Error("Unexpected error message: no healthy proxies") } diff --git a/plugin/geoip/geoip.go b/plugin/geoip/geoip.go index 85bf8f273..146651bc1 100644 --- a/plugin/geoip/geoip.go +++ b/plugin/geoip/geoip.go @@ -3,6 +3,7 @@ package geoip import ( "context" + "errors" "fmt" "net/netip" "path/filepath" @@ -42,7 +43,7 @@ var probingIP = netip.MustParseAddr("127.0.0.1") func newGeoIP(dbPath string, edns0 bool) (*GeoIP, error) { reader, err := geoip2.Open(dbPath) if err != nil { - return nil, fmt.Errorf("failed to open database file: %v", err) + return nil, fmt.Errorf("failed to open database file: %w", err) } db := db{Reader: reader} schemas := []struct { @@ -57,8 +58,9 @@ func newGeoIP(dbPath string, edns0 bool) (*GeoIP, error) { for _, schema := range schemas { if err := schema.validate(); err != nil { // If we get an InvalidMethodError then we know this database does not provide that schema. - if _, ok := err.(geoip2.InvalidMethodError); !ok { - return nil, fmt.Errorf("unexpected failure looking up database %q schema %q: %v", filepath.Base(dbPath), schema.name, err) + var invalidMethodErr geoip2.InvalidMethodError + if !errors.As(err, &invalidMethodErr) { + return nil, fmt.Errorf("unexpected failure looking up database %q schema %q: %w", filepath.Base(dbPath), schema.name, err) } } else { db.provides |= schema.provides diff --git a/plugin/health/setup.go b/plugin/health/setup.go index e9163ad44..c078dfc79 100644 --- a/plugin/health/setup.go +++ b/plugin/health/setup.go @@ -54,7 +54,7 @@ func parse(c *caddy.Controller) (string, time.Duration, error) { } l, err := time.ParseDuration(args[0]) if err != nil { - return "", 0, fmt.Errorf("unable to parse lameduck duration value: '%v' : %v", args[0], err) + return "", 0, fmt.Errorf("unable to parse lameduck duration value: %q: %w", args[0], err) } dur = l default: diff --git a/plugin/k8s_external/apex_test.go b/plugin/k8s_external/apex_test.go index ab0818708..5422bf021 100644 --- a/plugin/k8s_external/apex_test.go +++ b/plugin/k8s_external/apex_test.go @@ -2,6 +2,7 @@ package external import ( "context" + "errors" "testing" "github.com/coredns/coredns/plugin/kubernetes" @@ -30,7 +31,7 @@ func TestApex(t *testing.T) { w := dnstest.NewRecorder(&test.ResponseWriter{}) _, err := e.ServeDNS(ctx, w, r) - if err != tc.Error { + if !errors.Is(err, tc.Error) { t.Errorf("Test %d expected no error, got %v", i, err) return } diff --git a/plugin/k8s_external/external_test.go b/plugin/k8s_external/external_test.go index 331930831..4cf0eb6b4 100644 --- a/plugin/k8s_external/external_test.go +++ b/plugin/k8s_external/external_test.go @@ -2,6 +2,7 @@ package external import ( "context" + "errors" "testing" "github.com/coredns/coredns/plugin/kubernetes" @@ -33,7 +34,7 @@ func TestExternal(t *testing.T) { w := dnstest.NewRecorder(&test.ResponseWriter{}) _, err := e.ServeDNS(ctx, w, r) - if err != tc.Error { + if !errors.Is(err, tc.Error) { t.Errorf("Test %d expected no error, got %v", i, err) return } diff --git a/plugin/kubernetes/handler_case_test.go b/plugin/kubernetes/handler_case_test.go index c3f90f1eb..b32be4957 100644 --- a/plugin/kubernetes/handler_case_test.go +++ b/plugin/kubernetes/handler_case_test.go @@ -2,6 +2,7 @@ package kubernetes import ( "context" + "errors" "testing" "github.com/coredns/coredns/plugin/pkg/dnstest" @@ -60,7 +61,7 @@ func TestPreserveCase(t *testing.T) { w := dnstest.NewRecorder(&test.ResponseWriter{}) _, err := k.ServeDNS(ctx, w, r) - if err != tc.Error { + if !errors.Is(err, tc.Error) { t.Errorf("Test %d expected no error, got %v", i, err) return } diff --git a/plugin/kubernetes/handler_ignore_emptyservice_test.go b/plugin/kubernetes/handler_ignore_emptyservice_test.go index 7af77fe1b..d22e4d227 100644 --- a/plugin/kubernetes/handler_ignore_emptyservice_test.go +++ b/plugin/kubernetes/handler_ignore_emptyservice_test.go @@ -2,6 +2,7 @@ package kubernetes import ( "context" + "errors" "testing" "github.com/coredns/coredns/plugin/pkg/dnstest" @@ -42,7 +43,7 @@ func TestServeDNSEmptyService(t *testing.T) { w := dnstest.NewRecorder(&test.ResponseWriter{}) _, err := k.ServeDNS(ctx, w, r) - if err != tc.Error { + if !errors.Is(err, tc.Error) { t.Errorf("Test %d expected no error, got %v", i, err) return } diff --git a/plugin/kubernetes/handler_pod_disabled_test.go b/plugin/kubernetes/handler_pod_disabled_test.go index be7e7a37b..c918c7084 100644 --- a/plugin/kubernetes/handler_pod_disabled_test.go +++ b/plugin/kubernetes/handler_pod_disabled_test.go @@ -2,6 +2,7 @@ package kubernetes import ( "context" + "errors" "testing" "github.com/coredns/coredns/plugin/pkg/dnstest" @@ -40,7 +41,7 @@ func TestServeDNSModeDisabled(t *testing.T) { w := dnstest.NewRecorder(&test.ResponseWriter{}) _, err := k.ServeDNS(ctx, w, r) - if err != tc.Error { + if !errors.Is(err, tc.Error) { t.Errorf("Test %d got unexpected error %v", i, err) return } diff --git a/plugin/kubernetes/handler_pod_insecure_test.go b/plugin/kubernetes/handler_pod_insecure_test.go index b01d53f9e..e8e1788c1 100644 --- a/plugin/kubernetes/handler_pod_insecure_test.go +++ b/plugin/kubernetes/handler_pod_insecure_test.go @@ -2,6 +2,7 @@ package kubernetes import ( "context" + "errors" "testing" "github.com/coredns/coredns/plugin/pkg/dnstest" @@ -75,7 +76,7 @@ func TestServeDNSModeInsecure(t *testing.T) { w := dnstest.NewRecorder(&test.ResponseWriter{}) _, err := k.ServeDNS(ctx, w, r) - if err != tc.Error { + if !errors.Is(err, tc.Error) { t.Errorf("Test %d expected no error, got %v", i, err) return } diff --git a/plugin/kubernetes/handler_pod_verified_test.go b/plugin/kubernetes/handler_pod_verified_test.go index c8b09c4f5..760368a07 100644 --- a/plugin/kubernetes/handler_pod_verified_test.go +++ b/plugin/kubernetes/handler_pod_verified_test.go @@ -2,6 +2,7 @@ package kubernetes import ( "context" + "errors" "testing" "github.com/coredns/coredns/plugin/pkg/dnstest" @@ -61,7 +62,7 @@ func TestServeDNSModeVerified(t *testing.T) { w := dnstest.NewRecorder(&test.ResponseWriter{}) _, err := k.ServeDNS(ctx, w, r) - if err != tc.Error { + if !errors.Is(err, tc.Error) { t.Errorf("Test %d expected no error, got %v", i, err) return } diff --git a/plugin/kubernetes/handler_test.go b/plugin/kubernetes/handler_test.go index ce0e50c74..230f56d29 100644 --- a/plugin/kubernetes/handler_test.go +++ b/plugin/kubernetes/handler_test.go @@ -2,6 +2,7 @@ package kubernetes import ( "context" + "errors" "fmt" "testing" @@ -436,7 +437,7 @@ func TestServeDNS(t *testing.T) { w := dnstest.NewRecorder(&test.ResponseWriter{}) _, err := k.ServeDNS(ctx, w, r) - if err != tc.Error { + if !errors.Is(err, tc.Error) { t.Errorf("Test %d expected no error, got %v", i, err) return } @@ -568,7 +569,7 @@ func TestMultiClusterServeDNS(t *testing.T) { w := dnstest.NewRecorder(&test.ResponseWriter{}) _, err := k.ServeDNS(ctx, w, r) - if err != tc.Error { + if !errors.Is(err, tc.Error) { t.Errorf("Test %d expected no error, got %v", i, err) return } @@ -629,7 +630,7 @@ func TestServeNamespaceDNS(t *testing.T) { w := dnstest.NewRecorder(&test.ResponseWriter{}) _, err := k.ServeDNS(ctx, w, r) - if err != tc.Error { + if !errors.Is(err, tc.Error) { t.Errorf("Test %d expected no error, got %v", i, err) return } @@ -675,7 +676,7 @@ func TestNotSyncedServeDNS(t *testing.T) { w := dnstest.NewRecorder(&test.ResponseWriter{}) _, err := k.ServeDNS(ctx, w, r) - if err != tc.Error { + if !errors.Is(err, tc.Error) { t.Errorf("Test %d expected no error, got %v", i, err) return } diff --git a/plugin/kubernetes/kubernetes.go b/plugin/kubernetes/kubernetes.go index 72d43a272..69db6daac 100644 --- a/plugin/kubernetes/kubernetes.go +++ b/plugin/kubernetes/kubernetes.go @@ -181,7 +181,7 @@ func (k *Kubernetes) Lookup(ctx context.Context, state request.Request, name str // IsNameError implements the ServiceBackend interface. func (k *Kubernetes) IsNameError(err error) bool { - return err == errNoItems || err == errNsNotExposed || err == errInvalidRequest + return errors.Is(err, errNoItems) || errors.Is(err, errNsNotExposed) || errors.Is(err, errInvalidRequest) } func (k *Kubernetes) getClientConfig() (*rest.Config, error) { @@ -240,14 +240,14 @@ func (k *Kubernetes) InitKubeCache(ctx context.Context) (onStart func() error, o kubeClient, err := kubernetes.NewForConfig(config) if err != nil { - return nil, nil, fmt.Errorf("failed to create kubernetes notification controller: %q", err) + return nil, nil, fmt.Errorf("failed to create kubernetes notification controller: %w", err) } var mcsClient mcsClientset.MulticlusterV1alpha1Interface if len(k.opts.multiclusterZones) > 0 { mcsClient, err = mcsClientset.NewForConfig(config) if err != nil { - return nil, nil, fmt.Errorf("failed to create kubernetes multicluster notification controller: %q", err) + return nil, nil, fmt.Errorf("failed to create kubernetes multicluster notification controller: %w", err) } } @@ -255,7 +255,7 @@ func (k *Kubernetes) InitKubeCache(ctx context.Context) (onStart func() error, o var selector labels.Selector selector, err = meta.LabelSelectorAsSelector(k.opts.labelSelector) if err != nil { - return nil, nil, fmt.Errorf("unable to create Selector for LabelSelector '%s': %q", k.opts.labelSelector, err) + return nil, nil, fmt.Errorf("unable to create Selector for LabelSelector %q: %w", k.opts.labelSelector, err) } k.opts.selector = selector } @@ -264,7 +264,7 @@ func (k *Kubernetes) InitKubeCache(ctx context.Context) (onStart func() error, o var selector labels.Selector selector, err = meta.LabelSelectorAsSelector(k.opts.namespaceLabelSelector) if err != nil { - return nil, nil, fmt.Errorf("unable to create Selector for LabelSelector '%s': %q", k.opts.namespaceLabelSelector, err) + return nil, nil, fmt.Errorf("unable to create Selector for LabelSelector %q: %w", k.opts.namespaceLabelSelector, err) } k.opts.namespaceSelector = selector } diff --git a/plugin/kubernetes/kubernetes_apex_test.go b/plugin/kubernetes/kubernetes_apex_test.go index 7531e2141..c110cf0fc 100644 --- a/plugin/kubernetes/kubernetes_apex_test.go +++ b/plugin/kubernetes/kubernetes_apex_test.go @@ -2,6 +2,7 @@ package kubernetes import ( "context" + "errors" "net" "testing" @@ -72,7 +73,7 @@ func TestServeDNSApex(t *testing.T) { w := dnstest.NewRecorder(&test.ResponseWriter{}) _, err := k.ServeDNS(ctx, w, r) - if err != tc.Error { + if !errors.Is(err, tc.Error) { t.Errorf("Test %d, expected no error, got %v", i, err) return } diff --git a/plugin/kubernetes/object/informer.go b/plugin/kubernetes/object/informer.go index 4ed0eb8e2..6f74798fd 100644 --- a/plugin/kubernetes/object/informer.go +++ b/plugin/kubernetes/object/informer.go @@ -1,6 +1,7 @@ package object import ( + "errors" "fmt" meta "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -39,7 +40,7 @@ func DefaultProcessor(convert ToFunc, recordLatency *EndpointLatencyRecorder) Pr case cache.Sync, cache.Added, cache.Updated: obj, err := convert(d.Object.(meta.Object)) if err != nil { - if err == errPodTerminating { + if errors.Is(err, errPodTerminating) { continue } return err @@ -68,7 +69,7 @@ func DefaultProcessor(convert ToFunc, recordLatency *EndpointLatencyRecorder) Pr return fmt.Errorf("unexpected object %v", d.Object) } obj, err = convert(metaObj) - if err != nil && err != errPodTerminating { + if err != nil && !errors.Is(err, errPodTerminating) { return err } } diff --git a/plugin/kubernetes/reverse_test.go b/plugin/kubernetes/reverse_test.go index 143d84ed7..346fdfb17 100644 --- a/plugin/kubernetes/reverse_test.go +++ b/plugin/kubernetes/reverse_test.go @@ -2,6 +2,7 @@ package kubernetes import ( "context" + "errors" "testing" "github.com/coredns/coredns/plugin/kubernetes/object" @@ -243,7 +244,7 @@ func TestReverse(t *testing.T) { w := dnstest.NewRecorder(&test.ResponseWriter{}) _, err := k.ServeDNS(ctx, w, r) - if err != tc.Error { + if !errors.Is(err, tc.Error) { t.Errorf("Test %d: expected no error, got %v", i, err) return } diff --git a/plugin/kubernetes/setup.go b/plugin/kubernetes/setup.go index e054452c5..aeb2d9c4d 100644 --- a/plugin/kubernetes/setup.go +++ b/plugin/kubernetes/setup.go @@ -169,7 +169,7 @@ func ParseStanza(c *caddy.Controller) (*Kubernetes, error) { labelSelectorString := strings.Join(args, " ") ls, err := meta.ParseToLabelSelector(labelSelectorString) if err != nil { - return nil, fmt.Errorf("unable to parse label selector value: '%v': %v", labelSelectorString, err) + return nil, fmt.Errorf("unable to parse label selector value %q: %w", labelSelectorString, err) } k8s.opts.labelSelector = ls continue @@ -181,7 +181,7 @@ func ParseStanza(c *caddy.Controller) (*Kubernetes, error) { namespaceLabelSelectorString := strings.Join(args, " ") nls, err := meta.ParseToLabelSelector(namespaceLabelSelectorString) if err != nil { - return nil, fmt.Errorf("unable to parse namespace_label selector value: '%v': %v", namespaceLabelSelectorString, err) + return nil, fmt.Errorf("unable to parse namespace_label selector value %q: %w", namespaceLabelSelectorString, err) } k8s.opts.namespaceLabelSelector = nls continue @@ -241,7 +241,7 @@ func ParseStanza(c *caddy.Controller) (*Kubernetes, error) { var err error k8s.startupTimeout, err = time.ParseDuration(args[0]) if err != nil { - return nil, fmt.Errorf("failed to parse startup_timeout: %v, %s", args[0], err) + return nil, fmt.Errorf("failed to parse startup_timeout %q: %w", args[0], err) } case "apiserver_qps": args := c.RemainingArgs() diff --git a/plugin/kubernetes/xfr_test.go b/plugin/kubernetes/xfr_test.go index ebc876e33..ef9399ed1 100644 --- a/plugin/kubernetes/xfr_test.go +++ b/plugin/kubernetes/xfr_test.go @@ -1,6 +1,7 @@ package kubernetes import ( + "errors" "net" "strings" "testing" @@ -20,7 +21,7 @@ func TestKubernetesTransferNonAuthZone(t *testing.T) { dnsmsg.SetAxfr("example.com") _, err := k.Transfer("example.com", 0) - if err != transfer.ErrNotAuthoritative { + if !errors.Is(err, transfer.ErrNotAuthoritative) { t.Error(err) } } diff --git a/plugin/loadbalance/weighted.go b/plugin/loadbalance/weighted.go index 791d0b345..286cf08a5 100644 --- a/plugin/loadbalance/weighted.go +++ b/plugin/loadbalance/weighted.go @@ -322,7 +322,7 @@ func (w *weightedRR) parseWeights(scanner *bufio.Scanner) (map[string]weights, e } if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("weight file %s parsing error:%s", w.fileName, err) + return nil, fmt.Errorf("weight file %s parsing error: %w", w.fileName, err) } return domains, nil diff --git a/plugin/metrics/metrics.go b/plugin/metrics/metrics.go index d8c16de26..1b054da70 100644 --- a/plugin/metrics/metrics.go +++ b/plugin/metrics/metrics.go @@ -3,6 +3,7 @@ package metrics import ( "context" + "errors" "log/slog" "net" "net/http" @@ -59,7 +60,8 @@ func (m *Metrics) MustRegister(c prometheus.Collector) { err := m.Reg.Register(c) if err != nil { // ignore any duplicate error, but fatal on any other kind of error - if _, ok := err.(prometheus.AlreadyRegisteredError); !ok { + var alreadyRegisteredErr prometheus.AlreadyRegisteredError + if !errors.As(err, &alreadyRegisteredErr) { log.Fatalf("Cannot register metrics collector: %s", err) } } @@ -143,7 +145,7 @@ func (m *Metrics) OnStartup() error { if m.tlsConfigPath == "" { go func() { - if err := server.Serve(ln); err != nil && err != http.ErrServerClosed { + if err := server.Serve(ln); err != nil && !errors.Is(err, http.ErrServerClosed) { log.Errorf("Failed to start HTTP metrics server: %s", err) } }() @@ -174,7 +176,7 @@ func (m *Metrics) OnStartup() error { // it doesn't retun anything if server starts successfully. // startupListener handles capturing succesful startup. err := web.Serve(m.ln, server, webConfig, logger) - if err != nil && err != http.ErrServerClosed { + if err != nil && !errors.Is(err, http.ErrServerClosed) { log.Errorf("Failed to start HTTPS metrics server: %v", err) startUpErr <- err } diff --git a/plugin/nomad/nomad_test.go b/plugin/nomad/nomad_test.go index da673506c..1f2cee62f 100644 --- a/plugin/nomad/nomad_test.go +++ b/plugin/nomad/nomad_test.go @@ -2,6 +2,7 @@ package nomad import ( "context" + "errors" "net/http" "net/http/httptest" "testing" @@ -189,7 +190,7 @@ func runTests(ctx context.Context, t *testing.T, n *Nomad, cases []test.Case) { w := dnstest.NewRecorder(&test.ResponseWriter{}) _, err := n.ServeDNS(ctx, w, r) - if err != tc.Error { + if !errors.Is(err, tc.Error) { t.Errorf("Test %d: %v (%v) (%v)", i, err, w, r) return } diff --git a/plugin/nsid/nsid_test.go b/plugin/nsid/nsid_test.go index c6268b409..6249fcf15 100644 --- a/plugin/nsid/nsid_test.go +++ b/plugin/nsid/nsid_test.go @@ -3,6 +3,7 @@ package nsid import ( "context" "encoding/hex" + "errors" "testing" "github.com/coredns/coredns/plugin" @@ -54,7 +55,7 @@ func TestNsid(t *testing.T) { rec := dnstest.NewRecorder(&test.ResponseWriter{}) code, err := em.ServeDNS(ctx, rec, req) - if err != tc.expectedErr { + if !errors.Is(err, tc.expectedErr) { t.Errorf("Test %d: Expected error %v, but got %v", i, tc.expectedErr, err) } if code != tc.expectedCode { @@ -116,7 +117,7 @@ func TestNsidCache(t *testing.T) { c.Next = em code, err := c.ServeDNS(ctx, rec, req) - if err != tc.expectedErr { + if !errors.Is(err, tc.expectedErr) { t.Errorf("Test %d: Expected error %v, but got %v", i, tc.expectedErr, err) } if code != tc.expectedCode { diff --git a/plugin/pkg/parse/host.go b/plugin/pkg/parse/host.go index f3f750aa7..8c058f46e 100644 --- a/plugin/pkg/parse/host.go +++ b/plugin/pkg/parse/host.go @@ -92,8 +92,8 @@ func HostPortOrFile(s ...string) ([]string, error) { // Try to open this is a file first. func tryFile(s string) ([]string, error) { c, err := dns.ClientConfigFromFile(s) - if err == os.ErrNotExist { - return nil, fmt.Errorf("failed to open file %q: %q", s, err) + if errors.Is(err, os.ErrNotExist) { + return nil, fmt.Errorf("failed to open file %q: %w", s, err) } else if err != nil { return nil, err } diff --git a/plugin/pkg/proxy/connect.go b/plugin/pkg/proxy/connect.go index ec68debd8..df2941d5d 100644 --- a/plugin/pkg/proxy/connect.go +++ b/plugin/pkg/proxy/connect.go @@ -134,7 +134,7 @@ func (p *Proxy) Connect(_ctx context.Context, state request.Request, opts Option if err := pc.c.WriteMsg(state.Req); err != nil { pc.c.Close() // not giving it back - if err == io.EOF && cached { + if errors.Is(err, io.EOF) && cached { return nil, ErrCachedClosed } return nil, err @@ -158,7 +158,7 @@ func (p *Proxy) Connect(_ctx context.Context, state request.Request, opts Option } pc.c.Close() // not giving it back - if err == io.EOF && cached { + if errors.Is(err, io.EOF) && cached { return nil, ErrCachedClosed } // recovery the origin Id after upstream. @@ -193,7 +193,8 @@ const cumulativeAvgWeight = 4 func shouldTruncateResponse(err error) bool { // This is to handle a scenario in which upstream sets the TC bit, but doesn't truncate the response // and we get ErrBuf instead of overflow. - if _, isDNSErr := err.(*dns.Error); isDNSErr && errors.Is(err, dns.ErrBuf) { + var dnsErr *dns.Error + if errors.As(err, &dnsErr) && errors.Is(err, dns.ErrBuf) { return true } else if strings.Contains(err.Error(), "overflow") { return true diff --git a/plugin/pkg/singleflight/singleflight_test.go b/plugin/pkg/singleflight/singleflight_test.go index 522bb6b70..db6cf37dd 100644 --- a/plugin/pkg/singleflight/singleflight_test.go +++ b/plugin/pkg/singleflight/singleflight_test.go @@ -44,7 +44,7 @@ func TestDoErr(t *testing.T) { v, err := g.Do(1, func() (any, error) { return nil, someErr }) - if err != someErr { + if !errors.Is(err, someErr) { t.Errorf("Do error = %v; want someErr", err) } if v != nil { diff --git a/plugin/pkg/tls/tls.go b/plugin/pkg/tls/tls.go index d469370c8..2f4240ad8 100644 --- a/plugin/pkg/tls/tls.go +++ b/plugin/pkg/tls/tls.go @@ -97,7 +97,7 @@ func NewTLSConfigFromArgs(args ...string) (*tls.Config, error) { func NewTLSConfig(certPath, keyPath, caPath string) (*tls.Config, error) { cert, err := tls.LoadX509KeyPair(certPath, keyPath) if err != nil { - return nil, fmt.Errorf("could not load TLS cert: %s", err) + return nil, fmt.Errorf("could not load TLS cert: %w", err) } roots, err := loadRoots(caPath) @@ -140,11 +140,11 @@ func loadRoots(caPath string) (*x509.CertPool, error) { roots := x509.NewCertPool() pem, err := os.ReadFile(filepath.Clean(caPath)) if err != nil { - return nil, fmt.Errorf("error reading %s: %s", caPath, err) + return nil, fmt.Errorf("error reading %s: %w", caPath, err) } ok := roots.AppendCertsFromPEM(pem) if !ok { - return nil, fmt.Errorf("could not read root certs: %s", err) + return nil, fmt.Errorf("could not read root certs from %s", caPath) } return roots, nil } diff --git a/plugin/rewrite/name.go b/plugin/rewrite/name.go index 4a05ef54f..b8a6d4286 100644 --- a/plugin/rewrite/name.go +++ b/plugin/rewrite/name.go @@ -397,7 +397,7 @@ func parseAnswerRules(name string, args []string) (auto bool, rules ResponseRule rewriteAnswerFromPattern, err := isValidRegexPattern(rewriteAnswerFrom, rewriteAnswerTo) rewriteAnswerTo = plugin.Name(rewriteAnswerTo).Normalize() if err != nil { - return false, nil, fmt.Errorf("%s answer rule for %s rule: %s", last, name, err) + return false, nil, fmt.Errorf("%s answer rule for %s rule: %w", last, name, err) } rules = append(rules, &nameRewriterResponseRule{newStringRewriter(rewriteAnswerFromPattern, rewriteAnswerTo)}) arg += 2 @@ -411,7 +411,7 @@ func parseAnswerRules(name string, args []string) (auto bool, rules ResponseRule rewriteAnswerFromPattern, err := isValidRegexPattern(rewriteAnswerFrom, rewriteAnswerTo) rewriteAnswerTo = plugin.Name(rewriteAnswerTo).Normalize() if err != nil { - return false, nil, fmt.Errorf("%s answer rule for %s rule: %s", last, name, err) + return false, nil, fmt.Errorf("%s answer rule for %s rule: %w", last, name, err) } rules = append(rules, &valueRewriterResponseRule{newStringRewriter(rewriteAnswerFromPattern, rewriteAnswerTo)}) arg += 2 diff --git a/plugin/route53/route53.go b/plugin/route53/route53.go index 4d31f7dec..3c942701a 100644 --- a/plugin/route53/route53.go +++ b/plugin/route53/route53.go @@ -215,21 +215,23 @@ func updateZoneFromRRS(rrs *types.ResourceRecordSet, z *file.Zone) error { for _, rr := range rrs.ResourceRecords { n, err := maybeUnescape(aws.ToString(rrs.Name)) if err != nil { - return fmt.Errorf("failed to unescape `%s' name: %v", aws.ToString(rrs.Name), err) + return fmt.Errorf("failed to unescape `%s' name: %w", aws.ToString(rrs.Name), err) } v, err := maybeUnescape(aws.ToString(rr.Value)) if err != nil { - return fmt.Errorf("failed to unescape `%s' value: %v", aws.ToString(rr.Value), err) + return fmt.Errorf("failed to unescape `%s' value: %w", aws.ToString(rr.Value), err) } // Assemble RFC 1035 conforming record to pass into dns scanner. rfc1035 := fmt.Sprintf("%s %d IN %s %s", n, aws.ToInt64(rrs.TTL), rrs.Type, v) r, err := dns.NewRR(rfc1035) if err != nil { - return fmt.Errorf("failed to parse resource record: %v", err) + return fmt.Errorf("failed to parse resource record: %w", err) } - z.Insert(r) + if err := z.Insert(r); err != nil { + return fmt.Errorf("failed to insert resource record: %w", err) + } } return nil } @@ -259,7 +261,7 @@ func (h *Route53) updateZones(ctx context.Context) error { var out *route53.ListResourceRecordSetsOutput for out, err = h.client.ListResourceRecordSets(ctx, in); !complete; out, err = h.client.ListResourceRecordSets(ctx, in) { if err != nil { - err = fmt.Errorf("failed to list resource records for %v:%v from route53: %v", zName, hostedZone.id, err) + err = fmt.Errorf("failed to list resource records for %v:%v from route53: %w", zName, hostedZone.id, err) return } for _, rrs := range out.ResourceRecordSets { diff --git a/plugin/route53/route53_test.go b/plugin/route53/route53_test.go index 2c30fc63c..f7b47ff8e 100644 --- a/plugin/route53/route53_test.go +++ b/plugin/route53/route53_test.go @@ -225,7 +225,7 @@ func TestRoute53(t *testing.T) { rec := dnstest.NewRecorder(&test.ResponseWriter{}) code, err := r.ServeDNS(ctx, rec, req) - if err != tc.expectedErr { + if !errors.Is(err, tc.expectedErr) { t.Fatalf("Test %d: Expected error %v, but got %v", ti, tc.expectedErr, err) } if code != tc.wantRetCode { @@ -285,7 +285,7 @@ func TestMaybeUnescape(t *testing.T) { {escaped: `example.com\0`, wantErr: errors.New(`invalid escape sequence: '\0'`)}, } { got, gotErr := maybeUnescape(tc.escaped) - if tc.wantErr != gotErr && !reflect.DeepEqual(tc.wantErr, gotErr) { + if !errors.Is(gotErr, tc.wantErr) && !reflect.DeepEqual(tc.wantErr, gotErr) { t.Fatalf("Test %d: Expected error: `%v', but got: `%v'", ti, tc.wantErr, gotErr) } if tc.want != got { diff --git a/plugin/test/scrape.go b/plugin/test/scrape.go index 8494105f3..688c7a3df 100644 --- a/plugin/test/scrape.go +++ b/plugin/test/scrape.go @@ -24,6 +24,7 @@ package test import ( "bufio" + "errors" "fmt" "io" "mime" @@ -240,7 +241,7 @@ func fetchMetricFamilies(url string, ch chan<- *dto.MetricFamily) { for { mf := &dto.MetricFamily{} if err = protodelim.UnmarshalFrom(reader, mf); err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } return diff --git a/plugin/transfer/notify.go b/plugin/transfer/notify.go index af5bada46..b6a37fd28 100644 --- a/plugin/transfer/notify.go +++ b/plugin/transfer/notify.go @@ -53,7 +53,7 @@ func sendNotify(c *dns.Client, m *dns.Msg, s string) error { } } if err != nil { - return fmt.Errorf("notify for zone %q was not accepted by %q: %q", m.Question[0].Name, s, err) + return fmt.Errorf("notify for zone %q was not accepted by %q: %w", m.Question[0].Name, s, err) } return fmt.Errorf("notify for zone %q was not accepted by %q: rcode was %q", m.Question[0].Name, s, rcode.ToString(code)) } diff --git a/plugin/transfer/transfer.go b/plugin/transfer/transfer.go index d4d26c982..da5b06755 100644 --- a/plugin/transfer/transfer.go +++ b/plugin/transfer/transfer.go @@ -94,7 +94,7 @@ func (t *Transfer) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Ms var err error for _, p := range t.Transferers { pchan, err = p.Transfer(state.Name(), serial) - if err == ErrNotAuthoritative { + if errors.Is(err, ErrNotAuthoritative) { // plugin was not authoritative for the zone, try next plugin continue } diff --git a/plugin/tsig/tsig.go b/plugin/tsig/tsig.go index 458b765d9..2e1392779 100644 --- a/plugin/tsig/tsig.go +++ b/plugin/tsig/tsig.go @@ -4,6 +4,7 @@ import ( "context" "encoding/binary" "encoding/hex" + "errors" "time" "github.com/coredns/coredns/plugin" @@ -56,10 +57,10 @@ func (t *TSIGServer) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns. if tsigStatus != nil { log.Debugf("TSIG validation failed: %v %v", dns.TypeToString[state.QType()], tsigStatus) rcode = dns.RcodeNotAuth - switch tsigStatus { - case dns.ErrSecret: + switch { + case errors.Is(tsigStatus, dns.ErrSecret): tsigRR.Error = dns.RcodeBadKey - case dns.ErrTime: + case errors.Is(tsigStatus, dns.ErrTime): tsigRR.Error = dns.RcodeBadTime default: tsigRR.Error = dns.RcodeBadSig diff --git a/plugin/view/setup_test.go b/plugin/view/setup_test.go index 309d85cb8..86fc5db9b 100644 --- a/plugin/view/setup_test.go +++ b/plugin/view/setup_test.go @@ -57,7 +57,7 @@ func TestServeDNS_DelegatesToNext(t *testing.T) { if gotCode != wantCode { t.Fatalf("rcode: got %d, want %d", gotCode, wantCode) } - if gotErr != wantErr { + if !errors.Is(gotErr, wantErr) { t.Fatalf("error: got %v, want %v", gotErr, wantErr) } } diff --git a/plugin/whoami/whoami_test.go b/plugin/whoami/whoami_test.go index fa6a6f0fa..eb279dd38 100644 --- a/plugin/whoami/whoami_test.go +++ b/plugin/whoami/whoami_test.go @@ -2,6 +2,7 @@ package whoami import ( "context" + "errors" "testing" "github.com/coredns/coredns/plugin/pkg/dnstest" @@ -63,7 +64,7 @@ func TestWhoami(t *testing.T) { req.SetQuestion(dns.Fqdn(tc.qname), tc.qtype) rec := dnstest.NewRecorder(&test.ResponseWriter{RemoteIP: tc.remote}) code, err := wh.ServeDNS(ctx, rec, req) - if err != tc.expectedErr { + if !errors.Is(err, tc.expectedErr) { t.Errorf("Test %d: Expected error %v, but got %v", i, tc.expectedErr, err) } if code != tc.expectedCode { diff --git a/test/metrics_test.go b/test/metrics_test.go index efb3bdbbd..30a6853cf 100644 --- a/test/metrics_test.go +++ b/test/metrics_test.go @@ -110,7 +110,7 @@ func getBucketCount(mf *test.MetricFamily, bucketLabel string) (int, error) { count, err := strconv.Atoi(countStr) if err != nil { - return 0, fmt.Errorf("could not parse bucket count '%s' for %s: %v", countStr, mf.Name, err) + return 0, fmt.Errorf("could not parse bucket count %q for %s: %w", countStr, mf.Name, err) } return count, nil } @@ -126,11 +126,11 @@ func extractRequestSizeBucketCounts(t *testing.T, metrics []*test.MetricFamily, t.Logf(" %s: %v", mf.Name, mf.Metrics) countBelow100, err = getBucketCount(mf, "100") if err != nil { - return 0, 0, fmt.Errorf("%s: error getting bucket count for 100: %v", label, err) + return 0, 0, fmt.Errorf("%s: error getting bucket count for 100: %w", label, err) } countAbove100, err = getBucketCount(mf, "1023") if err != nil { - return 0, 0, fmt.Errorf("%s: error getting bucket count for 1023: %v", label, err) + return 0, 0, fmt.Errorf("%s: error getting bucket count for 1023: %w", label, err) } return countBelow100, countAbove100, nil } diff --git a/test/tsig_test.go b/test/tsig_test.go index f126f792b..d8cf1b456 100644 --- a/test/tsig_test.go +++ b/test/tsig_test.go @@ -1,6 +1,7 @@ package test import ( + "errors" "testing" "time" @@ -62,7 +63,7 @@ func TestTsigBadKey(t *testing.T) { client := dns.Client{Net: "udp", TsigSecret: map[string]string{"bad.key.": tsigSecret}} r, _, err := client.Exchange(m, udp) - if err != dns.ErrAuth { + if !errors.Is(err, dns.ErrAuth) { t.Fatalf("Expected \"dns: bad authentication\" error, got: %s", err) } if r.Rcode != dns.RcodeNotAuth { @@ -101,7 +102,7 @@ func TestTsigBadSig(t *testing.T) { client := dns.Client{Net: "udp", TsigSecret: map[string]string{tsigKey: "BADSIG00ECfVZG2qCjr4mPpaGim/Bq+IWMiNrLjUO4Y="}} r, _, err := client.Exchange(m, udp) - if err != dns.ErrAuth { + if !errors.Is(err, dns.ErrAuth) { t.Fatalf("Expected \"dns: bad authentication\" error, got: %s", err) } if r.Rcode != dns.RcodeNotAuth { @@ -141,7 +142,7 @@ func TestTsigBadTime(t *testing.T) { client := dns.Client{Net: "udp", TsigSecret: map[string]string{tsigKey: tsigSecret}} r, _, err := client.Exchange(m, udp) - if err != dns.ErrAuth { + if !errors.Is(err, dns.ErrAuth) { t.Fatalf("Expected \"dns: bad authentication\" error, got: %s", err) } if r.Rcode != dns.RcodeNotAuth {