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

@@ -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()

View File

@@ -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)
}

View File

@@ -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() {

View File

@@ -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 {

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)
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)

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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.

View File

@@ -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")
}

View File

@@ -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

View File

@@ -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:

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}
}

View File

@@ -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
}

View File

@@ -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()

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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
}

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 {
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

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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

View File

@@ -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))
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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 {