lint(errorlint): handle wrapped errors

Enable errorlint and preserve wrapped error chains so runtime checks
and tests classify failures correctly. This also makes Route53
surface insert failures instead of silently dropping them.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
This commit is contained in:
Ville Vesilehto
2026-04-25 11:51:45 +03:00
parent a669d74088
commit 3080ec0448
53 changed files with 122 additions and 89 deletions

View File

@@ -10,6 +10,7 @@ linters:
- canonicalheader - canonicalheader
- copyloopvar - copyloopvar
- durationcheck - durationcheck
- errorlint
- godoclint - godoclint
- gosec - gosec
- govet - govet

View File

@@ -457,7 +457,7 @@ func TestGRPCResponseTsigStatusReturnsStoredStatus(t *testing.T) {
tsigStatus: want, tsigStatus: want,
} }
if got := r.TsigStatus(); got != want { if got := r.TsigStatus(); !errors.Is(got, want) {
t.Fatalf("TsigStatus() = %v, want %v", got, want) t.Fatalf("TsigStatus() = %v, want %v", got, want)
} }
} }

View File

@@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"crypto/tls" "crypto/tls"
"errors"
"io" "io"
"net" "net"
"net/http" "net/http"
@@ -579,7 +580,7 @@ func TestServeHTTPAcceptsValidTSIG(t *testing.T) {
func TestDoHWriterTsigStatusReturnsStoredStatus(t *testing.T) { func TestDoHWriterTsigStatusReturnsStoredStatus(t *testing.T) {
dw := &DoHWriter{tsigStatus: dns.ErrSecret} 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") t.Fatal("expected TsigStatus to return stored tsigStatus")
} }
} }

View File

@@ -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 // 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 // the STREAM FIN indicating that there will be no data to read
// anymore from this stream. // anymore from this stream.
if err != nil && err != io.EOF { if err != nil && !errors.Is(err, io.EOF) {
s.closeQUICConn(conn, DoQCodeProtocolError) s.closeQUICConn(conn, DoQCodeProtocolError)
return return

View File

@@ -455,7 +455,7 @@ func TestDoQWriterTsigStatusReturnsStoredStatus(t *testing.T) {
tsigStatus: want, tsigStatus: want,
} }
if got := w.TsigStatus(); got != want { if got := w.TsigStatus(); !errors.Is(got, want) {
t.Fatalf("TsigStatus() = %v, want %v", got, want) t.Fatalf("TsigStatus() = %v, want %v", got, want)
} }
} }

View File

@@ -57,7 +57,7 @@ func autoPathParse(c *caddy.Controller) (*AutoPath, string, error) {
// assume file on disk // assume file on disk
rc, err := dns.ClientConfigFromFile(resolv) rc, err := dns.ClientConfigFromFile(resolv)
if err != nil { 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 ap.search = rc.Search
plugin.Zones(ap.search).Normalize() plugin.Zones(ap.search).Normalize()

View File

@@ -2,6 +2,7 @@ package azure
import ( import (
"context" "context"
"errors"
"reflect" "reflect"
"testing" "testing"
@@ -141,7 +142,7 @@ func TestAzure(t *testing.T) {
rec := dnstest.NewRecorder(&test.ResponseWriter{}) rec := dnstest.NewRecorder(&test.ResponseWriter{})
code, err := demoAzure.ServeDNS(context.Background(), rec, req) 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) t.Fatalf("Test %d: Expected error %v, but got %v", ti, tc.expectedErr, err)
} }

View File

@@ -18,7 +18,7 @@ func setup(c *caddy.Controller) error {
all := []string{} all := []string{}
ifaces, err := net.Interfaces() ifaces, err := net.Interfaces()
if err != nil { 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() { for c.Next() {

View File

@@ -2,6 +2,7 @@ package chaos
import ( import (
"context" "context"
"errors"
"testing" "testing"
"github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin"
@@ -62,7 +63,7 @@ func TestChaos(t *testing.T) {
rec := dnstest.NewRecorder(&test.ResponseWriter{}) rec := dnstest.NewRecorder(&test.ResponseWriter{})
code, err := em.ServeDNS(ctx, rec, req) 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) t.Errorf("Test %d: Expected error %v, but got %v", i, tc.expectedErr, err)
} }
if code != tc.expectedCode { if code != tc.expectedCode {

View File

@@ -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) rfc1035 = fmt.Sprintf("%s %d IN %s %s", dns.Fqdn(rr.Name), rr.Ttl, rr.Type, value)
r, err = dns.NewRR(rfc1035) r, err = dns.NewRR(rfc1035)
if err != nil { 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) err = z.Insert(r)
if err != nil { 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 newZ.Upstream = h.upstream
rrListResponse, err = h.client.listRRSets(ctx, hostedZone.projectName, hostedZone.zoneName) rrListResponse, err = h.client.listRRSets(ctx, hostedZone.projectName, hostedZone.zoneName)
if err != nil { 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 return
} }
updateZoneFromRRS(rrListResponse, newZ) updateZoneFromRRS(rrListResponse, newZ)

View File

@@ -291,7 +291,7 @@ func TestCloudDNS(t *testing.T) {
rec := dnstest.NewRecorder(&test.ResponseWriter{}) rec := dnstest.NewRecorder(&test.ResponseWriter{})
code, err := r.ServeDNS(ctx, rec, req) 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) t.Fatalf("Test %d: Expected error %v, but got %v", ti, tc.expectedErr, err)
} }
if code != tc.wantRetCode { if code != tc.wantRetCode {

View File

@@ -2,6 +2,7 @@ package erratic
import ( import (
"context" "context"
"errors"
"testing" "testing"
"github.com/coredns/coredns/plugin/pkg/dnstest" "github.com/coredns/coredns/plugin/pkg/dnstest"
@@ -34,7 +35,7 @@ func TestErraticDrop(t *testing.T) {
rec := dnstest.NewRecorder(&test.ResponseWriter{}) rec := dnstest.NewRecorder(&test.ResponseWriter{})
code, err := e.ServeDNS(ctx, rec, req) 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) t.Errorf("Test %d: Expected error %q, but got %q", i, tc.expectedErr, err)
} }
if code != tc.expectedCode { if code != tc.expectedCode {
@@ -68,7 +69,7 @@ func TestErraticTruncate(t *testing.T) {
rec := dnstest.NewRecorder(&test.ResponseWriter{}) rec := dnstest.NewRecorder(&test.ResponseWriter{})
code, err := e.ServeDNS(ctx, rec, req) 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) t.Errorf("Test %d: Expected error %q, but got %q", i, tc.expectedErr, err)
} }
if code != tc.expectedCode { if code != tc.expectedCode {

View File

@@ -56,7 +56,7 @@ func TestErrors(t *testing.T) {
rec := dnstest.NewRecorder(&test.ResponseWriter{}) rec := dnstest.NewRecorder(&test.ResponseWriter{})
code, err := em.ServeDNS(ctx, rec, req) 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", t.Errorf("Test %d: Expected error %v, but got %v",
i, tc.expectedErr, err) i, tc.expectedErr, err)
} }

View File

@@ -67,7 +67,7 @@ func (e *Etcd) Lookup(ctx context.Context, state request.Request, name string, t
// IsNameError implements the ServiceBackend interface. // IsNameError implements the ServiceBackend interface.
func (e *Etcd) IsNameError(err error) bool { 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 // Records looks up records in etcd. If exact is true, it will lookup just this

View File

@@ -167,7 +167,7 @@ func Parse(f io.Reader, origin, fileName string, serial int64) (*Zone, error) {
} }
} }
if zp.Err() != nil { 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 { if !seenSOA {
return nil, fmt.Errorf("file %q has no SOA record for origin %s", fileName, origin) return nil, fmt.Errorf("file %q has no SOA record for origin %s", fileName, origin)

View File

@@ -1,6 +1,7 @@
package file package file
import ( import (
"errors"
"os" "os"
"path/filepath" "path/filepath"
"time" "time"
@@ -30,7 +31,8 @@ func (z *Zone) Reload(t *transfer.Transfer) error {
zone, err := Parse(reader, z.origin, zFile, serial) zone, err := Parse(reader, z.origin, zFile, serial)
reader.Close() reader.Close()
if err != nil { 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) log.Errorf("Parsing zone %q: %v", z.origin, err)
} }
continue continue

View File

@@ -169,7 +169,7 @@ func (f *Forward) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
for { for {
ret, err = proxy.Connect(ctx, state, opts) 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 continue
} }
// Retry with TCP if truncated and prefer_udp configured. // Retry with TCP if truncated and prefer_udp configured.

View File

@@ -2,6 +2,7 @@ package forward
import ( import (
"context" "context"
"errors"
"sync/atomic" "sync/atomic"
"testing" "testing"
"time" "time"
@@ -343,8 +344,8 @@ func TestAllUpstreamsDown(t *testing.T) {
t.Errorf("Expected Response code: %d, Got: %d", dns.RcodeServerFailure, resp) t.Errorf("Expected Response code: %d, Got: %d", dns.RcodeServerFailure, resp)
} }
if err != ErrNoHealthy { if !errors.Is(err, ErrNoHealthy) {
t.Errorf("Expected error message: no healthy proxies, Got: %s", err.Error()) t.Errorf("Expected error message: no healthy proxies, Got: %v", err)
} }
q1 := atomic.LoadUint32(&qs) q1 := atomic.LoadUint32(&qs)
@@ -358,7 +359,7 @@ func TestAllUpstreamsDown(t *testing.T) {
req = new(dns.Msg) req = new(dns.Msg)
req.SetQuestion("example.org.", dns.TypeA) req.SetQuestion("example.org.", dns.TypeA)
_, err = f.ServeDNS(context.TODO(), &test.ResponseWriter{}, req) _, err = f.ServeDNS(context.TODO(), &test.ResponseWriter{}, req)
if err == ErrNoHealthy { if errors.Is(err, ErrNoHealthy) {
t.Error("Unexpected error message: no healthy proxies") t.Error("Unexpected error message: no healthy proxies")
} }

View File

@@ -3,6 +3,7 @@ package geoip
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"net/netip" "net/netip"
"path/filepath" "path/filepath"
@@ -42,7 +43,7 @@ var probingIP = netip.MustParseAddr("127.0.0.1")
func newGeoIP(dbPath string, edns0 bool) (*GeoIP, error) { func newGeoIP(dbPath string, edns0 bool) (*GeoIP, error) {
reader, err := geoip2.Open(dbPath) reader, err := geoip2.Open(dbPath)
if err != nil { 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} db := db{Reader: reader}
schemas := []struct { schemas := []struct {
@@ -57,8 +58,9 @@ func newGeoIP(dbPath string, edns0 bool) (*GeoIP, error) {
for _, schema := range schemas { for _, schema := range schemas {
if err := schema.validate(); err != nil { if err := schema.validate(); err != nil {
// If we get an InvalidMethodError then we know this database does not provide that schema. // If we get an InvalidMethodError then we know this database does not provide that schema.
if _, ok := err.(geoip2.InvalidMethodError); !ok { var invalidMethodErr geoip2.InvalidMethodError
return nil, fmt.Errorf("unexpected failure looking up database %q schema %q: %v", filepath.Base(dbPath), schema.name, err) 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 { } else {
db.provides |= schema.provides db.provides |= schema.provides

View File

@@ -54,7 +54,7 @@ func parse(c *caddy.Controller) (string, time.Duration, error) {
} }
l, err := time.ParseDuration(args[0]) l, err := time.ParseDuration(args[0])
if err != nil { 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 dur = l
default: default:

View File

@@ -2,6 +2,7 @@ package external
import ( import (
"context" "context"
"errors"
"testing" "testing"
"github.com/coredns/coredns/plugin/kubernetes" "github.com/coredns/coredns/plugin/kubernetes"
@@ -30,7 +31,7 @@ func TestApex(t *testing.T) {
w := dnstest.NewRecorder(&test.ResponseWriter{}) w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := e.ServeDNS(ctx, w, r) _, 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) t.Errorf("Test %d expected no error, got %v", i, err)
return return
} }

View File

@@ -2,6 +2,7 @@ package external
import ( import (
"context" "context"
"errors"
"testing" "testing"
"github.com/coredns/coredns/plugin/kubernetes" "github.com/coredns/coredns/plugin/kubernetes"
@@ -33,7 +34,7 @@ func TestExternal(t *testing.T) {
w := dnstest.NewRecorder(&test.ResponseWriter{}) w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := e.ServeDNS(ctx, w, r) _, 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) t.Errorf("Test %d expected no error, got %v", i, err)
return return
} }

View File

@@ -2,6 +2,7 @@ package kubernetes
import ( import (
"context" "context"
"errors"
"testing" "testing"
"github.com/coredns/coredns/plugin/pkg/dnstest" "github.com/coredns/coredns/plugin/pkg/dnstest"
@@ -60,7 +61,7 @@ func TestPreserveCase(t *testing.T) {
w := dnstest.NewRecorder(&test.ResponseWriter{}) w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := k.ServeDNS(ctx, w, r) _, 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) t.Errorf("Test %d expected no error, got %v", i, err)
return return
} }

View File

@@ -2,6 +2,7 @@ package kubernetes
import ( import (
"context" "context"
"errors"
"testing" "testing"
"github.com/coredns/coredns/plugin/pkg/dnstest" "github.com/coredns/coredns/plugin/pkg/dnstest"
@@ -42,7 +43,7 @@ func TestServeDNSEmptyService(t *testing.T) {
w := dnstest.NewRecorder(&test.ResponseWriter{}) w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := k.ServeDNS(ctx, w, r) _, 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) t.Errorf("Test %d expected no error, got %v", i, err)
return return
} }

View File

@@ -2,6 +2,7 @@ package kubernetes
import ( import (
"context" "context"
"errors"
"testing" "testing"
"github.com/coredns/coredns/plugin/pkg/dnstest" "github.com/coredns/coredns/plugin/pkg/dnstest"
@@ -40,7 +41,7 @@ func TestServeDNSModeDisabled(t *testing.T) {
w := dnstest.NewRecorder(&test.ResponseWriter{}) w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := k.ServeDNS(ctx, w, r) _, 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) t.Errorf("Test %d got unexpected error %v", i, err)
return return
} }

View File

@@ -2,6 +2,7 @@ package kubernetes
import ( import (
"context" "context"
"errors"
"testing" "testing"
"github.com/coredns/coredns/plugin/pkg/dnstest" "github.com/coredns/coredns/plugin/pkg/dnstest"
@@ -75,7 +76,7 @@ func TestServeDNSModeInsecure(t *testing.T) {
w := dnstest.NewRecorder(&test.ResponseWriter{}) w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := k.ServeDNS(ctx, w, r) _, 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) t.Errorf("Test %d expected no error, got %v", i, err)
return return
} }

View File

@@ -2,6 +2,7 @@ package kubernetes
import ( import (
"context" "context"
"errors"
"testing" "testing"
"github.com/coredns/coredns/plugin/pkg/dnstest" "github.com/coredns/coredns/plugin/pkg/dnstest"
@@ -61,7 +62,7 @@ func TestServeDNSModeVerified(t *testing.T) {
w := dnstest.NewRecorder(&test.ResponseWriter{}) w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := k.ServeDNS(ctx, w, r) _, 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) t.Errorf("Test %d expected no error, got %v", i, err)
return return
} }

View File

@@ -2,6 +2,7 @@ package kubernetes
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"testing" "testing"
@@ -436,7 +437,7 @@ func TestServeDNS(t *testing.T) {
w := dnstest.NewRecorder(&test.ResponseWriter{}) w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := k.ServeDNS(ctx, w, r) _, 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) t.Errorf("Test %d expected no error, got %v", i, err)
return return
} }
@@ -568,7 +569,7 @@ func TestMultiClusterServeDNS(t *testing.T) {
w := dnstest.NewRecorder(&test.ResponseWriter{}) w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := k.ServeDNS(ctx, w, r) _, 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) t.Errorf("Test %d expected no error, got %v", i, err)
return return
} }
@@ -629,7 +630,7 @@ func TestServeNamespaceDNS(t *testing.T) {
w := dnstest.NewRecorder(&test.ResponseWriter{}) w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := k.ServeDNS(ctx, w, r) _, 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) t.Errorf("Test %d expected no error, got %v", i, err)
return return
} }
@@ -675,7 +676,7 @@ func TestNotSyncedServeDNS(t *testing.T) {
w := dnstest.NewRecorder(&test.ResponseWriter{}) w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := k.ServeDNS(ctx, w, r) _, 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) t.Errorf("Test %d expected no error, got %v", i, err)
return return
} }

View File

@@ -181,7 +181,7 @@ func (k *Kubernetes) Lookup(ctx context.Context, state request.Request, name str
// IsNameError implements the ServiceBackend interface. // IsNameError implements the ServiceBackend interface.
func (k *Kubernetes) IsNameError(err error) bool { 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) { 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) kubeClient, err := kubernetes.NewForConfig(config)
if err != nil { 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 var mcsClient mcsClientset.MulticlusterV1alpha1Interface
if len(k.opts.multiclusterZones) > 0 { if len(k.opts.multiclusterZones) > 0 {
mcsClient, err = mcsClientset.NewForConfig(config) mcsClient, err = mcsClientset.NewForConfig(config)
if err != nil { 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 var selector labels.Selector
selector, err = meta.LabelSelectorAsSelector(k.opts.labelSelector) selector, err = meta.LabelSelectorAsSelector(k.opts.labelSelector)
if err != nil { 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 k.opts.selector = selector
} }
@@ -264,7 +264,7 @@ func (k *Kubernetes) InitKubeCache(ctx context.Context) (onStart func() error, o
var selector labels.Selector var selector labels.Selector
selector, err = meta.LabelSelectorAsSelector(k.opts.namespaceLabelSelector) selector, err = meta.LabelSelectorAsSelector(k.opts.namespaceLabelSelector)
if err != nil { 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 k.opts.namespaceSelector = selector
} }

View File

@@ -2,6 +2,7 @@ package kubernetes
import ( import (
"context" "context"
"errors"
"net" "net"
"testing" "testing"
@@ -72,7 +73,7 @@ func TestServeDNSApex(t *testing.T) {
w := dnstest.NewRecorder(&test.ResponseWriter{}) w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := k.ServeDNS(ctx, w, r) _, 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) t.Errorf("Test %d, expected no error, got %v", i, err)
return return
} }

View File

@@ -1,6 +1,7 @@
package object package object
import ( import (
"errors"
"fmt" "fmt"
meta "k8s.io/apimachinery/pkg/apis/meta/v1" 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: case cache.Sync, cache.Added, cache.Updated:
obj, err := convert(d.Object.(meta.Object)) obj, err := convert(d.Object.(meta.Object))
if err != nil { if err != nil {
if err == errPodTerminating { if errors.Is(err, errPodTerminating) {
continue continue
} }
return err return err
@@ -68,7 +69,7 @@ func DefaultProcessor(convert ToFunc, recordLatency *EndpointLatencyRecorder) Pr
return fmt.Errorf("unexpected object %v", d.Object) return fmt.Errorf("unexpected object %v", d.Object)
} }
obj, err = convert(metaObj) obj, err = convert(metaObj)
if err != nil && err != errPodTerminating { if err != nil && !errors.Is(err, errPodTerminating) {
return err return err
} }
} }

View File

@@ -2,6 +2,7 @@ package kubernetes
import ( import (
"context" "context"
"errors"
"testing" "testing"
"github.com/coredns/coredns/plugin/kubernetes/object" "github.com/coredns/coredns/plugin/kubernetes/object"
@@ -243,7 +244,7 @@ func TestReverse(t *testing.T) {
w := dnstest.NewRecorder(&test.ResponseWriter{}) w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := k.ServeDNS(ctx, w, r) _, 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) t.Errorf("Test %d: expected no error, got %v", i, err)
return return
} }

View File

@@ -169,7 +169,7 @@ func ParseStanza(c *caddy.Controller) (*Kubernetes, error) {
labelSelectorString := strings.Join(args, " ") labelSelectorString := strings.Join(args, " ")
ls, err := meta.ParseToLabelSelector(labelSelectorString) ls, err := meta.ParseToLabelSelector(labelSelectorString)
if err != nil { 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 k8s.opts.labelSelector = ls
continue continue
@@ -181,7 +181,7 @@ func ParseStanza(c *caddy.Controller) (*Kubernetes, error) {
namespaceLabelSelectorString := strings.Join(args, " ") namespaceLabelSelectorString := strings.Join(args, " ")
nls, err := meta.ParseToLabelSelector(namespaceLabelSelectorString) nls, err := meta.ParseToLabelSelector(namespaceLabelSelectorString)
if err != nil { 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 k8s.opts.namespaceLabelSelector = nls
continue continue
@@ -241,7 +241,7 @@ func ParseStanza(c *caddy.Controller) (*Kubernetes, error) {
var err error var err error
k8s.startupTimeout, err = time.ParseDuration(args[0]) k8s.startupTimeout, err = time.ParseDuration(args[0])
if err != nil { 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": case "apiserver_qps":
args := c.RemainingArgs() args := c.RemainingArgs()

View File

@@ -1,6 +1,7 @@
package kubernetes package kubernetes
import ( import (
"errors"
"net" "net"
"strings" "strings"
"testing" "testing"
@@ -20,7 +21,7 @@ func TestKubernetesTransferNonAuthZone(t *testing.T) {
dnsmsg.SetAxfr("example.com") dnsmsg.SetAxfr("example.com")
_, err := k.Transfer("example.com", 0) _, err := k.Transfer("example.com", 0)
if err != transfer.ErrNotAuthoritative { if !errors.Is(err, transfer.ErrNotAuthoritative) {
t.Error(err) t.Error(err)
} }
} }

View File

@@ -322,7 +322,7 @@ func (w *weightedRR) parseWeights(scanner *bufio.Scanner) (map[string]weights, e
} }
if err := scanner.Err(); err != nil { 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 return domains, nil

View File

@@ -3,6 +3,7 @@ package metrics
import ( import (
"context" "context"
"errors"
"log/slog" "log/slog"
"net" "net"
"net/http" "net/http"
@@ -59,7 +60,8 @@ func (m *Metrics) MustRegister(c prometheus.Collector) {
err := m.Reg.Register(c) err := m.Reg.Register(c)
if err != nil { if err != nil {
// ignore any duplicate error, but fatal on any other kind of error // 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) log.Fatalf("Cannot register metrics collector: %s", err)
} }
} }
@@ -143,7 +145,7 @@ func (m *Metrics) OnStartup() error {
if m.tlsConfigPath == "" { if m.tlsConfigPath == "" {
go func() { 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) 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. // it doesn't retun anything if server starts successfully.
// startupListener handles capturing succesful startup. // startupListener handles capturing succesful startup.
err := web.Serve(m.ln, server, webConfig, logger) 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) log.Errorf("Failed to start HTTPS metrics server: %v", err)
startUpErr <- err startUpErr <- err
} }

View File

@@ -2,6 +2,7 @@ package nomad
import ( import (
"context" "context"
"errors"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
@@ -189,7 +190,7 @@ func runTests(ctx context.Context, t *testing.T, n *Nomad, cases []test.Case) {
w := dnstest.NewRecorder(&test.ResponseWriter{}) w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := n.ServeDNS(ctx, w, r) _, 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) t.Errorf("Test %d: %v (%v) (%v)", i, err, w, r)
return return
} }

View File

@@ -3,6 +3,7 @@ package nsid
import ( import (
"context" "context"
"encoding/hex" "encoding/hex"
"errors"
"testing" "testing"
"github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin"
@@ -54,7 +55,7 @@ func TestNsid(t *testing.T) {
rec := dnstest.NewRecorder(&test.ResponseWriter{}) rec := dnstest.NewRecorder(&test.ResponseWriter{})
code, err := em.ServeDNS(ctx, rec, req) 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) t.Errorf("Test %d: Expected error %v, but got %v", i, tc.expectedErr, err)
} }
if code != tc.expectedCode { if code != tc.expectedCode {
@@ -116,7 +117,7 @@ func TestNsidCache(t *testing.T) {
c.Next = em c.Next = em
code, err := c.ServeDNS(ctx, rec, req) 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) t.Errorf("Test %d: Expected error %v, but got %v", i, tc.expectedErr, err)
} }
if code != tc.expectedCode { if code != tc.expectedCode {

View File

@@ -92,8 +92,8 @@ func HostPortOrFile(s ...string) ([]string, error) {
// Try to open this is a file first. // Try to open this is a file first.
func tryFile(s string) ([]string, error) { func tryFile(s string) ([]string, error) {
c, err := dns.ClientConfigFromFile(s) c, err := dns.ClientConfigFromFile(s)
if err == os.ErrNotExist { if errors.Is(err, os.ErrNotExist) {
return nil, fmt.Errorf("failed to open file %q: %q", s, err) return nil, fmt.Errorf("failed to open file %q: %w", s, err)
} else if err != nil { } else if err != nil {
return nil, err return nil, err
} }

View File

@@ -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 { if err := pc.c.WriteMsg(state.Req); err != nil {
pc.c.Close() // not giving it back pc.c.Close() // not giving it back
if err == io.EOF && cached { if errors.Is(err, io.EOF) && cached {
return nil, ErrCachedClosed return nil, ErrCachedClosed
} }
return nil, err 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 pc.c.Close() // not giving it back
if err == io.EOF && cached { if errors.Is(err, io.EOF) && cached {
return nil, ErrCachedClosed return nil, ErrCachedClosed
} }
// recovery the origin Id after upstream. // recovery the origin Id after upstream.
@@ -193,7 +193,8 @@ const cumulativeAvgWeight = 4
func shouldTruncateResponse(err error) bool { func shouldTruncateResponse(err error) bool {
// This is to handle a scenario in which upstream sets the TC bit, but doesn't truncate the response // 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. // 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 return true
} else if strings.Contains(err.Error(), "overflow") { } else if strings.Contains(err.Error(), "overflow") {
return true return true

View File

@@ -44,7 +44,7 @@ func TestDoErr(t *testing.T) {
v, err := g.Do(1, func() (any, error) { v, err := g.Do(1, func() (any, error) {
return nil, someErr return nil, someErr
}) })
if err != someErr { if !errors.Is(err, someErr) {
t.Errorf("Do error = %v; want someErr", err) t.Errorf("Do error = %v; want someErr", err)
} }
if v != nil { if v != nil {

View File

@@ -97,7 +97,7 @@ func NewTLSConfigFromArgs(args ...string) (*tls.Config, error) {
func NewTLSConfig(certPath, keyPath, caPath string) (*tls.Config, error) { func NewTLSConfig(certPath, keyPath, caPath string) (*tls.Config, error) {
cert, err := tls.LoadX509KeyPair(certPath, keyPath) cert, err := tls.LoadX509KeyPair(certPath, keyPath)
if err != nil { 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) roots, err := loadRoots(caPath)
@@ -140,11 +140,11 @@ func loadRoots(caPath string) (*x509.CertPool, error) {
roots := x509.NewCertPool() roots := x509.NewCertPool()
pem, err := os.ReadFile(filepath.Clean(caPath)) pem, err := os.ReadFile(filepath.Clean(caPath))
if err != nil { 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) ok := roots.AppendCertsFromPEM(pem)
if !ok { 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 return roots, nil
} }

View File

@@ -397,7 +397,7 @@ func parseAnswerRules(name string, args []string) (auto bool, rules ResponseRule
rewriteAnswerFromPattern, err := isValidRegexPattern(rewriteAnswerFrom, rewriteAnswerTo) rewriteAnswerFromPattern, err := isValidRegexPattern(rewriteAnswerFrom, rewriteAnswerTo)
rewriteAnswerTo = plugin.Name(rewriteAnswerTo).Normalize() rewriteAnswerTo = plugin.Name(rewriteAnswerTo).Normalize()
if err != nil { 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)}) rules = append(rules, &nameRewriterResponseRule{newStringRewriter(rewriteAnswerFromPattern, rewriteAnswerTo)})
arg += 2 arg += 2
@@ -411,7 +411,7 @@ func parseAnswerRules(name string, args []string) (auto bool, rules ResponseRule
rewriteAnswerFromPattern, err := isValidRegexPattern(rewriteAnswerFrom, rewriteAnswerTo) rewriteAnswerFromPattern, err := isValidRegexPattern(rewriteAnswerFrom, rewriteAnswerTo)
rewriteAnswerTo = plugin.Name(rewriteAnswerTo).Normalize() rewriteAnswerTo = plugin.Name(rewriteAnswerTo).Normalize()
if err != nil { 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)}) rules = append(rules, &valueRewriterResponseRule{newStringRewriter(rewriteAnswerFromPattern, rewriteAnswerTo)})
arg += 2 arg += 2

View File

@@ -215,21 +215,23 @@ func updateZoneFromRRS(rrs *types.ResourceRecordSet, z *file.Zone) error {
for _, rr := range rrs.ResourceRecords { for _, rr := range rrs.ResourceRecords {
n, err := maybeUnescape(aws.ToString(rrs.Name)) n, err := maybeUnescape(aws.ToString(rrs.Name))
if err != nil { 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)) v, err := maybeUnescape(aws.ToString(rr.Value))
if err != nil { 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. // 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) rfc1035 := fmt.Sprintf("%s %d IN %s %s", n, aws.ToInt64(rrs.TTL), rrs.Type, v)
r, err := dns.NewRR(rfc1035) r, err := dns.NewRR(rfc1035)
if err != nil { 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 return nil
} }
@@ -259,7 +261,7 @@ func (h *Route53) updateZones(ctx context.Context) error {
var out *route53.ListResourceRecordSetsOutput var out *route53.ListResourceRecordSetsOutput
for out, err = h.client.ListResourceRecordSets(ctx, in); !complete; out, err = h.client.ListResourceRecordSets(ctx, in) { for out, err = h.client.ListResourceRecordSets(ctx, in); !complete; out, err = h.client.ListResourceRecordSets(ctx, in) {
if err != nil { 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 return
} }
for _, rrs := range out.ResourceRecordSets { for _, rrs := range out.ResourceRecordSets {

View File

@@ -225,7 +225,7 @@ func TestRoute53(t *testing.T) {
rec := dnstest.NewRecorder(&test.ResponseWriter{}) rec := dnstest.NewRecorder(&test.ResponseWriter{})
code, err := r.ServeDNS(ctx, rec, req) 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) t.Fatalf("Test %d: Expected error %v, but got %v", ti, tc.expectedErr, err)
} }
if code != tc.wantRetCode { if code != tc.wantRetCode {
@@ -285,7 +285,7 @@ func TestMaybeUnescape(t *testing.T) {
{escaped: `example.com\0`, wantErr: errors.New(`invalid escape sequence: '\0'`)}, {escaped: `example.com\0`, wantErr: errors.New(`invalid escape sequence: '\0'`)},
} { } {
got, gotErr := maybeUnescape(tc.escaped) 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) t.Fatalf("Test %d: Expected error: `%v', but got: `%v'", ti, tc.wantErr, gotErr)
} }
if tc.want != got { if tc.want != got {

View File

@@ -24,6 +24,7 @@ package test
import ( import (
"bufio" "bufio"
"errors"
"fmt" "fmt"
"io" "io"
"mime" "mime"
@@ -240,7 +241,7 @@ func fetchMetricFamilies(url string, ch chan<- *dto.MetricFamily) {
for { for {
mf := &dto.MetricFamily{} mf := &dto.MetricFamily{}
if err = protodelim.UnmarshalFrom(reader, mf); err != nil { if err = protodelim.UnmarshalFrom(reader, mf); err != nil {
if err == io.EOF { if errors.Is(err, io.EOF) {
break break
} }
return return

View File

@@ -53,7 +53,7 @@ func sendNotify(c *dns.Client, m *dns.Msg, s string) error {
} }
} }
if err != nil { 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)) return fmt.Errorf("notify for zone %q was not accepted by %q: rcode was %q", m.Question[0].Name, s, rcode.ToString(code))
} }

View File

@@ -94,7 +94,7 @@ func (t *Transfer) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Ms
var err error var err error
for _, p := range t.Transferers { for _, p := range t.Transferers {
pchan, err = p.Transfer(state.Name(), serial) 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 // plugin was not authoritative for the zone, try next plugin
continue continue
} }

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"errors"
"time" "time"
"github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin"
@@ -56,10 +57,10 @@ func (t *TSIGServer) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.
if tsigStatus != nil { if tsigStatus != nil {
log.Debugf("TSIG validation failed: %v %v", dns.TypeToString[state.QType()], tsigStatus) log.Debugf("TSIG validation failed: %v %v", dns.TypeToString[state.QType()], tsigStatus)
rcode = dns.RcodeNotAuth rcode = dns.RcodeNotAuth
switch tsigStatus { switch {
case dns.ErrSecret: case errors.Is(tsigStatus, dns.ErrSecret):
tsigRR.Error = dns.RcodeBadKey tsigRR.Error = dns.RcodeBadKey
case dns.ErrTime: case errors.Is(tsigStatus, dns.ErrTime):
tsigRR.Error = dns.RcodeBadTime tsigRR.Error = dns.RcodeBadTime
default: default:
tsigRR.Error = dns.RcodeBadSig tsigRR.Error = dns.RcodeBadSig

View File

@@ -57,7 +57,7 @@ func TestServeDNS_DelegatesToNext(t *testing.T) {
if gotCode != wantCode { if gotCode != wantCode {
t.Fatalf("rcode: got %d, want %d", 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) t.Fatalf("error: got %v, want %v", gotErr, wantErr)
} }
} }

View File

@@ -2,6 +2,7 @@ package whoami
import ( import (
"context" "context"
"errors"
"testing" "testing"
"github.com/coredns/coredns/plugin/pkg/dnstest" "github.com/coredns/coredns/plugin/pkg/dnstest"
@@ -63,7 +64,7 @@ func TestWhoami(t *testing.T) {
req.SetQuestion(dns.Fqdn(tc.qname), tc.qtype) req.SetQuestion(dns.Fqdn(tc.qname), tc.qtype)
rec := dnstest.NewRecorder(&test.ResponseWriter{RemoteIP: tc.remote}) rec := dnstest.NewRecorder(&test.ResponseWriter{RemoteIP: tc.remote})
code, err := wh.ServeDNS(ctx, rec, req) 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) t.Errorf("Test %d: Expected error %v, but got %v", i, tc.expectedErr, err)
} }
if code != tc.expectedCode { if code != tc.expectedCode {

View File

@@ -110,7 +110,7 @@ func getBucketCount(mf *test.MetricFamily, bucketLabel string) (int, error) {
count, err := strconv.Atoi(countStr) count, err := strconv.Atoi(countStr)
if err != nil { 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 return count, nil
} }
@@ -126,11 +126,11 @@ func extractRequestSizeBucketCounts(t *testing.T, metrics []*test.MetricFamily,
t.Logf(" %s: %v", mf.Name, mf.Metrics) t.Logf(" %s: %v", mf.Name, mf.Metrics)
countBelow100, err = getBucketCount(mf, "100") countBelow100, err = getBucketCount(mf, "100")
if err != nil { 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") countAbove100, err = getBucketCount(mf, "1023")
if err != nil { 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 return countBelow100, countAbove100, nil
} }

View File

@@ -1,6 +1,7 @@
package test package test
import ( import (
"errors"
"testing" "testing"
"time" "time"
@@ -62,7 +63,7 @@ func TestTsigBadKey(t *testing.T) {
client := dns.Client{Net: "udp", TsigSecret: map[string]string{"bad.key.": tsigSecret}} client := dns.Client{Net: "udp", TsigSecret: map[string]string{"bad.key.": tsigSecret}}
r, _, err := client.Exchange(m, udp) 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) t.Fatalf("Expected \"dns: bad authentication\" error, got: %s", err)
} }
if r.Rcode != dns.RcodeNotAuth { 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="}} client := dns.Client{Net: "udp", TsigSecret: map[string]string{tsigKey: "BADSIG00ECfVZG2qCjr4mPpaGim/Bq+IWMiNrLjUO4Y="}}
r, _, err := client.Exchange(m, udp) 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) t.Fatalf("Expected \"dns: bad authentication\" error, got: %s", err)
} }
if r.Rcode != dns.RcodeNotAuth { 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}} client := dns.Client{Net: "udp", TsigSecret: map[string]string{tsigKey: tsigSecret}}
r, _, err := client.Exchange(m, udp) 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) t.Fatalf("Expected \"dns: bad authentication\" error, got: %s", err)
} }
if r.Rcode != dns.RcodeNotAuth { if r.Rcode != dns.RcodeNotAuth {